Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

python - Paramiko: Port Forwarding Around A NAT Router

Configuration

  • LOCAL: A local machine that will create an ssh connection and issue commands on a REMOTE box.
  • PROXY: An EC-2 instance with ssh access to both LOCAL and REMOTE.
  • REMOTE: A remote machine sitting behind a NAT Router (inaccessible by LOCAL, but will open a connection to PROXY and allow LOCAL to tunnel to it).

Port Forwarding Steps (via command line)

  1. Create an ssh connection from REMOTE to PROXY to forward ssh traffic on port 22 on the REMOTE machine to port 8000 on the PROXY server.

    # Run from the REMOTE machine
    ssh -N -R 0.0.0.0:8000:localhost:22 PROXY_USER@PROXY_HOSTNAME

  2. Create an ssh tunnel from LOCAL to PROXY and forward ssh traffic from LOCAL:1234 to PROXY:8000 (which then forwards to REMOTE:22).

    # Run from LOCAL machine
    ssh -L 1234:localhost:8000 PROXY_USER@PROXY_HOSTNAME

  3. Create the forwarded ssh connection from LOCAL to REMOTE (via PROXY).

    # Run from LOCAL machine in a new terminal window
    ssh -p 1234 REMOTE_USER@localhost

    # I have now ssh'd to the REMOTE box and can run commands

Paramiko Research

I have looked at a handful of questions related to port forwarding using Paramiko, but they don't seem to address this specific situation.

My Question

How can I use Paramiko to run steps 2 and 3 above? I essentially would like to run:

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')
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A detailed explanation of what Paramiko is doing "under the hood" can be found at @bitprohet's blog here.

Assuming the configuration above, the code I have working looks something like this:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...