Debian.pro/

Про Debian


«Телепортируем» белый ip-адрес на другой сервер при помощи pptp.

Дооолгое время я бился над этой задачей. Как обычно решение в голову пришло очень внезапно на курилке одновременно с ударом по голове (она и так болела и думать не хотела). Ведь все отдельные составляющие, как обычно, были известны, но соединить знания воедино для решения задачки я традиционно не мог.
Задача была следующая — при помощи чего-нибудь (неважно чего) сделать так, чтобы ip адрес фактически «работал» на другом сервере. То есть, все запросы к ip-адресу перенаправлялись на другой сервер, а этот самый «другой» сервер вполне себе нормально отвечал на запросы к этому адресу.

Зачем это нужно?

  1. на виртуалочку на своём домашнем сервере (где, само собой, белым адресом и не пахнет (или пахнет только одним, а нужен второй)) притащить белый адрес для прямого доступа из интернета на неё. В топку DynDNS, да.
  2. при миграции содержимого сервера на новый сервер временно перевесить старый адрес на новый сервер не заморачиваясь с проксированием/форвардингом чего-либо куда-либо
  3. мигрировать виртуалки между физическими машинами в hetzner без заказа failover-ip =) Само собой, не в качестве постоянного решения, а в качестве «блин, надо вот эту виртуалку на другую железку на время перетащить».
  4. можно ipv6 таким образом притаскивать на машины без ipv6 (хотя для этого есть несколько более удачных способов)

Что будем использовать? ppptd. Всё. Никаких iptables с nat/forwarding-правилами, никаких проксирований — всё на честной маршрутизации и pptp. Такой вариант будет работать пошустрее и понадежнее за счёт того, что не будет использоваться conntrack, таблица которого достаточно бодро забивается при большом количестве соединений (и пакеты начинают дропаться). Можно pppoe, l2tp или opencensored — что сами сможете настроить. PPTP просто очень быстро настраивается сам по себе (и с ним этот вариант точно пройдет) — потому и пишу именно о нём.

Что нужно:

  1. Сервер с двумя адресами. В моём примере это будут 46.4.251.90 (адрес, который я повешу на клиент) и 46.4.251.85 (адрес, который будет адресом исходного сервера).
  2. Клиент с доступом к интернету и отсутствием запрета на использование gre-passthrough. Учтите, что домашние провайдеры (особенно те, что по pppoe) и дешевые роутеры частенько блокируют gre.
  3. Второй адрес на сервере не должен в текущий момент использоваться на сервере. Попингуйте его, что ли =)
  4. минимальные познания в linux networking.

Само собой, чудеса невозможны. Нельзя просто взять и перевесить ip-адрес, привязанный к дата-центру в Германии на машинку на нашу виртуалку в Москве (да ещё и за NAT-ом, например). Поэтому в результате мы получим такую схему:
клиент делает запрос на ip-адрес 46.4.251.90 -> пакетики попадают на сервер 46.4.251.85 -> пакеты отправляются в pptp-туннель на адрес 46.4.251.90 -> пакеты попадают на вторую машину -> вторая машина смотрит в свою таблицу маршрутизации и исходящие пакеты отправляет обратно клиенту через pptp-туннель -> сервер 46.4.251.85 получает пакеты из туннеля, видит, что получатель не он (и что отправитель «не он») -> пакеты уходят клиенту, делавшему запрос.

Поехали.

Настраиваем сервер pptpd:

root@server:~# apt-get -qq update; apt-get install pptpd

В файл /etc/pptpd.conf пишем следующее:

option /etc/ppp/pptpd-options
logwtmp
# localip-адрес не должен пересекаться ни с одним из адресов, доступных машине-клиенту через, например, локальную сеть.
localip 192.168.10.1
# во многих мануалах описывается ещё и параметр remoteip - но нам он в данном случае не нужен, т.к. все адреса мы будем прибивать к логину/паролю в следующем файле.

Теперь напишем файлик с авторизацией и ip-адресами клиентов — /etc/ppp/chap-secrets :

# Secrets for authentication using CHAP
# client server secret IP addresses
user1 pptpd password1 46.4.251.90
# если нужен другой пользователь с другим адресом, то:
#user2 pptpd password2 xx.xx.xx.xx
# адрес в четвертой колонке может быть любым, главное, чтобы он маршрутизировался на ваш сервер и не был, собственно, занят этим сервером.

Рестартим pptpd на всякий:

