Multihome IPv4 в Linux

Вміст: як зробити так, щоб комп'ютер відповідав в інтернеті на всі свої IP-адреси по всім своїм інтерфейсам, кожен з яких шлюз за замовчуванням. Стосується і серверів, і десктопів.

Ключові слова: policy routing, source based routing

Лірика: Є достатньо статей про policy routing в Linux. Але вони найчастіше розбирають загальні, більш тонкі і складні випадки. Я ж розберу тривіальний сценарій наступного виду:



Нашого комп'ютера (сервера) доступно три інтерфейсу. На кожному інтерфейсі шлюз йому видав IP (статикою або по dhcp, не важливо) і сказав «весь трафік йшли мені».

Якщо ми залишимо цю конфігурацію як є, то буде використовуватися принцип «хто останній встав, того і дефолтний шлюз». На картинці вище, якщо останнім підніметься нижній інтерфейс (241), то в нього буде відправлятися весь трафік. Якщо до нашого сервера прийде запит на перший інтерфейс (188), то відповідь на нього все одно піде по нижньому. Якщо маршрутизатор/провайдера є хоча б мінімальна захист від підробки адрес, то відповідь просто дропнут, як невалидный (з точки зору 241.241.241.1 йому прислали з мережі 241.241.241.0/24 пакет з src 188.188.188.188, чого, очевидно, бути не повинно).

Іншими словами, в звичайному варіанті буде працювати тільки один інтерфейс. Щоб зробити ситуацію гірше, якщо адреси отримані по dhcp, то оновлення оренди на інших інтерфейсах може перезаписати шлюз за замовчуванням, що означає, що той інтерфейс, який працював, перестане працювати, а почне працювати інший інтерфейс. Вдалою стабільної роботи вашого сервера, так сказати.

Рішення
Спільне рішення — policy routing. Досить об'ємна і цікава штука дозволяє виробляти всілякі дива. З цих чудес ми (в рамках цієї статті) залишимо тільки одне: «відсилати кожного маршрутизатора трафік з „його“ інтерфейсу». Тобто класичний source-based routing в самій примітивній формі.

Огляд рішення з висоти пташиного польоту:

Ми ставимо три варіанти маршрутизації трафіку: «все в eth0», «все в eth1», «все в eth2», далі формулюємо правила: трафік IP першого інтерфейсу відправляти через перший варіант, трафік з другого IP — через другий варіант, третій IP — через третій.

В результаті ми отримуємо таку конструкцію:
source: 188.188.188.188 в таблицю eth0-route default via 188.188.1 via eth0
source: 75.75.75.75 в таблицю eth1-route default via 75.75.75.1 via eth1
source: 241.241.241.241 в таблицю eth2-route default via 241.241.241.1 via eth2


Короткий вміст:
  1. Налаштувати утиліту iproute2 з допомогою конфига (раптово, у неї є конфіг!) — дати імена трьох таблиць маршрутизації
  2. Налаштувати маршрути в трьох таблицях маршрутизації — точніше, задати дефолтні машруты
  3. Вказати правила, за якими трафік буде розподілятися за трьома таблиць маршрутів


Кроки детальніше
Утиліта ip (її офіційна назва iproute2) має спеціальну команду — ip rule для управління policy routing. А додавання маршрутів (ip route add) може приймати аргумент з назвою таблиці. Ядро нічого про назви таблиць не знає, а от iproute2 потребує використання імені свого конфига —
/etc/iproute2/rt_tables
(яка зіставляє імена абстрактних чисел, які розуміє ядро). Значення «0» і значення нижче 255 (254, 253) зайняті, інші можна використовувати.

Налаштування iroute2
Ми назвемо наші таблиці маршрутизації eth0-route, eth1-route, eth2-route. Візьмемо випадкові символічні номера — 100, 101, 102.

echo 100 eth0-route >>/etc/iproute2/rt_tables
echo 101 eth1-route >>/etc/iproute2/rt_tables
echo 102 eth2-route >>/etc/iproute2/rt_tables

Налаштування маршрутів в трьох таблицях маршрутизації
Для кожної таблиці задамо маршрут за замовчуванням (можна і не за замовчуванням — фантазія у ваших руках). Ці правила нічого не зламають на сервері і їх можна робити на живу. Поки ми не скажемо використовувати ці таблиці — це всього лише байтікі в пам'яті, і вони на роботу маршрутизації не впливають (тобто ми не залишимося раптово без коннективити в середині процесу).

ip route add default via 188.188.188.1 dev eth0 table eth0-route
ip route add default via 75.75.75.1 dev eth1 table eth1-route
ip route add default via 241.241.241.1 dev eth2 table eth2-route

Тепер інтимний момент: уважно перечитати написане. Після включення правил помилка в таблиці може залишити сервер без коннективити.

Включення policy routing

ip rule add from 188.188.188.188 lookup eth0-route
ip rule add from 75.75.75.75 lookup eth1-route
ip rule add from 241.241.241.241 lookup eth2-route

Всі. З цього моменту сервер почне відповідати за всіма трьома адресами. Приємна новина: policy routing має більш високий пріоритет, ніж dhcp'шний default route, так що оновлення оренди не зламає маршрутизацію.
Неприємна новина: якщо при оновленні оренди вам видадуть іншу адресу, то він перестане працювати. Це можна виправити або зробивши правило з маскою (
from 241.241.241.0/24
), або прибивши адреса цвяхами в конфіги dhcp-сервера (взагалі, серверів не прийнято видавати динамічні адреси DHCP...)

Відлиття в конфігах
(debian/ubuntu)
Відмінне місце для цих правил — в /etc/network/interfaces. Для потрібного інтерфейсу пишемо:

iface eth0 inet static
address 188.188.188.188
netmask 255.255.255.0
broadcast: 188.188.188.255
pre-up ip route add default via 188.188.188.1 dev eth0 table eth0-route
pre-up ip rule add from 188.188.188.188 lookup eth0-route

Примітки
Зауваження про маршрутизації: source routing в загальному випадку відкриває уразливість в системі (вам шлють пакет з фальшивим source, а ви передаєте його далі, наче так і треба), але ця узявімость рівня directly connected. Крім того, якщо ви обмежуєтеся лише своїм адресою from в правилах, то лінукс такого не пропустить, плюс вам треба мати включену маршрутизацію. На звичайному сервері така конфігурація цілком безпечна і досить надійна.

Зауваження про load-balancing: Прописавши всі три адреси A-записи DNS-зони, ви отримаєте безкоштовний round-robin по всім трьом інтерфейсам без бондингу і поетес. Так як вони будуть оброблятися одним і тим же сервером і одним і тим же додатком, це дозволить балансувати навіть stateful-сесії.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.