san*_*mai 7 networking tcp congestion-control
sshuttle 声称它解决了很多讨论过的TCP-over-TCP 崩溃问题。
sshuttle 在本地组装 TCP 流,通过 ssh 会话有状态地多路复用它,然后在另一端将其分解回数据包。所以它永远不会做 TCP-over-TCP。它只是通过 TCP 传输的数据,这是安全的。
但是从程序的角度来看,它维护与目标服务器的 TCP 连接及其附带的所有内容(读取指数超时),这是与其他 TCP 会话分层的,因为 SSH 还不能仅在udp. 这很像 TCP-over-TCP。
这里的诀窍是什么?问题真的通过sshuttle解决了吗?
我尝试阅读源代码,但到目前为止还没有找到答案。
更重要的是,他们究竟是如何做到的?如果想在准系统中重新实现它,应该从哪里寻找灵感?
sshuttle客户端设置防火墙规则(Linux 中的 iptables,这就是sshuttle客户端需要 root 权限的原因)将某些传出 TCP 连接重定向到本地端口(默认为 12300),您可以在启动 sshuttle 时看到此过程:
firewall manager: starting transproxy.
>> iptables -t nat -N sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -I OUTPUT 1 -j sshuttle-12300
>> iptables -t nat -I PREROUTING 1 -j sshuttle-12300
>> iptables -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.0/8 -p tcp
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 0.0.0.0/0 -p tcp --to-ports 12300 -m ttl ! --ttl 42
Run Code Online (Sandbox Code Playgroud)
并在 sshuttle 退出时删除 iptables nat 规则,
>> iptables -t nat -D OUTPUT -j sshuttle-12300
>> iptables -t nat -D PREROUTING -j sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -X sshuttle-12300
Run Code Online (Sandbox Code Playgroud)
TCP 内容被拾取并通过 ssh 连接多路复用到sshuttle服务器,然后再次多路分解为连接。client.pyonaccept_tcpin中的函数执行复用:
def onaccept_tcp(listener, method, mux, handlers):
global _extra_fd
try:
sock, srcip = listener.accept()
except socket.error as e:
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
debug1('Rejected incoming connection: too many open files!\n')
# free up an fd so we can eat the connection
os.close(_extra_fd)
try:
sock, srcip = listener.accept()
sock.close()
finally:
_extra_fd = os.open('/dev/null', os.O_RDONLY)
return
else:
raise
dstip = method.get_tcp_dstip(sock)
debug1('Accept TCP: %s:%r -> %s:%r.\n' % (srcip[0], srcip[1],
dstip[0], dstip[1]))
if dstip[1] == sock.getsockname()[1] and islocal(dstip[0], sock.family):
debug1("-- ignored: that's my address!\n")
sock.close()
return
chan = mux.next_channel()
if not chan:
log('warning: too many open channels. Discarded connection.\n')
sock.close()
return
mux.send(chan, ssnet.CMD_TCP_CONNECT, b'%d,%s,%d' %
(sock.family, dstip[0].encode("ASCII"), dstip[1]))
outwrap = MuxWrapper(mux, chan)
handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
expire_connections(time.time(), mux)
Run Code Online (Sandbox Code Playgroud)
您可以在ssnet.py中看到数据是如何打包的。
我在redsocks中看到了相同的策略(我的意思是设置防火墙规则),旨在将任何 TCP 连接重定向到 SOCKS 或 HTTPS 代理。
| 归档时间: |
|
| 查看次数: |
1732 次 |
| 最近记录: |