【问题标题】:Paramiko: Port Forwarding Around A NAT RouterParamiko:NAT 路由器周围的端口转发
【发布时间】:2013-09-28 20:52:40
【问题描述】:

配置

  • LOCAL:将创建 ssh 连接并在 REMOTE 机器上发出命令的本地计算机。
  • 代理:一个 EC-2 实例,可以通过 ssh 访问 LOCAL 和 REMOTE。
  • REMOTE: 位于 NAT 路由器后面的远程机器(LOCAL 无法访问,但会打开与 PROXY 的连接并允许 LOCAL 与它建立隧道)。

端口转发步骤(通过命令行)

  1. 创建从 REMOTE 到 PROXY 的 ssh 连接,以将 REMOTE 机器上 22 端口上的 ssh 流量转发到 PROXY 服务器上的 8000 端口。

    # 从远程机器运行
    ssh -N -R 0.0.0.0:8000:localhost:22 PROXY_USER@PROXY_HOSTNAME

  2. 创建从 LOCAL 到 PROXY 的 ssh 隧道,并将 ssh 流量从 LOCAL:1234 转发到 PROXY:8000(然后转发到 REMOTE:22)。

    # 从本地机器运行
    ssh -L 1234:localhost:8000 PROXY_USER@PROXY_HOSTNAME

  3. 创建从 LOCAL 到 REMOTE 的转发 ssh 连接(通过 PROXY)。

    # 在新的终端窗口中从本地机器运行
    ssh -p 1234 REMOTE_USER@localhost

    # 我现在已经 ssh'd 到 REMOTE 框并且可以运行命令了

帕拉米科研究

我查看了questions 中的handful 与使用 Paramiko 进行端口转发相关,但他们似乎没有解决这种特定情况。

我的问题

如何使用 Paramiko 运行上述第 2 步和第 3 步?我基本上想跑:

import paramiko

# Create the tunnel connection
tunnel_cli = paramiko.SSHClient()
tunnel_cli.connect(PROXY_HOSTNAME, PROXY_PORT, PROXY_USER)

# Create the forwarded connection and issue commands from LOCAL on the REMOTE box
fwd_cli = paramiko.SSHClient()
fwd_cli.connect('localhost', LOCAL_PORT, REMOTE_USER)
fwd_cli.exec_command('pwd')

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    可以在@bitprohet's blog here 找到有关 Paramiko 在“幕后”所做的事情的详细说明。

    假设上面的配置,我工作的代码看起来像这样:

    from paramiko import SSHClient
    
    # Set up the proxy (forwarding server) credentials
    proxy_hostname = 'your.proxy.hostname'
    proxy_username = 'proxy-username'
    proxy_port = 22
    
    # Instantiate a client and connect to the proxy server
    proxy_client = SSHClient()
    proxy_client.load_host_keys('~/.ssh/known_hosts/')
    proxy_client.connect(
        proxy_hostname,
        port=proxy_port,
        username=proxy_username,
        key_filename='/path/to/your/private/key/'
    )
    
    # Get the client's transport and open a `direct-tcpip` channel passing
    # the destination hostname:port and the local hostname:port
    transport = proxy_client.get_transport()
    dest_addr = ('0.0.0.0', 8000)
    local_addr = ('127.0.0.1', 1234)
    channel = transport.open_channel("direct-tcpip", dest_addr, local_addr)
    
    # Create a NEW client and pass this channel to it as the `sock` (along with
    # whatever credentials you need to auth into your REMOTE box
    remote_client = SSHClient()
    remote_client.load_host_keys(hosts_file)
    remote_client.connect('localhost', port=1234, username='remote_username', sock=channel)
    
    # `remote_client` should now be able to issue commands to the REMOTE box
    remote_client.exec_command('pwd')
    

    【讨论】:

    • 确实是史诗。谢谢!!
    • 我相信代码中存在冗余。如果指定sock,则hostnameport 将被忽略(毕竟它已经是频道的一部分了)。
    【解决方案2】:

    只是将 SSH 命令从 PROXY 中反弹回来,还是您还需要转发其他非 SSH 端口?

    如果您只需要通过 SSH 进入 REMOTE 框,Paramiko 支持 SSH 级网关(告诉 PROXY sshd 打开到 REMOTE 的连接并代表 LOCAL 转发 SSH 流量)和 ProxyCommand 支持(通过本地命令,可以是任何能够与远程机器对话的命令)。

    听起来你想要前者,因为 PROXY 显然已经有一个 sshd 正在运行。如果您查看 Fabric 的副本并四处搜索“网关”,您会发现 Fabric 如何使用 Paramiko 的网关支持的指针(我现在没有时间自己挖掘具体的位置。)

    【讨论】:

      猜你喜欢
      • 2016-04-23
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多