2012-05-07 84 views
1

我正在修改Python腳本以獨立於操作系統,並在Windows上運行。我已將其ssh系統調用更改爲調用paramiko函數。我堅持使用http代理身份驗證的問題。在UNIX(實際上Cygwin的)環境中我會使用的〜/ .ssh/config中如何在Python中通過http代理ssh?

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

有沒有一種方法來獲得使用的paramiko相同(或Python的SSH模塊)或者使用或不使用開瓶器? This post似乎表明,但我不知道如何。

注意:我在防火牆後面允許我只使用端口80.我需要控制Amazon ec2實例,因此我在這些機器上配置了sshd服務器以偵聽端口80.一切工作正常,在我的cygwin +開瓶器原型,但我想有一個Python腳本,沒有Cygwin的作品。

回答

1

paraproxy,它實現Paramiko的代理支持。

您鏈接到建議,Paramiko可以在任意套接字上運行的帖子,但似乎並非如此。事實上,paraproxy通過完成替換paramiko內的特定方法來工作,因爲現有代碼只需調用socket.socket()即可獲取套接字,並且不提供任何掛接代理的方式。

+0

該OP要求Windows支持,但根據Paraproxy 1.2自述:可移植性 Paraproxy需要unix域套接字來做它的魔力。 因此,支持僅適用於Linux和MacOS (這可能會根據對Win32支持的需求而改變)。 –

+0

它仍然演示了一種用代理支持修補Paramiko的技術。希望有人會有更好的答案。 – larsks

4

您可以通過SSHClient.connect(hostname,username,password,...,sock)中的sock參數將任何預先建立的會話使用到paramiko。

下面是通過HTTP-Proxy-Tunnel(HTTP-CONNECT)隧道SSH的代碼片段。首先建立與代理的連接,並指示代理連接到本地主機:22。結果是建立會話上的TCP隧道通常用於隧道SSL,但可用於任何基於tcp的協議。

此方案適用於默認安裝tinyproxy,其中Allow <yourIP>ConnectPort 22設置爲/etc/tinyproxy.conf。在我的例子中,代理和sshd在同一主機上運行,​​但所有您需要的是允許您將CONNECT加入到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 

hereare一些其他資源如何通過代理隧道。只需做任何需要建立你的隧道,並通過套接字SSHClient.connect(...,sock)