Подтвердить что ты не робот

Парамико: перенаправление портов вокруг NAT-маршрутизатора

Конфигурация

  • LOCAL: Локальный компьютер, который создаст соединение ssh и выдаст команды в поле REMOTE.
  • PROXY: Экземпляр EC-2 с доступом ssh к LOCAL и REMOTE.
  • REMOTE: Удаленная машина, сидящая за NAT-маршрутизатором (недоступна LOCAL, но откроет соединение с PROXY и разрешит LOCAL туннелировать его).

Шаги переадресации портов (через командную строку)

  • Создайте соединение ssh с REMOTE на PROXY, чтобы перенаправить ssh-трафик на порт 22 на машине REMOTE на порт 8000 на сервере PROXY.

    # Запуск с машины REMOTE
    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: localhost: 8000 PROXY_USER @PROXY_HOSTNAME

  • Создайте перенаправленное ssh-соединение с LOCAL на REMOTE (через PROXY).

    # Запуск из LOCAL машины в новом окне терминала
    ssh -p 1234 REMOTE_USER @localhost

    # У меня теперь ssh'd в поле REMOTE и вы можете запускать команды

Исследование Парамико

Я рассмотрел несколько questions, связанных с переадресацией портов с помощью 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')
4b9b3361

Ответ 1

Подробное объяснение того, что 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 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')

Ответ 2

Является ли смысл только отказываться от SSH-команд от PROXY или вам нужно пересылать другие, кроме SSH-портов?

Если вам просто нужно SSH в поле REMOTE, Paramiko поддерживает шлюз SSH-уровня (сообщает PROXY sshd, чтобы открыть соединение с REMOTE и пересылать SSH-трафик на имя LOCAL) и поддержку ProxyCommand (пересылает весь SSH-трафик через локальная команда, которая может быть любой, способной разговаривать с удаленным ящиком).

Похоже, что вы хотите, чтобы первый был для меня, поскольку PROXY явно уже работает с sshd. Если вы проверите копию Fabric и выполните поиск вокруг "шлюза", вы найдете указатели на то, как Fabric использует поддержку шлюза Paramiko (у меня нет времени на то, чтобы самостоятельно расчистить конкретные места).