2017-01-02 4 views
3

sshuttle claimsdiscussed problemTCP-over-TCP meltdownのように多く解決されています。sshuttleはTCP-over-TCPの呪いをどう回避するのですか?

sshuttleはTCPストリームをローカルに組み立て、sshセッションでステートフルに多重化し、逆アセンブルしてもう一方の端でパケットに戻します。したがって、TCP-over-TCPを実行することは決してありません。これは単なるデータオーバーTCPであり、安全です。

しかし、SSHがまだないので、他のTCPセッションについての階層化され、それに付属しているものすべてとターゲットサーバへのTCP接続を(指数タイムアウトを読んで)維持プログラムの観点から、 udpで作業してください。これはTCP-over-TCPのようなものです。

ここでのトリックとは何ですか?問題は本当にsshuttleによって解決されるのですか?

私はsource codeを読んでみましたが、これまでに答えが見つかりませんでした。

さらに重要なことは、どのように正確に行うのですか?ベアボーンでそれを再実装したい場合、インスピレーションを求めるべき場所は?

答えて

1

sshuttleクライアントは、ローカルポート(デフォルトで12300)に、特定の発信TCP接続をリダイレクトするようにファイアウォールルール(sshuttleクライアントは、root権限を必要とする理由ですLinuxではiptablesの、)設定sshuttleを開始するとき、あなたはこのプロセスを見ることができます: sshuttle終了するが、

>> 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 

TCP内容をピックアップしてssh接続tにわたって多重化され

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 

そして削除iptablesのNATルールo sshuttleサーバに接続し、接続に再度多重化解除します。

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) 

あなたは、データがssnet.pyにパックされてどのように見ることができます:client.py内の関数onaccept_tcpinはマルチプレクサを行います。

redsocksには、SOCKSまたはHTTPSプロキシへのTCP接続のリダイレクトを目的とした同じ戦略(ファイアウォールルールの設定を意味します)があります。

2

ステートメントの通り、ではなく、 TCP-over-TCPです。

これはTCP-オーバー-TCP:外側のTCP接続は、内側TCP接続を介して行われているか

First application 
    First end of outer TCP connection 
    First end of inner TCP connection 
    Datagram/packet link 
    Send end of inner TCP connection 
    Second end of outer TCP connection 
Second application 

お知らせ?内側のTCP接続を介して輸送されるいかなる外側のTCP接続がないことを

First application 
First end of outer TCP connection 
    Outer end of First TCP connection 
    Inner end of First TCP connection 
    Byte stream link 
    Inner end of Second TCP connection 
    Outer end of Second TCP connection 
Second application 

お知らせ:

これは、彼らが何をやっているのですか? TCP-over-TCPはありません。

あなたがそれを行うこと4つの明白な方法があります。

  1. は、すでにシステムに割り当てられたIPアドレスへのTCP接続を行うアプリケーションを誘導します。
  2. アプリケーションが接続しようとしているIPアドレスをシステムに割り当てます。
  3. NATローカルシステム上で実行されているプロセスへのアウトバウンドTCP接続。 (jfly answerこれは彼らが何をしているかのヒントです)
  4. OSのTCPパケットをあなたにルーティングさせ、ユーザ空間のTCPの実装でそれを終了させます。
+0

これは素晴らしい説明です。しかし、彼らはそれをいかに正確にしていますか? – sanmai

+1

どちらが分かりませんか?私の図からわかるように、各アプリケーションはバイトストリームリンクの一端に完全にローカルなTCP接続を持っています。 –

+0

カーネルが最初の接続を「終了」してカーネルがそれを気にかけなくなるのはどうですか?更新された質問を参照してください – sanmai

関連する問題