Show HN: Tunnelling TCP through a file
180 points| fiddyschmitt | 1 year ago |github.com
People have used it for interesting things:
- Bridging connections which would otherwise be blocked by a firewall
- Tunneling through RDP (similar to an SSH tunnel)
- Exposing a localhost web server to others
Key features I put effort into:
1. The shared file is restarted every 10 MB, so it doesn't grow indefinitely.
2. Optimisations for latency & bandwidth. (800 Mbps on a Gigabit LAN. 108 Mbps if file tunneling through RDP)
3. Synchronisation between two sides (each side can be started and restarted in any order)
I'd love to hear about any weird and wonderful uses you might have for it.
Thanks, Fidel
ycombiredd|1 year ago
If that is indeed the case, (I am not a Windows pr SMB expert, so perhaps you will tell me it is not the case and to be clear, I am not asserting that it is or trying to say anything negative; I am just curious and you seem like a pretty likely source to be able to answer the question, since something motivated you to write this tool)
One difference would seem at first brush is that a named pipe used for this would not need to be periodically truncated in 10 minute intervals to prevent runaway file growth. Again, not knocking what you’ve made at all, I’m genuinely curious for the answer.
mr_mitm|1 year ago
_flux|1 year ago
It would presume trusting the permission system over NFS, though.
rakoo|1 year ago
aeonik|1 year ago
fiddyschmitt|1 year ago
rnmmrnm|1 year ago
good thing I needed HTTP access or else i had to find that socks5 server that's actually working again.
aeonik|1 year ago
Do you have a good resource recommendation to learn this more?
fiddyschmitt|1 year ago
dheera|1 year ago
For use on flights where they give you "messenger only" internet access.
Feature request: TCP over JPEG cat pictures on HTTP port 80
It would likely do a better job at circumventing the China firewall than existing VPNs that can be flagged as VPN protocols.
mike_d|1 year ago
They still rate limit these flows to a very low speed.
ranger_danger|1 year ago
You could just sniff the traffic for an already-logged-in MAC and clone it.
DonHopkins|1 year ago
imhoguy|1 year ago
fiddyschmitt|1 year ago
jclarkcom|1 year ago
fiddyschmitt|1 year ago
The key to high performance as you rightly pointed out was preventing flushing. In the end, what worked best was reducing the number of writes to disk (which is the bottleneck). I did that by buffering 10-50 ms worth of TCP data, coupled with only flushing explicitly (using a large buffer so that neither BinaryWriter or FileStream flush automatically).
jclarkcom|1 year ago
import socket import win32pipe import win32file import sys
BUFFER_SIZE = 4096
def create_pipe(pipe_name): return win32pipe.CreateNamedPipe(pipe_name, win32pipe.PIPE_ACCESS_DUPLEX, win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE | win32pipe.PIPE_WAIT, 1, BUFFER_SIZE, BUFFER_SIZE, 0, None)
def open_pipe(pipe_name): return win32file.CreateFile(pipe_name, win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None, win32file.OPEN_EXISTING, 0, None)
def proxy_server(machine_name): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('0.0.0.0', 8080)) server_socket.listen(1)
def proxy_client(server_name, machine_name): target_host, target_port = 'cnn.com', 80 if __name__ == '__main__': if len(sys.argv) < 3: print("Usage: python script.py [server|client] [machine_name] [server_name (for client only)]") sys.exit(1)bawolff|1 year ago
fiddyschmitt|1 year ago
1. It gracefully supports each side of the tunnel turning on and off.
2. It accepts any number of clients, and forwards them through the tunnel.
3. It recycles the shared file.
lambdaxyzw|1 year ago
As for the uses, see the three author listed. For example, by using a file share as transport you may evade firewall.
Thorrez|1 year ago
andrewstuart|1 year ago
Also how does either side know when the file has been updated?
jandrese|1 year ago
fiddyschmitt|1 year ago
Arbitration was indeed one of the trickiest bits. Originally I pre-reallocated the full file size (10 MB). Then used an integer at the beginning of the file to signal to the other side that a block was ready. The other side repeatedly read that int, and read the corresponding part of the file. But writing twice (once for the data, once for the int) had a significant performance impact.
In the end, what worked best was not pre-allocating the file. Rather letting the file grow whenever the writer writes to it. The reader knows when data is available by doing a PeekChar() in a tight loop. It's surprisingly fast, and accurately reflects the state of the file.
resoluteteeth|1 year ago
fiddyschmitt|1 year ago
https://rdp2tcp.sourceforge.net/
coppolafab|1 year ago
[deleted]