root@server:~# /etc/init.d/pptpd restart

Теперь настроим клиент. Ставим пакет для клиента:

root@client:~# apt-get -qq update; apt-get install pptp-linux

В файл /etc/ppp/peers/yourpeername пишем такое:

pty "pptp 46.4.251.85 --nolaunchpppd"
name user1
password password1
remotename PPTP
require-mppe-128
persist
maxfail 0
holdoff 20
noauth

В файл /etc/ppp/ip-up _дописываем_ в конец такое:

/sbin/ip ru add from ${4} lookup 17 priority 17
/sbin/ip ro add default via ${5} dev ${1} src ${4} table 17 mtu 1450 advmss 1410

В файл /etc/ppp/ip-down _дописываем_ в конец такое:

/sbin/ip ro del default via ${5} dev ${1} src ${4} table 17 mtu 1450 advmss 1410
/sbin/ip ru del pref 17

Что мы дописали? Первая команда создаёт дополнительную таблицу маршрутизации внутри системы. Вторая команда, соответственно, «говорит» нашему тазику использовать эту таблицу через нужный интерфейс с нужным default-шлюзом. Такая конструкция позволит нам отвечать на входящие пакеты исходящими пакетами с нужного адреса/интерфейса, через нужный шлюз, в тех случаях, когда на машинке несколько адресов из нескольких сетей с разными шлюзами. Собственно, аналогичную конструкцию я использовал, когда писал про VLAN-ы.

Запускаем наше соединение:

root@client:~# pon yourpeername

С другой машинки проверяем, что всё заработало:

inkvizitor68sl@malygos:~$ ping 46.4.251.90
PING 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 ms
64 bytes from 46.4.251.90: icmp_req=2 ttl=52 time=84.9 ms
inkvizitor68sl@client:~$ traceroute -n 46.4.251.90
...
12 46.4.251.85 56.923 ms 56.921 ms 56.875 ms
13 46.4.251.90 85.020 ms 84.822 ms 84.606 ms

Ну и последний штрих — обеспечить автостарт этой конструкции. Например, в /etc/rc.local перед exit 0 вписать

pon yourpeername

Рестарт подвисшего соединения можно сделать командой:

root@client:~# poff yourpeername; sleep 2; pon yourpeername

Или около того.

Хотя при обрывах оно будет само рестартиться.

Из известных проблем такой схемы — провайдеры с отключенной фрагментацией проходящих пакетов. В таком случае большие пакеты, проходящие через туннель, могут дропаться. В этом случае следует снижать значение mtu/mss в файлах /etc/ppp/ip-{up,down}


Комментарии (10):

  1. cru5ade :

    Привет, у меня вопрос маленько не в тему , но все ж…
    Когда появятся видеозаписи для скачивания с прошлых вебинаров/семинаров?

  2. Влад :

    А черт его знает(
    У меня осталась запись только одного вебинара, обрабатывать некому. Теран в Мирантис ушел уже)

  3. t3mp :

    Рассматривали тунель: ipip/gre?

  4. Да всё то же самое будет.

    Вся магия в этом:
    /sbin/ip ru add from ${ip} lookup 17 priority 17
    /sbin/ip ro add default via ${remote_ip} dev ${iface} src ${ip} table 17 mtu 1450 advmss 1410

    ip — локальный адрес в туннеле, remote_ip — адрес второй точки ptp-соединения (ну или default gatewy для туннеля, по-простому, если у нас более сложная сеть), iface — локальный интерфейс соединения, на котором адрес висит.

    Просто с pptp всем понятно и автоматизировать там всё легко )

  5. t3mp :

    «Магия» понятно, ipip/gre тунель по надежнее будет, + работает в ядре.

  6. Ага. Напишу потом статью тоже, наверное. Только придумаю, как persistence конфигурацию сделать.

  7. t3mp:

    Я хоть и не прочитал статью (ибо слишком банальная задача и поэтому статья скучная), но там упоминается использование pptpd-сервера, которые уже достаточно давно как работает почти полностью на уровне ядра.

    Ранее использовался accel-pptpd, но его наработки успешно перенесли в ядро, IIRC.

  8. Spirt :

    IPv6 не пробовали телепортировать таким образом?

  9. > IPv6 не пробовали телепортировать таким образом?
    Через pptp нет, через ipip делал — https://debian.pro/1578
    Если на dst нет ipv6 «родного», то и вовсе достаточно на src сделать /128 маршрут в туннель для адреса.

Написать комментарий