Доступ до віддаленої /24 через тунель: NETMAP, DNAT чи маршрут?
Зіставте весь префікс через NETMAP, додайте правила DNAT для кожного хоста або маршрутизуйте реальний діапазон, і вирішіть за тим, що має бачити дальня сторона і кому можна починати трафік.
До підмережі за кінцевою точкою тунелю можна дістатися трьома способами, і хвилина збору фактів зазвичай виключає два. Факти такі: чи мають тамошні сервери розрізняти користувачів, чи хтось звідти колись підключатиметься до вашого діапазону, і хто може редагувати дальній маршрутизатор. Дайте відповідь на ці три, і дизайн обереться сам. Решта припускає, що ви керуєте кінцевою точкою і можете редагувати її міжмережевий екран.
Три варіанти і що кожен насправді змінює
Зіставлення префіксів, DNAT для кожного хоста і маршрутизований префікс переміщують пакети між тими самими двома діапазонами, але змінюють різні речі. Зіставлення вигадує діапазон псевдонімів і арифметично переписує адреси на льоту. Правила для хостів теж переписують, лише кожен пункт призначення задається вручну. Маршрутизований префікс нічого не переписує: пакети зберігають реальні адреси, і обидва кінці погоджуються, де живуть ці адреси.
| What the far side needs | Prefix mapping | Per-host DNAT | Routed prefix |
|---|---|---|---|
| Users visible to its logs | Only without source NAT | Same condition | Yes, unchanged |
| To start a connection toward you | No, alias is local | No, same reason | Yes, both ends route |
| To absorb a new host | Yes, arithmetic only | No, one rule per address | Yes, it simply routes |
| To require no config change | Yes, with source NAT | Yes, same condition | No, it needs a route back |
Починайте виключення з дальнього боку, де обмеження найважче змінити. Якщо тамошній сервер пише адреси клієнтів у журнали, звіряє їх зі списком дозволених або передає іншій системі, трансляція джерела знищує його єдиний ідентифікатор. Якщо дальній стороні теж треба підключатися всередину, трансляція виключена повністю, бо там ніхто не знає, що псевдонім існує. Лише коли дальня сторона тільки відповідає на запити, дешевші варіанти стають безпечними.
Пари префіксів і чому розміри мають збігатися
NETMAP — це ціль таблиці nat, що працює з парою префіксів однакової довжини. Усередині вона не має таблиці за адресами: відкидає префікс, зберігає біти хоста і приєднує їх до нового префікса, тому /24 відображається на /24 і ніколи на /25. Позиція визначає напрямок: збіг за призначенням у PREROUTING переписує, куди йде пакет, а збіг за джерелом у POSTROUTING переписує, звідки він прийшов.
Хост на 192.168.2.17 видно вашим клієнтам як 10.50.1.17, і останній октет — не прикраса, це те саме число з обох боків. Додайте завтра хост на 192.168.2.40, і його псевдонім буде 10.50.1.40, без правил, які треба редагувати.
Клієнтам усе ще потрібен маршрут до діапазону псевдонімів, що вказує на вашу машину, якщо тільки псевдонім не потрапляє в підмережу, до якої вони вже дістають. Шлюзу не потрібен маршрут для псевдоніма, бо трансляція призначення виконується в PREROUTING, до пошуку маршруту. Пересилання теж має бути ввімкнене, інакше ядро відкине пакет після перезапису. Три команди нижче — це все налаштування на шлюзі в стилі Debian з клієнтами на br0, псевдонімом на 10.50.1.0/24 і тунелем на tun0.
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -i br0 -d 10.50.1.0/24 -j NETMAP --to 192.168.2.0/24
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADEВідповідь має сама знайти зворотний шлях
Перезапис призначення вирішує лише, куди пакет буде доставлено. Дальній сервер усе одно має відповісти на адресу, до якої дістає, і це можна влаштувати двома способами. Транслюйте джерело, щоб відповіді поверталися на вашу машину, або залиште джерело і дайте дальній стороні маршрут до діапазону клієнтів.
Masquerade на виході — коротший шлях: одне правило в POSTROUTING, і дальня сторона бачить адресу вашого тунелю, тож власний маршрут їй не потрібен. Ціна — усі користувачі сходяться в одну адресу, і журнали за користувачами перестають щось означати. Якщо залишити джерело недоторканим, ця інформація зберігається, але тоді віддалений сайт має надсилати відповіді для діапазону клієнтів назад через тунель.OpenVPN сервері це push-надісланий push "route 10.50.9.0 255.255.255.0", плюс route 192.168.2.0 255.255.255.0 рядок.
Дорога помилка — зробити половину кожного. Якщо ви маскуєте частину трафіку, а дальня сторона несе ще й зворотний маршрут для іншого трафіку, відповіді приходять на інтерфейс, де запис відстеження з'єднань ніколи не з'являвся. Клієнт повідомляє про тайм-аут для запиту, який сервер записав як обслужений. Обидва напрямки потоку мають проходити через один і той самий екземпляр netfilter: один шлюз транслює, а не два міжмережеві екрани послідовно.
conntrack -L -d 10.50.1.17
iptables -t nat -L PREROUTING -v -nЧитайте запис в обох напрямках: початковий tuple зберігає ваш псевдонім у призначенні, а tuple відповіді несе реальну адресу. Якщо tuple відповіді немає, проблема у зворотному шляху, а не в правилі. Якщо лічильники PREROUTING жодного разу не зрушили, пакет так і не дійшов до цього хука.
Колізії та пошук, що виконується першим
Два різні діапазони можуть конфліктувати, і обидві відмови виглядають як зламаний тунель, а не як погане правило. Вигаданий псевдонім має бути невикористаним уздовж усього шляху, а реальний дальній діапазон не повинен уже існувати у вашій мережі. Дублікат дає періодичний трафік не тому хосту, і це важче діагностувати, ніж відмову в з'єднанні. Запитайте таблицю маршрутизації, перш ніж додавати правило.
На шлюзі, ip route get 192.168.2.17 має вказувати на пристрій тунелю; локальний bridge означає, що дальній діапазон затінений і жодне правило nat це не виправить. Якщо ваша мережа вже використовує 192.168.2.0/24, перенумеруйте віддалений сайт, а не нашаровуйте зіставлення на колізію.
Перевірка з реального клієнта, а потім збереження
Перевіряйте з машини, яка справді використовуватиме псевдонім, а не зі шлюзу, бо локально створений трафік ніколи не проходить PREROUTING так само. Відкрийте з'єднання до одного хоста з псевдонімом і спостерігайте, як лічильники та запис conntrack з'являються разом, потім закрийте і переконайтеся, що запис зникає. Застарілий запис указує на напіввідкрите з'єднання, що зазвичай означає, що відповідь так і не повернулася.
curl -sv http://10.50.1.17/ -o /dev/null
ss -tn dst 10.50.1.17
conntrack -L -d 10.50.1.17Два-три успішні з'єднання доводять арифметику, але нічого не кажуть про стійкість чи наступного інженера. Зберігайте правила там, де їх читає процес завантаження, що в Debian і Ubuntu означає iptables-save > /etc/iptables/rules.v4 з увімкненим netfilter-persistent. Зіставлення, яке зникає після перезавантаження, гірше за відсутнє, бо збій приходить без недавньої зміни, яку можна звинуватити.
Залиште нотатку поруч із правилами: діапазон псевдонімів, реальний діапазон, причина пари і яка сторона може ініціювати. Ця нотатка відділяє проєкт від купи правил, які ніхто не наважується видалити. Вона ж вирішує пізніше питання, коли віддалений сайт додає хост, а адреса, яку ніхто не налаштував, уже відповідає. Якщо в нотатці сказано, що дальній стороні потрібен зворотний маршрут, наступна людина знає, що видалення правила masquerade ламає зв'язність. Документація тут дешева; повторно відкривати залежність від NAT о третій ночі — ні.