Допустим, у нас есть удалённая локальная сеть. Локальная сеть состоит из компьютеров с Windows XP или какого-либо другого сорта Windows. На этих компьютерах разрешено удалённое управление рабочим столом.
Все компьютеры локальной сети выходят в интернет через шлюз на Linux. На нём работает ssh-сервер, через который мы успешно админим собственно сам шлюз, а заодно и другие линуксовые сервера, если они есть. Единственный открытый порт - номер 22 (SSH).
Как в таких условиях подключиться к удалённому рабочему столу произвольного виндового клиента этой сети?
Как вариант, используя доступ по ssh, можно настроить проброс портов (http://www.it-simple.ru/?p=2250) на самом шлюзе, например средствами 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-адрес второго компьютера в локальной сети
В первой локальной консоли:
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.
Полная запись параметров ключа -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. Огромная благодарность Евгению Короткову за пинки в правильном направлении.