Редко, но метко в моей практике возникает задача, когда нужно быстро поднять сервер с «белым ip» для демонстрации результатов работы или просто для целей тестирования нового функционала перед выкатыванием его в продакшен. Каждый раз арендовать
Поскольку локально я располагаю достаточным количеством практически даровых ресурсов, то мне нужно организовать временный сервер локально, а ip адрес прокинуть с любого внешнего сервера.
Чтобы решить задачу наиболее общим способом были пославлены следующие цели:
- получить на тестовом сервере (srv-test), который находится за NAT, ip адрес, который доступен извне;
- на тестовом сервере не должно быть артефактов реализации.
После небольшой пробежки по поисковикам я так и не нашел решение, которое устроило бы меня целиком. Потому пришлось планировать решение самостоятельно. После прикидывания различных вариантов получился VPN туннель с двойным NAT
На внешнем сервере был запущен минимальный openvz контейнер, в котором крутится только openvpn. Чтобы отличать этот контейнер от других серверов, я буду называеть его srv-ovpn.
Первичный IP адрес контейнера — 212.78.101.113 — он же по совместительству «белый» ip, по которому должен быть доступен тестовый сервер (буду называть его srv-test) из интернета. Также у srv-ovpn есть дополнительный ip адрес 212.78.101.114 — на этот адрес подключается VPN клиент. В принципе от второго адреса можно отказаться, если немного усложнить policy routing, но у меня были свободные ip и было лениво заморачиваться с подобной экономией.
Адрес шлюза, через который сервер виртуальных машин подключен к интернету — 93.100.17.39. Чтобы srv-ovpn не светил подключение для всех — закрываю его на файерволе
root@srv-ovpn # iptables -A INPUT -p udp -s 93.100.17.39 --dport 1194 -j ACCEPT
root@srv-ovpn # iptables -A INPUT -p udp --dport 1194 -j REJECT
root@srv-ovpn # iptables-save > /etc/sysconfig/iptables
Теперь OpenVPN сервер доступен только для меня и надежно скрыт от посторонних глаз.
Далее поднимаю на локальном сервере виртуалок (назову этот сервера — srv-virt) VPN соединение до openvz контейнера srv-ovpn:
root@srv-virt # service openvpn start vpntunnel
После окончания инициализации появился новый интерфейс tun0, который получил адрес 10.117.9.6. Второй конец туннеля имеет адрес 10.117.9.1. Сетевой адаптер, входящий в VLAN srv-test, виден на сервере srv-virt с именем veth3 и имеет адрес 212.78.101.112.
Чтобы автоматизировать процесс настройки VPN соединения я использовал скрипт /etc/openvpn/vpntunnel.sh, который вызывается OpenVPN при инициализации/деинициализации VPN интерфейса.
#!/bin/sh
TUN_DEV="$2"
TUN_IP="$5"
REMOTE_IP="212.78.101.113"
IPR_BIN="/bin/ip"
IPT_BIN="/sbin/iptables"
if [ ! -r /etc/iproute2/rt_tables ]; then
echo "File not found: /etc/iproute2/rt_tables"
echo "iproute2 package must be installed"
exit 1
fi
case $1 in
start)
grep -q '^100tvpntunnel' /etc/iproute2/rt_tables || echo '100tvpntunnel' >> /etc/iproute2/rt_tables
${IPR_BIN} rule add from ${REMOTE_IP} table vpntunnel
${IPR_BIN} route add default via ${TUN_IP} dev ${TUN_DEV} table vpntunnel
${IPR_BIN} route flush cache
${IPT_BIN} -t nat -A PREROUTING -d ${TUN_IP} -j DNAT --to-destination ${REMOTE_IP}
${IPT_BIN} -t nat -A POSTROUTING -o ${TUN_DEV} -j SNAT --to-source ${TUN_IP}
;;
stop)
${IPT_BIN} -t nat -D PREROUTING -d ${TUN_IP} -j DNAT --to-destination ${REMOTE_IP}
${IPT_BIN} -t nat -D POSTROUTING -o ${TUN_DEV} -j SNAT --to-source ${TUN_IP}
${IPR_BIN} route del default via ${TUN_IP} dev ${TUN_DEV} table vpntunnel
${IPR_BIN} route flush cache
${IPR_BIN} rule del from ${REMOTE_IP} table vpntunnel
;;
*)
echo "Incorrect usage"
exit 1
esac
В конфиг VPN соединения нужно добавить вызов скрипта
...
up "/etc/openvpn/vpntunnel.sh start"
down "/etc/openvpn/vpntunnel.sh stop"
down-pre
...
Аналогичный конфиг OpenVPN должен быть и на сервере srv-ovpn.
Осталось настроить на сервере srv-test адрес 212.78.101.113/31 со шлюзом 212.78.101.112 и все должно заработать.
В этом посте все ip адреса и названия серверов заменены на вымышленные и любое совпадение с реальными — случайность.
Автор: tataranovich