«Телепортируем» белый ip-адрес на другой сервер при помощи pptp.
Дооолгое время я бился над этой задачей. Как обычно решение в голову пришло очень внезапно на курилке одновременно с ударом по голове (она и так болела и думать не хотела). Ведь все отдельные составляющие, как обычно, были известны, но соединить знания воедино для решения задачки я традиционно не мог. Задача была следующая — при помощи чего-нибудь (неважно чего) сделать так, чтобы ip адрес фактически «работал» на другом сервере. То есть, все запросы к ip-адресу перенаправлялись на другой сервер, а этот самый «другой» сервер вполне себе нормально отвечал на запросы к этому адресу.
Зачем это нужно?
- на виртуалочку на своём домашнем сервере (где, само собой, белым адресом и не пахнет (или пахнет только одним, а нужен второй)) притащить белый адрес для прямого доступа из интернета на неё. В топку DynDNS, да.
- при миграции содержимого сервера на новый сервер временно перевесить старый адрес на новый сервер не заморачиваясь с проксированием/форвардингом чего-либо куда-либо
- мигрировать виртуалки между физическими машинами в hetzner без заказа failover-ip =) Само собой, не в качестве постоянного решения, а в качестве «блин, надо вот эту виртуалку на другую железку на время перетащить».
- можно ipv6 таким образом притаскивать на машины без ipv6 (хотя для этого есть несколько более удачных способов)
Что будем использовать? ppptd. Всё. Никаких iptables с nat/forwarding-правилами, никаких проксирований — всё на честной маршрутизации и pptp. Такой вариант будет работать пошустрее и понадежнее за счёт того, что не будет использоваться conntrack, таблица которого достаточно бодро забивается при большом количестве соединений (и пакеты начинают дропаться). Можно pppoe, l2tp или openvpn — что сами сможете настроить. PPTP просто очень быстро настраивается сам по себе (и с ним этот вариант точно пройдет) — потому и пишу именно о нём.
- Сервер с двумя адресами. В моём примере это будут 46.4.251.90 (адрес, который я повешу на клиент) и 46.4.251.85 (адрес, который будет адресом исходного сервера).
- Клиент с доступом к интернету и отсутствием запрета на использование gre/vpn-passthrough. Учтите, что домашние провайдеры (особенно те, что по pppoe) и дешевые роутеры частенько блокируют gre.
- Второй адрес на сервере не должен в текущий момент использоваться на сервере. Попингуйте его, что ли =)
- минимальные познания в linux networking.
Само собой, чудеса невозможны. Нельзя просто взять и перевесить ip-адрес, привязанный к дата-центру в Германии на машинку на нашу виртуалку в Москве (да ещё и за NAT-ом, например). Поэтому в результате мы получим такую схему: клиент делает запрос на ip-адрес 46.4.251.90 -> пакетики попадают на сервер 46.4.251.85 -> пакеты отправляются в pptp-туннель на адрес 46.4.251.90 -> пакеты попадают на вторую машину -> вторая машина смотрит в свою таблицу маршрутизации и исходящие пакеты отправляет обратно клиенту через pptp-туннель -> сервер 46.4.251.85 получает пакеты из туннеля, видит, что получатель не он (и что отправитель «не он») -> пакеты уходят клиенту, делавшему запрос.
Настраиваем сервер pptpd:
# apt-get -qq update; apt-get install pptpd
В файл /etc/pptpd.conf пишем следующее:
Теперь напишем файлик с авторизацией и ip-адресами клиентов — /etc/ppp/chap-secrets :
Рестартим pptpd на всякий:
# /etc/init.d/pptpd restart
Теперь настроим клиент. Ставим пакет для клиента:
# apt-get -qq update; apt-get install pptp-linux
В файл /etc/ppp/peers/yourpeername пишем такое:
В файл /etc/ppp/ip-up _дописываем_ в конец такое:
В файл /etc/ppp/ip-down _дописываем_ в конец такое:
Что мы дописали? Первая команда создаёт дополнительную таблицу маршрутизации внутри системы. Вторая команда, соответственно, «говорит» нашему тазику использовать эту таблицу через нужный интерфейс с нужным default-шлюзом. Такая конструкция позволит нам отвечать на входящие пакеты исходящими пакетами с нужного адреса/интерфейса, через нужный шлюз, в тех случаях, когда на машинке несколько адресов из нескольких сетей с разными шлюзами. Собственно, аналогичную конструкцию я использовал, когда писал про VLAN-ы.
Запускаем наше соединение:
# pon yourpeername
С другой машинки проверяем, что всё заработало:
$ ping 46.4.251.90PING 46.4.251.90 (46.4.251.90) 56(84) bytes of data.64 bytes from 46.4.251.90: icmp_req=1 ttl=52 time=85.1 ms64 bytes from 46.4.251.90: icmp_req=2 ttl=52 time=84.9 ms
$ traceroute -n 46.4.251.90. 12 46.4.251.85 56.923 ms 56.921 ms 56.875 ms13 46.4.251.90 85.020 ms 84.822 ms 84.606 ms
Ну и последний штрих — обеспечить автостарт этой конструкции. Например, в /etc/rc.local перед exit 0 вписать
Рестарт подвисшего соединения можно сделать командой:
# poff yourpeername; sleep 2; pon yourpeername
Хотя при обрывах оно будет само рестартиться.
Из известных проблем такой схемы — провайдеры с отключенной фрагментацией проходящих пакетов. В таком случае большие пакеты, проходящие через туннель, могут дропаться. В этом случае следует снижать значение mtu/mss в файлах /etc/ppp/ip-