Один публічний хост для VPN і вебу: як розділити ролі
Одна публічна IP-адреса може завершувати тунелі, обслуговувати HTTPS і досягати двох приватних мереж LAN. Спершу вирішіть, кому належать адреса, кожен порт і політика пересилання.
Одна машина може задовольнити всі три потреби одразу: завершувати тунелі, відповідати на HTTPS і пересилати між двома приватними мережами LAN. Чи це розумно, зводиться до трьох речей, які можна вирішити на папері: кому належить публічна адреса, кому належить кожна пара порту й протоколу і якому процесу дозволено пересилати пакети. Якщо все правильно, спільний хост нічим не примітний. Якщо ні, ви проведете вихідні з сервісом, який чисто запускається і ніколи не відповідає.
Далі йде процедура ухвалення рішень, а не креслення складання. Кожен крок завершується перевіркою, яка доводить, що щойно додану роль справді ізольовано.
Виберіть власника адреси раніше за порти
Кінцева точка тунелю і вебсервер можуть ділити одне ядро; одночасний спільний доступ до однієї адреси, порту й протоколу — це те, що ламається. WireGuard зазвичай займає UDP 51820, OpenVPN займає UDP 1194 або TCP 443, а вебсервер займає TCP 443. Болісна пара — OpenVPN поверх TCP 443 поруч із HTTPS, бо обом потрібен той самий сокет, і ядро віддає його тому, хто прив'язався першим. Лише демультиплексор попереду, наприклад sslh або проксі, що розуміє TLS, дозволяє їм ділити цей порт, і він додає компонент, збій якого виглядає точно як проблема брандмауера.
Подивіться на власників, перш ніж щось змінювати: ss -lntup друкує локальну адресу, порт і процес кожного сокета, що слухає. Два рядки з 0.0.0.0:443 означають, що друга служба так і не прив'язалася, яким би бадьорим не був її init-скрипт. Міст теж переносить власника. Коли eth0 приєднується до br0, IP переходить на br0 і кожне правило брандмауера, що згадує eth0, перестає збігатися, тож прив'яжіть служби на мосту й підтвердьте через ip -br addr.
Те саме правило володіння пояснює несподіванку, яка виникає з віртуальними машинами. Тунельний сервер, що працює всередині гостьової системи в тій самій мережі LAN, зберігає адресу гостьової системи, тож з'єднання, скеровані на адресу самого хоста, залишаються на хості й тунель гостьової системи їх ніколи не бачить, хоч би що стверджував профіль клієнта.
Маршрутизуйте між двома мережами LAN або зробіть NAT з одного боку
Дві мережі LAN, які не бачать одна одну, можуть кожна звернутися до публічного хоста, який потім пересилає між тунелями. Такий маршрутизований дизайн потребує трьох речей: увімкненого пересилання, маршруту до кожного віддаленого префікса й політики пересилання, що пропускає транзит. sysctl -w net.ipv4.ip_forward=1 покриває перше, ip route add 10.20.0.0/24 dev wg1 друге, а рядок nftables на кшталт nft add rule inet filter forward iifname "wg0" oifname "wg1" accept третє.
NAT джерела легше додати й важче налагоджувати. Маскування переписує адресу клієнта, тож віддалений бік бачить концентратор, а не справжній хост, і його правила доступу та журнали перестають бути корисними для атрибуції. Коли обидві мережі ваші, маршрутизуйте. Коли один бік належить третій стороні, яка не додасть зворотного маршруту, NAT — це варіант, що вийде цього тижня. У будь-якому разі запишіть план адрес, бо дві перекривані /24 не можна маршрутизувати жодною конфігурацією.
Ніщо в тому, що машина слугує інтернет-виходом для ноутбука, не заважає їй же завершувати вхідні тунелі. Заважають лише перекривані адреси, і саме тому план адрес — той документ, що має значення.
Перевірте поділ, коли дві ролі зупинені
Корисний тест — віднімання: зупиніть дві ролі й переконайтеся, що третя все ще відповідає. Вебзапит має завершитися, коли служба тунелю вимкнена, а рукостискання тунелю має завершитися, коли вебсервер зупинений. Якщо обидва працюють лише тоді, коли працює все, у вас випадкова залежність, як-от спільна таблиця брандмауера, заблуканий маршрут або ім'я, що вказує на неправильну адресу.
Три команди роблять цей тест конкретним. curl -sk --resolve example.test:443:203.0.113.10 https://example.test/ доводить, що локальний слухач відповідає без зовнішнього DNS, wg show на клієнті доводить, що рукостискання завершилося, а tcpdump -ni any port 51820 на концентраторі відокремлює проблему маршрутизації від проблеми ключа. Рукостискання, яке ніколи не з'являється в записі, померло до хоста: брандмауер провайдера, неправильна публічна адреса або правило NAT на шляху.
Повторіть віднімання для пересиланих мереж LAN. Коли один партнер від'єднаний, ping через концентратор має зазнати невдачі; коли його знову під'єднано, ping має відновитися без дотику до правила. Ping, що відновлюється лише після перезапуску тунелю, вказує на політику, а не на доступність, і це інше виправлення.
Тримайте набір правил читабельним, поки віднімаєте ролі. nft list ruleset має показувати одне правило дозволу на кожен напрямок, який вам справді потрібен, а ланцюг пересилання, що дозволяє все, — це не розділення, а робоча демонстрація.
Лінії доступу лише з IPv6 і служби IPv4
Деякі лінії доступу дають лише доступність IPv6, а служби все одно треба публікувати через IPv4. Сам тунель іде через родину, яка ще пропускає трафік, тоді як опублікована служба сидить на адресі всередині тунелю. Це перевертає звичне припущення й тихо ламає моніторинг: правило брандмауера або перевірка доступності, написані для шляху IPv4, тепер стежать за інтерфейсом, що нічого не несе.
Перевіряйте кожну родину окремо за допомогою curl -4 і curl -6, бо один успішний запит нічого не каже про шлях, якого ви не пробували. Володіння портом не змінюється між родинами, а слухач змінюється: ss -lntup перелічує сокети IPv4 і IPv6 окремими рядками, а 0.0.0.0:443 не покриває [::]:443, якщо процес не попросив dual-stack сокет.
Служба, що відповідає на одній родині й відмовляє на іншій, зазвичай є проблемою слухача, а не маршрутизації. Перш ніж назвати дизайн готовим, переконайтеся, що кожна роль має власну адресу або порт, що пересилання ввімкнене й дозволене і що кожна роль усе ще відповідає, коли дві інші зупинені.