Возможно, вы когда-нибудь задумывались о том, как на определенной машине под управлением MS Windows перенаправить входящий траффик в другой сетевой интерфейс, на другой адрес и другой порт? Такая возможность есть, называется она portproxy. Сделать это совсем несложно и я объясню как, но сначала — небольшая предыстория.
Наверное, не стоит судить об организации только на основании того, какие у них в ходу решения и технологии, но иной раз так и хочется «навесить ярлык» на очередную фирму. В этот раз история пойдет о крупной транспортной конторе для которой мы сначала делали, а потом интегрировали целый «проект». И, если обычно в цивилизованном мире для предоставления доступа посредством VPN используют решения, такие как SSTP, L2TP/IPsec, OpenVPN или даже WireGuard (т.е.открытые и общедоступные технологии), то некоторых хлебом не корми, дай подложить свинью в виде Cisco Any Connect, GlobalProtect или даже RadminVPN. Наш заказчик использовал именно Cisco Any Connect, причем, отнюдь не ванильное решение — на клиентские машины с Windows поставлялись какие-то явно самопальные, но брендированные дистрибутивы. Была заявлена (формально) поддержка Linux и MacOS, но на поверку поставляемые решения оказались просто-напросто неработоспособными (о чем, как оказалось, заказчик знал, но сообщить не посчитал нужным). Признаюсь, даже на этом этапе во мне еще теплилась надежда, что можно поднять VPN-клиент на роутере (как я обычно поступаю) и красиво маршрутизировать траффик на машины наших разработчиков, работающих удаленно и использующих, в основном, Arch и Ubuntu в качестве операционных систем. Развернув в виртуалке чистую Windows, я установил дистрибутив Cisco Any Connect, после чего попробовал подключиться к серверу заказчика по ранее переданным мне реквизитам. Всплывающее окошко радостно сообщило, что «подключение успешно установлено», однако что-то было явно не так. Присмотревшись внимательнее я увидел, что при подключении к заказчику практически все прежние имеющиеся сетевые маршруты (которые у меня анонсирует роутер) были просто-напросто перекроены. Если бы я установил этот Cisco Any Connect на свою девелоперскую машину, то это был бы тот еще гемморой. В такой ситуации я предпринял самый разумный и логичный шаг, я спросил у заказчика — как вы вообще собираетесь нам предоставлять необходимый доступ? Мы же, дескать, обговаривали вопросы доступа заранее, я вам четко обозначил возможные варианты, вы подтвердили, что проблем не будет. «Проблемы негров шерифа не интересуют» — примерно так ответил заказчик на этот раз. Неприятно, конечно, но я все же пробежался по профильным форумам, посоветовался с несколькими знакомыми — и, к сожалению, все вело к тому, что адекватного решения «здесь и сейчас» нет, нужно тратить определенное количество времени (достаточно ограниченного) без гарантии результата.
Взвесив все «за» и «против» я приступил к организации оперативного решения. Возвращаемся в виртуалку с поднятой Windows и установленным клиентом Cisco Any Connect. Проверяем настройки виртуальной машины, в частности, тип подключения к сети — сетевой мост. В самой Windows видим, что при подключении к заказчику поднимается отдельный интерфейс виртуальной сетевой карты, ему присваивается определенный адрес. Открываем службы, ищем пункт «Вспомогательная служба IP» — меняем тип запуска на «Автоматически», после чего запускаем эту службу. Эта служба, как следует из описания, «Обеспечивает возможность туннельного подключения с помощью технологий туннелирования для IP версии 6 (6to4, ISATAP, порты прокси и Teredo), а также IP-HTTPS», из всего этого перечня нам нужно только проксирование портов.
Теперь открываем командную строку от имени администратора. Пусть у первого адаптера виртуальной машины будет адрес 192.168.0.50, у адаптера Cisco Any Connect 10.0.70.60, а адрес удаленного сервера заказчика — 10.0.77.66 (будем считать, что предварительно мы посмотрели маршруты и на 10.0.77.66 можно попасть через шлюз интерфейса Cisco Any Connect). На текущем этапе наша виртуальная машина смотрит сразу в две сети — нашу основную (и, посколько она подключена бриджем, то мы видем её на роутере наряду с другими компьютерами) и сеть заказчика. Пишем в командной строке следующее:
netsh interface portproxy add v4tov4 listenport=1234 listenaddress=192.168.0.50 connectport=8084 connectaddress=10.0.77.66
Тем самым мы обозначаем, что если на нашу виртуальную машину кто-то постучится извне на порт 1234, то, фактически, он постучится на сервер заказчика 10.0.77.66 на порт 8084. Таким образом мы сделали проксирование не только портов, но получили возможность направлять траффик вообще в другую сеть. Далее, тут же в командной строке проверяем локальный порт 1234:
netstat -na|find "1234"
Если все сделано правильно, то вы увидите, что порт 1234 теперь прослушивается. По образу и подобию можно указать и другие порты для проброса. Просмотреть весь список проброшенных таким образом портов можно следующей командой:
netsh interface portproxy show all
Чтобы удалить отдельное взятое правило, нужно сделать следующее:
netsh interface portproxy delete v4tov4 listenport=1234 listenaddress=192.168.0.50
А чтобы полностью удалить все имеющиеся правила подойдет эта команда:
netsh interface portproxy reset
Общие принципы, я думаю, понятны. Особо стоит отметить, что таким образом можно перенаправлять трафик только для TCP портов. Трафик на UDP порты перенаправить не выйдет, помимо этого нельзя использовать 127.0.0.1 в качестве адреса назначения. Для настройки перенаправления UDP можно использовать Windows Server с ролями RRAS и NAT (помимо командной строки можно будет использовать графическую оснастку rrasmgmt.msc). Официальная документация по portproxy находится здесь.
Моя история закончилась тем, что в роутере я прописал все нужные правила маршрутизации относительно виртуальной машины (которая фактически выступила просто в роли своеобразного прокси для удаленного сервера заказчика), после чего анонсировал новые маршруты: наши разработчики получили весь необходимый доступ к серверу заказчика без необходимости настраивать на своей стороне что-либо.