Допустим, у нас есть удалённая локальная сеть. Локальная сеть состоит из компьютеров с Windows XP или какого-либо другого сорта Windows. На этих компьютерах разрешено удалённое управление рабочим столом.

Все компьютеры локальной сети выходят в интернет через шлюз на Linux. На нём работает ssh-сервер, через который мы успешно админим собственно сам шлюз, а заодно и другие линуксовые сервера, если они есть. Единственный открытый порт - номер 22 (SSH).

Как в таких условиях подключиться к удалённому рабочему столу произвольного виндового клиента этой сети?

Как вариант, используя доступ по ssh, можно настроить проброс портов на самом шлюзе, например средствами iptables. После чего зайти на внешний адрес по выбранному порту и творить свои ч0рные дела. Главное не забыть потом вернуть таблицы iptables в исходное состояние, чтоб не создавать дополнительные угрозы безопасности.

А можно использовать средства самого ssh.

Подключение к одному компьютеру

Делаем в консоли:

ssh user@$EXT_IP -L 3389:$LAN_IP:3389

Здесь:
user - пользователь на шлюзе с правом подключения по ssh
$EXT_IP - внешний IP-адрес шлюза
$LAN_IP - IP-адрес целевого компьютера в локальной сети
3389 - порт протокола RDP (протокола удалённого рабочего стола)

После ввода команды окажемся в консоли шлюза, как будто ключ -L и не использовали. Теперь открываем у себя любой клиент терминального сервера (tsclient, rdesktop и т.д.) и подключаемся к адресу localhost (!).

Почему так?

После ввода команды все подключения к нашему локальному адресу на порт 3389 будут отправляться в ssh, а на той стороне переправляться на адрес $LAN_IP и на тот же порт 3389. Поэтому попытка подключения к localhost по RDP приведёт к тому, что мы окажемся на целевой машине в удалённой сети.

Пример для закрепления

Внешний адрес шлюза - 194.87.0.50. В локальной сети 192.168.1.0/24 нас интересует доступ по RDP (порт 3389) к компьютеру с адресом 192.168.1.111. Но на своей стороне мы хотим использовать порт 1234! Делаем так:

ssh user@194.87.0.50 -L 1234:192.168.1.111:3389

После попадания в консоль шлюза подключаемся нашим терминальным клиентом на адрес localhost:1234. Всё, мы на месте.

Одновременное подключение к нескольким удалённым компьютерам

Иногда бывает необходимо держать одновременно несколько удалённых подключений.

user - пользователь на шлюзе
$EXT_IP - внешний IP-адрес шлюза
$LAN_IP1 - IP-адрес первого компьютера в локальной сети
$LAN_IP2 - IP-адрес второго компьютера в локальной сети

Вариант 1. Разные локальные порты

В первой локальной консоли:

ssh user@$EXT_IP -L 1234:$LAN_IP1:3389

Во второй локальной консоли:

ssh user@$EXT_IP -L 5432:$LAN_IP2:3389

Теперь при подключении к localhost:1234 мы попадём на первый компьютер, к localhost:5432 - на второй.

Играясь с портами надо быть предельно внимательным: если у нас стоит PostgreSQL, то в последнем примере он отвалится, потому что сидит как раз на 5432 порту. Запросы к нему будут долбиться в RDP $LAN_IP2.

Вариант 2. Разные локальные интерфейсы

Полная запись параметров ключа -L такая:

-L [наш_адрес]:[наш_порт]:[удалённый_адрес]:[удалённый_порт]

То есть нашим адресом может быть не только localhost, а вообще произвольный.

Поднимаем виртуальный сетевой интерфейс и делаем ssh-канал через него:

ifconfig eth0:0 $ANY_IP up
ssh user@$EXT_IP -L $ANY_IP:3389:$LAN_IP2:3389

$ANY_IP - любой IP-адрес

Теперь надо следить, чтоб не законфликтовали айпи адреса :). Для подключения к удалённому рабочему столу используем $ANY_IP.

Можно использовать виртуальный интерфейс eth0:0 с IP-аресом $ANY_IP для всех удалённых подключений, разделяя их номерами портов.

Понятно, что варьируя целевой порт можно подключаться не только к рабочему столу, но и к другим удалённым службам. RDP был взят просто как наиболее понятный пример.

P.S. Огромная благодарность Евгению Короткову за пинки в правильном направлении.