Paramiko: переадресация портов вокруг маршрутизатора NAT
конфигурация
- ЛОКАЛЬНЫЙ: Локальный компьютер, который создаст ssh-соединение и выдаст команды в удаленном окне.
- ПРОКСИ: Экземпляр EC-2 с ssh-доступом к ЛОКАЛЬНОМУ и УДАЛЕННОМУ.
- УДАЛЕННЫЙ: удаленный компьютер, расположенный за NAT-маршрутизатором (недоступен LOCAL, но откроет соединение с PROXY и позволит LOCAL туннелировать к нему).
Шаги по переадресации портов (через командную строку)
Создайте соединение ssh от REMOTE до PROXY для пересылки трафика ssh через порт 22 на REMOTE-машине на порт 8000 на сервере PROXY.
# Бег от УДАЛЕННОЙ машины
ssh -N -R 0.0.0.0:8000:localhost:22 PROXY_USER@PROXY_HOSTNAMEСоздайте ssh-туннель из LOCAL в PROXY и перенаправьте ssh-трафик из LOCAL:1234 в PROXY:8000 (который затем пересылается в REMOTE: 22).
# Запуск от ЛОКАЛЬНОЙ машины
ssh -L 1234: локальный хост:8000 PROXY_USER@PROXY_HOSTNAMEСоздайте переадресованное соединение ssh от LOCAL до REMOTE (через PROXY).
# Запустить с ЛОКАЛЬНОЙ машины в новом окне терминала
ssh -p 1234 REMOTE_USER @ localhost# Теперь у меня есть ssh'd для удаленного окна и могу запускать команды
Paramiko Research
Я рассмотрел несколько вопросов, связанных с переадресацией портов с использованием 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')
2 ответа
Подробное объяснение того, что Paramiko делает "под капотом", можно найти в блоге @bitprohet здесь.
Предполагая конфигурацию выше, код, который я работаю, выглядит примерно так:
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')
Является ли смысл только отказов SSH-команд от PROXY или вам нужно перенаправлять и другие, не SSH-порты тоже?
Если вам просто нужно подключить SSH к блоку REMOTE, Paramiko поддерживает как шлюзы уровня SSH (сообщает PROXY sshd открыть соединение с REMOTE и пересылать трафик SSH от имени LOCAL), так и поддержку ProxyCommand (перенаправляет весь трафик SSH через локальную команду, который может быть чем угодно, способным общаться с удаленной коробкой).
Звучит так, будто вы хотите первое для меня, поскольку в PROXY уже работает sshd. Если вы посмотрите копию Fabric и поищете "шлюз", вы обнаружите указатели на то, как Fabric использует поддержку Paramiko для шлюзов (у меня нет времени самим раскапывать конкретные места).