2

OSに依存せず、Windowsで実行されるようにPythonスクリプトを適応させています。その ssh システム コールをparamiko関数の呼び出しに変更しました。http プロキシ認証の問題で立ち往生しています。Unix (実際には Cygwin) 環境では ~/.ssh/config を使用します

Host *
    ProxyCommand corkscrew http-proxy.example.com 8080 %h %p

コルクスクリューを使用するかどうかに関係なく、paramiko (または Python ssh モジュール) を使用して同じものを取得する方法はありますか? この投稿はそれを示唆しているようですが、方法がわかりません。

注: ポート 80 のみを使用できるファイアウォールの背後にいます。Amazon ec2 インスタンスを制御する必要があるため、それらのマシンの sshd サーバーをポート 80 をリッスンするように構成しました。cygwin+corkscrew プロトタイプではすべて正常に動作していますが、 Cygwin なしで動作する Python スクリプトが必要です。

4

2 に答える 2

8

sockのパラメーターを介して、事前に確立されたセッションを paramiko に使用できますSSHClient.connect(hostname,username,password,...,sock)

以下は、HTTP-Proxy-Tunnel (HTTP-CONNECT) 経由で SSH をトンネリングするコード スニペットです。最初にプロキシへの接続が確立され、プロキシは localhost:22 に接続するように指示されます。その結果、確立されたセッションを介した TCP トンネルが作成されます。これは通常、SSL のトンネリングに使用されますが、任意の tcp ベースのプロトコルに使用できます。

tinyproxyこのシナリオは、 withAllow <yourIP>およびConnectPort 22で設定されているのデフォルト インストールで機能します/etc/tinyproxy.confCONNECT私の例では、プロキシと sshd は同じホストで実行されていますが、必要なのは、ssh ポートにアクセスできるプロキシだけです。通常、これはポート 443 に制限されています (ヒント: sshd を 443 でリッスンする場合、相互運用性とセキュリティ上の理由からこれを行うことはお勧めしませんが、ほとんどのパブリック プロキシで動作します)。これにより最終的にファイアウォールをバイパスできるかどうかは、採用されているファイアウォールの種類によって異なります。DPI/SSL インターセプション機能が含まれていない場合は、問題ありません。SSL インターセプションが関係している場合でも、ssl 経由または HTTP ペイロードの一部としてトンネリングを試みることができます:)

import paramiko
import socket
import logging

logging.basicConfig(loglevel=logging.DEBUG)
LOG = logging.getLogger("xxx")

def http_proxy_tunnel_connect(proxy, target,timeout=None):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        sock.connect(proxy)
        LOG.debug("connected")
        cmd_connect = "CONNECT %s:%d HTTP/1.1\r\n\r\n"%target
        LOG.debug("--> %s"%repr(cmd_connect))
        sock.sendall(cmd_connect)
        response = []
        sock.settimeout(2) # quick hack - replace this with something better performing.
        try: 
            # in worst case this loop will take 2 seconds if not response was received (sock.timeout)
            while True:
                chunk = sock.recv(1024)
                if not chunk: # if something goes wrong
                    break
                response.append(chunk)
                if "\r\n\r\n" in chunk: # we do not want to read too far ;)
                    break
        except socket.error, se:
            if "timed out" not in se:
                response=[se]
        response = ''.join(response)
        LOG.debug("<-- %s"%repr(response))
        if not "200 connection established" in response.lower():
            raise Exception("Unable to establish HTTP-Tunnel: %s"%repr(response))
        return sock

if __name__=="__main__":
    LOG.setLevel(logging.DEBUG)
    LOG.debug("--start--")
    sock = http_proxy_tunnel_connect(proxy=("192.168.139.128",8888), 
                                     target=("192.168.139.128",22),
                                     timeout=50)
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname="192.168.139.128",sock=sock, username="xxxx", password="xxxxx")
    print "#> whoami \n%s"% ssh.exec_command("whoami")[1].read()

出力:

DEBUG:xxx:--start--
DEBUG:xxx:connected
DEBUG:xxx:--> 'CONNECT 192.168.139.128:22 HTTP/1.1\r\n\r\n'
DEBUG:xxx:<-- 'HTTP/1.0 200 Connection established\r\nProxy-agent: tinyproxy/1.8.3\r\n\r\n'
#> whoami 
root

プロキシをトンネリングする方法に関するその他のリソースを次に示しますトンネルを確立してソケットを渡すために必要なことは何でもするだけですSSHClient.connect(...,sock)

于 2015-11-17T21:20:56.543 に答える
1

Paramikoのプロキシ サポートを実装する paraproxy があります。

あなたがリンクした投稿は、Paramiko が任意のソケットで操作できることを示唆していますが、そうではないようです。実際、paramiko 内の特定のメソッドを完全に置き換えることで paraproxy が機能します。これは、既存のコードsocket.socket()がソケットを取得するために呼び出すだけで、プロキシにフックする方法を提供していないためです。

于 2012-05-07T21:27:57.920 に答える