Публікацыя хатняга сервера праз VPS, калі CGNAT блакуе порты
Шлях ад браўзера да хатняй машыны: дакажы, што лінія за CGNAT, накіруй DNS на VPS, зрабі DNAT аднаго порта, паправь зваротны шлях і правер звонку.
Я пачаў ззвонку, як зрабіў бы карыстальнік: увёў імя ў браўзеры тэлефона на мабільных даных і глядзеў, як злучэнне вісіць, пакуль не скончыўся час. Імя вырашалася, значыць DNS быў у парадку. Старонка пракіду партоў на хатнім роўтары таксама была тупіком, бо яе адрас WAN паказваў 100.64.31.42, а гэта не адрас, на які правайдар маршрутызуе мяне з інтэрнэту. Гэты лік тлумачыць усю няспраўнасць: лінія знаходзіцца за carrier-grade NAT, таму публічны адрас з майго боку тунэля належыць правайдару. Далей ідзе шлях, які я прайшоў ад той завіслай закладкі да сэрвісу, які адказвае.
Пачні з кліента і рухайся ўнутр
Перш чым змяніць любое правіла, дакажы, дзе абрываецца ланцуг. На ноўтбуку я выканаў dig +short files.example.net і атрымаў адрас VPS, што выключыла састарэлы DNS на маёй машыне. Затым curl -v --connect-timeout 5 files.example.net:5022 вычарпаў час замест адмовы. Гэтая розніца важная: тайм-аўт звычайна азначае, што пакеты адкідаюцца па дарозе, а адмова азначае, што нешта адказала і сказала не.
Наступным крокам унутр быў сам VPS. ss -ltnp не паказаў нічога, што слухае на 5022, як і чакалася да з'яўлення правіла DNAT. На той самай машыне wg show (або ip -br a show tun0 для OpenVPN) пацвердзіў, што хатні peer падняты і мае свежы handshake. Калі peer не працуе, ніякае правіла NAT не дапаможа, а зялёнае святло на старонцы VPN хатняга роўтара нічога не значыць.
Пацвердзі, што хатняя лінія сапраўды за CGNAT
Параўнай адрас, які роўтар паведамляе на інтэрфейсе WAN, з тым, што бачыць знешні сэрвіс. Усё ў 100.64.0.0/10, гэта значыць ад 100.64.x.x да 100.127.x.x, — гэта дыяпазон агульных адрасоў з RFC 6598, і з інтэрнэту ён недасяжны. Да таго ж высновы прыходзіш, калі роўтар сцвярджае, што мае звычайны прыватны адрас, а публічная праверка вяртае нешта незвязанае. У лініі CGNAT можа быць і публічны адрас, які дзейнічае толькі да наступнага lease, таму пракід порта нібыта працуе гадзіну, а потым ціха памірае.
Некаторыя правайдары сапраўды выдаюць сапраўдны публічны адрас, але блокуюць уваходныя порты 80 і 443 на хатніх тарыфах. Калі твой сэрвіс толькі вэб, а адрас WAN сапраўды публічны, спытай падтрымку, перш чым будаваць relay. Калі не, схема ніжэй прымяняецца аднолькава да любога порта, і варта спыніць эксперымент на баку роўтара: транслятар у сетцы правайдара завяршае злучэнне раней, чым яно даходзіць да твайго інтэрфейса WAN.
Накіруй імя на адрас VPS
DNS не перасылае трафік, таму A-запіс сэрвіса павінен змяшчаць публічны адрас VPS. A-запіс на 192.168.1.20 вырашаецца карысна толькі для кліентаў, якія ўжо ўнутры VPN; з інтэрнэту ён вырашаецца ў адрас, які ніхто не можа маршрутызаваць. Для адміністрацыйнага доступу да самога VPS я трымаю асобнае імя, каб ніколі не блытаць, да якога хоста адносіцца запіс.
Калі і VPS, і хатняя машына аддаюць HTTP, дай кожнай сваё імя і дазволь VPS вырашаць, хто адказвае. Звесці іх у адно імя і спадзявацца, што проксі выбера правільны backend, — гэта менавіта тое, як праводзіш цэлы дзень, адладжваючы не той хост.
Адзін порт праз DNAT, SSH застаецца на 22
Правы варыянт — NAT прызначэння на VPS. Уключы forwarding для працуючага ядра і трымай у правіле адрас тунэля хатняга сервера, а не яго адрас LAN:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -p tcp -d 198.51.100.10 --dport 5022 -j DNAT --to-destination 10.8.0.2
Пакінь SSH да самога VPS на 22 і пракінь іншы порт, напрыклад 5022, на хатнюю машыну. Калі пракінеш 22 на выключаную машыну, страціш адзіны шлях, які мог бы яе паправіць. Тая ж логіка датычыцца проксі: трымай порт кіравання VPS па-за правіламі relay.
Зрабі правілы пастаяннымі, калі яны запрацуюць. У Debian або Ubuntu apt install iptables-persistent і затым netfilter-persistent save запісваюць іх у /etc/iptables/rules.v4. На хосце з firewalld эквівалент — пастаянны пракід порта ў зоне, якому перад ужываннем патрэбны firewall-cmd --reload. Правілы, якія жывуць толькі ў памяці, знікаюць пры першым сэрвісным перазапуску правайдара, звычайна ў няўдалую гадзіну.
Паправь зваротны шлях або пазбягі патрэбы ў ім
DNAT перапісвае толькі прызначэнне. Хатні сервер бачыць злучэнне з зыходнага адраса кліента, і калі яго маршрут па змаўчанні паказвае на хатні роўтар, адказ выходзіць праз хатні WAN, дзе транслятар правайдара яго адкідае. Гэтая асіметрыя была другой няспраўнасцю, з якой я сутыкнуўся, пасля таго як правіла DNAT выглядала цалкам правільным.
Дзве праўкі працуюць. Дай хатняй машыне палітычны маршрут, каб трафік з тунэля вяртаўся праз тунэль:
ip rule add from 10.8.0.2 table 100
ip route add default dev wg0 table 100
Або дазволь VPS перапісаць крыніцу, каб у адказе быў адрас, якога ён можа дасягнуць, і дазволь conntrack разгарнуць яго на выхадзе:
iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp --dport 5022 -j SNAT --to-source 10.8.0.1
Варыянт з SNAT хавае сапраўдны адрас кліента ад хатняга сервера, таму ў логах праграмы як peer бачны 10.8.0.1. Перадай зыходны адрас на ўзроўні праграмы або прымі страту лагавання па кліентах, але вырашы гэта свядома, а не выяўляй падчас інцыдэнту.
Правер увесь шлях звонку
Правер з сеткі, якая не з'яўляецца ні VPS, ні домам: тэлефон на мабільных даных або танны shell у іншым месцы. nc -vz files.example.net 5022 павінен паведаміць пра паспяховае злучэнне, а openssl s_client -connect files.example.net:443 -servername files.example.net павінен паказаць сертыфікат для публічнага імя. Затым правер security group або хмарны фаервол правайдара. Правіла DNAT, якое ніколі не бачыць пакет, звычайна блакуецца на ўзровень вышэй хоста.
Нарэшце, вырашы, што адбудзецца, калі тунэль упадзе. Правіла DNAT працягвае прымаць злучэнні і ціха накіроўвае іх у мёртвы тунэль, што выглядае дакладна як зламаны сэрвіс. Праверка стану на VPS, якая адхіляе порт, пакуль peer не працуе, каштуе некалькі радкоў і эканоміць гадзіну здагадак. Пасля гэтага спыні рэдагаваць правілы і паназірай суткі, перш чым давяраць.