Коротко о сути того, что нужно было сделать.
Один корпоративный сайт, находящийся вне нашего филиала, доступен через интернет и по корпоративной сети. В интернете этот сайт имеет белый IP, а в корпоративной сети - серый. Соответственно трафик по интернет-сети оплачивается помегабайтно, а по корпоративной сети бесплатен.
Пользователи, подключающиеся по VPN к нашей сети имеют два DNS, один - провайдера, второй выдаётся VPN-сервером. Провайдерский DNS возвращает белый IP этого сайта, поэтому VPN-клиенты пытаются обращаться к сайту именно по белому IP. Нужно, чтобы они обращались по серому IP.
Отказаться от провайдерского DNS сложновато: он выдаётся автоматом и используется для установки соединения с VPN-сервером по его имени.
Был придуман костыль: на VPN-сервере настроить DNAT, чтобы заменять белый IP на серый.
Под Linux и iptables это настраивается элементарно, однако с FreeBSD, ipfw и natd пришлось немного попариться.
В итоге получились следующие правила, с дополнительным экземпляром natd:
${fwcmd} add divert 7667 tcp from VPN_сеть to белый_IP 443 ${fwcmd} add divert 7667 tcp from серый_IP 443 to VPN_сеть ${natd} -p 7667 -n интерфейс_серый -redirect_port tcp серый_IP:443 белый_IP:443
Суть правил в следующем:
В первом правиле отбираются пакеты, идущие от VPN-клиентов к белому IP корпоративного сервера и отправляются в специально обученный natd.
Во втором правиле отбираются ответные пакеты, то есть идущие от серого IP корпоративного сервера к VPN-клиентам и тоже направляются в специально обученный экземпляр natd.
В третьей строчке запускается специально обученный экземпляр natd. Он заменяет адрес назначения с белого на серый IP у пакетов, идущих от VPN-клиентов к корпоративному сайту. Для возвратных пакетов, идущих от корпоративного сайта к VPN-клиентам, осуществляется обратное преобразование, адрес корпоративного сайта с серым IP заменяется на адрес с белым IP.