Обзор
Сервис поднят дома и работает, но снаружи его не видно. Причина почти всегда одна: у домашнего подключения нет публичного адреса, и пробросить порт на роутере некуда — роутер сам стоит за чужим NAT. Обходной путь известен и устоялся: арендуется самый дешёвый VPS с белым IP, между ним и домашней машиной поднимается постоянный туннель, а входящие соединения с публичного адреса переправляются внутрь.
Схема выглядит простой ровно до момента реализации. Дальше выясняется, что туннель молча отваливается через пару минут простоя, что в логах веб-сервера у всех посетителей один и тот же адрес, что маленькие страницы открываются, а большие файлы виснут на середине, и что месячный лимит трафика на VPS кончился в четверг. Каждая из этих проблем имеет ровно одну причину, и все они разбираются ниже.
Отдельный раздел — про альтернативы. Самодельная схема на WireGuard даёт максимум контроля, но она не всегда лучший выбор, и честнее знать, где готовое решение объективно выигрывает.
Почему порт не пробросить
Стоит сначала точно понять, с чем имеем дело, — от этого зависит, нужна ли вся конструкция вообще.
Серый IP за домашним роутером. Обычная ситуация: роутер получает от провайдера публичный адрес, а домашние устройства сидят за его NAT. Это лечится пробросом порта в веб-интерфейсе роутера, и никакой VPS не нужен.
CGNAT (Carrier-Grade NAT). Провайдер выдаёт роутеру адрес из приватного диапазона и сам транслирует его в публичный, разделяемый между сотнями абонентов. Пробрасывать нечего: на внешнем адресе вы не хозяин. Диагностируется за минуту — адрес на WAN-интерфейсе роутера сравнивается с тем, что показывает внешний сервис:
curl -s https://api.ipify.org; echo # что видит интернет
ip -4 addr show dev "$(ip route show default | awk '{print $5; exit}')"
Если адрес на интерфейсе принадлежит 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 или 100.64.0.0/10 (последний зарезервирован именно под CGNAT), а внешний отличается — вы за CGNAT. Дальше два пути: попросить у провайдера белый адрес за доплату либо строить точку входа самостоятельно.
Схема и её границы
клиент VPS (белый IP) домашняя машина
│ ┌──────────────┐ ┌──────────────┐
│ 443/tcp │ eth0 │ │ │
├─────────────────>│ │ │ │
│ │ DNAT + FWD │ │ │
│ │ wg0 ────────┼── туннель ─┼──> wg0 │
│ │ 10.100.0.1 │ WireGuard │ 10.100.0.2 │
│ └──────────────┘ │ сервис:443 │
│ └──────────────┘
│ ↑ CGNAT провайдера обходится тем,
│ что соединение всегда исходящее
Работает это благодаря одной асимметрии: домашняя машина сама устанавливает исходящее соединение к VPS. Исходящие через CGNAT проходят беспрепятственно, а трансляция, созданная этим соединением, дальше используется в обе стороны. Публичный адрес VPS становится адресом ваших сервисов.
Чего схема не даёт, стоит зафиксировать сразу, потому что это часто выясняется постфактум:
- Пропускная способность ограничена VPS, а не домашним каналом. Виртуалка за пять евро с портом 100 Мбит/с — это потолок для всего, что вы публикуете, независимо от того, что дома гигабит.
- Задержка складывается. Клиент → VPS → дом, и обратно тем же путём. Если VPS во Франкфурте, а вы и клиент в одном городе, трафик всё равно ходит через Франкфурт.
- Лимит трафика — реальное ограничение. У большинства дешёвых провайдеров это 1–20 ТБ в месяц; медиасервер с внешними зрителями съедает такой объём быстрее, чем кажется.
- VPS становится единой точкой отказа и единственной публичной поверхностью атаки одновременно.
Из этого следует область применимости: схема отлично подходит для веб-сервисов, API, панелей управления и личного доступа; она плохо подходит для раздачи большого объёма медиа наружу и для нагрузок, чувствительных к задержке.
Туннель
Почему WireGuard, а не OpenVPN: для постоянного канала между двумя машинами он проще в конфигурации, легче по накладным расходам и не требует демона с собственным состоянием — интерфейс живёт в ядре. Подробное сравнение с разбором того, где выигрывает каждый, вынесено в отдельную заметку.
Ключи и адресация
Туннелю нужна своя маленькая подсеть, не пересекающаяся ни с домашней, ни с сетью VPS. Возьмём 10.100.0.0/24: .1 — VPS, .2 — домашняя машина.
wg genkey | tee privatekey | wg pubkey > publickey
chmod 600 privatekey
Конфигурация на VPS — /etc/wireguard/wg0.conf:
[Interface]
Address = 10.100.0.1/24
ListenPort = 51820
PrivateKey = <приватный ключ VPS>
[Peer]
# домашняя машина
PublicKey = <публичный ключ дома>
AllowedIPs = 10.100.0.2/32
Конфигурация дома:
[Interface]
Address = 10.100.0.2/24
PrivateKey = <приватный ключ дома>
[Peer]
PublicKey = <публичный ключ VPS>
Endpoint = vps.example.com:51820
AllowedIPs = 10.100.0.1/32
PersistentKeepalive = 25
Асимметрия здесь принципиальна и отражает суть схемы. У домашнего пира прописан Endpoint — он знает, куда стучаться. У VPS Endpoint для домашнего пира не указан: адрес за CGNAT непредсказуем и меняется, поэтому VPS узнаёт его из первого пришедшего пакета и запоминает. Это называется roaming и работает автоматически.
AllowedIPs — таблица маршрутов, а не список доступа
Самая частая ошибка в конфигурации WireGuard происходит из-за названия параметра. AllowedIPs выполняет две работы сразу: на приём — фильтрует, какие адреса-источники допустимы от этого пира (криптографическая привязка ключа к диапазону), на отправку — определяет, какой трафик вообще пойдёт в туннель. Второе важнее и неочевиднее: это фактически таблица маршрутизации, и wg-quick буквально создаёт по ней маршруты.
Отсюда прямой ответ на вопрос, какой трафик заворачивать. В нашей схеме — только трафик самого туннеля, то есть /32-адреса пиров. Прописать дома AllowedIPs = 0.0.0.0/0 означает отправить весь интернет-трафик домашней машины через VPS: она потеряет свой канал, упрётся в полосу виртуалки и начнёт ходить в сеть с чужого адреса. Для схемы публикации сервисов это не нужно совершенно.
Если наружу надо отдать не одну машину, а всю домашнюю подсеть, AllowedIPs у домашнего пира на стороне VPS расширяется до 10.100.0.2/32, 192.168.1.0/24, а дома включается форвардинг. Но начинать стоит с одной машины.
PersistentKeepalive: почему он здесь обязателен
Параметр выглядит необязательной оптимизацией, и в документации wg прямо сказано, что большинству пользователей он не нужен. В нашей схеме он нужен всегда, и вот почему.
WireGuard не имеет понятия соединения: нет ни установления, ни поддержания сессии, при отсутствии данных по проводу не идёт вообще ничего. Промежуточному NAT провайдера это неизвестно — он держит запись трансляции ограниченное время и выбрасывает её по таймауту неактивности, обычно от 30 секунд до нескольких минут. После этого пакет от VPS к дому приходить некуда: трансляции нет, и до восстановления пройдёт время, пока домашняя сторона сама что-нибудь не отправит.
Симптом узнаваем: туннель работает, пока им пользуются, и «залипает» после простоя — первое соединение отваливается по таймауту, второе проходит. PersistentKeepalive = 25 заставляет отправлять аутентифицированный пустой пакет каждые 25 секунд, что удерживает трансляцию открытой. Значение выбрано с запасом относительно самых агрессивных таймаутов; документация WireGuard рекомендует именно его.
Ставить keepalive нужно на стороне за NAT — дома. На VPS он бессмыслен: у виртуалки публичный адрес, ей нечего удерживать. Плата за это — небольшой постоянный трафик (порядка мегабайта в сутки) и то, что домашняя машина не уходит в глубокие энергосберегающие состояния; для сервера это не имеет значения.
Запуск и контроль живости
systemctl enable --now wg-quick@wg0
wg show # состояние: пиры, ключи, счётчики
wg show wg0 latest-handshakes # unix-время последнего рукопожатия
ping -c 3 10.100.0.1 # с домашней машины
Ключевой показатель здоровья — время последнего рукопожатия. WireGuard обновляет его не чаще, чем раз в две минуты при наличии трафика; значение старше пяти минут при живом keepalive означает, что туннель фактически мёртв, даже если интерфейс поднят. На это стоит завести простую проверку:
#!/usr/bin/env bash
# /usr/local/bin/wg-watchdog — перезапуск туннеля при потере связи
last=$(wg show wg0 latest-handshakes | awk '{print $2; exit}')
[[ -z $last || $last -eq 0 ]] && exit 0 # ещё ни разу не поднимался
if (( $(date +%s) - last > 300 )); then
logger -t wg-watchdog "рукопожатия нет $(( $(date +%s) - last ))s, перезапуск"
systemctl restart wg-quick@wg0
fi
Вешается на таймер systemd с интервалом в минуту. Автоматического восстановления в самом wg-quick нет: юнит имеет тип oneshot и после успешного поднятия интерфейса завершается, поэтому Restart= там ничего не даст — systemd нечего перезапускать, процесс и должен был завершиться.
Маршрутизация и firewall на входной точке
Форвардинг
Ядро по умолчанию не пересылает пакеты между интерфейсами. Пока это не включено, DNAT работать не будет, и это первое, что стоит проверять при разборе неработающей схемы:
# /etc/sysctl.d/99-forward.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
sysctl --system
sysctl net.ipv4.ip_forward # должно быть 1
Развилка: сохранять реальный IP клиента или нет
Это главное решение в схеме, и принимать его надо осознанно, потому что от него зависит и конфигурация firewall, и то, что вы увидите в логах.
Когда VPS делает только DNAT, пакет уходит в туннель с исходным адресом клиента нетронутым. Домашняя машина видит настоящий IP — но ответить не может: она отправит ответ по своему маршруту по умолчанию, через домашнего провайдера, с адресом источника, к которому клиент никогда не обращался. Ответ будет отброшен по пути или клиентом. Соединение зависнет на установлении.
Отсюда три рабочих варианта:
| Вариант | Что видит сервис | Цена |
|---|---|---|
| DNAT + SNAT на VPS | адрес туннеля VPS (10.100.0.1) |
простота; реальный IP потерян |
| DNAT + policy routing дома | настоящий адрес клиента | сложнее настройка, разметка соединений |
| Обратный прокси на VPS | адрес VPS + X-Forwarded-For |
только HTTP; TLS терминируется снаружи |
Начинать разумно с первого — он работает всегда и настраивается пятью строками. Второй берут, когда реальный адрес нужен приложению по существу: ограничения по географии, бан по IP, аудит. Третий — когда публикуется только HTTP и хочется, чтобы VPS занимался сертификатами.
nftables на VPS
Вариант с SNAT, публикация HTTP и HTTPS:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
udp dport 51820 accept # WireGuard
iifname "wg0" tcp dport 22 accept # SSH только изнутри туннеля
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "eth0" oifname "wg0" tcp dport { 80, 443 } ct state new accept
# без этого большие ответы не пройдут — см. раздел про MTU
tcp flags syn tcp option maxseg size set rt mtu
}
}
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iifname "eth0" tcp dport { 80, 443 } dnat to 10.100.0.2
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "wg0" ip daddr 10.100.0.2 masquerade
}
}
Существенные детали. Цепочка input с политикой drop защищает саму виртуалку, forward — управляет транзитом; путать их легко, а последствия разные. Правило SSH принимает подключения только с интерфейса wg0: после того как туннель заработал, публичный SSH становится необязательным, и его закрытие убирает основную мишень для перебора паролей. Порт 51820 остаётся единственным открытым наружу, помимо публикуемых.
Порядок действий здесь имеет значение. Правило, оставляющее SSH только внутри туннеля, применяется после того, как туннель проверен и работает, — иначе набор правил запрёт вас снаружи, а зайти изнутри будет ещё нельзя. На арендованной виртуалке это чинится только через консоль в панели провайдера, и хорошо, если она есть.
Две привычки, которые стоят потраченной минуты:
nft -c -f /etc/nftables.conf # проверить синтаксис, не применяя
systemd-run --on-active=5m nft flush ruleset # страховка: откат через 5 минут
Вторая команда ставит отложенный сброс правил: если после применения связь потерялась, через пять минут firewall очистится сам. Когда всё в порядке, таймер снимается через systemctl stop по имени из вывода команды.
Сохранение реального адреса клиента
Если выбран второй вариант, SNAT с VPS убирается, а на домашней машине настраивается возврат ответов через туннель. Механика: соединения, пришедшие из wg0, помечаются меткой в conntrack, метка восстанавливается на исходящих пакетах, и по ней срабатывает отдельное правило маршрутизации.
#!/usr/sbin/nft -f
table inet mangle {
chain prerouting {
type filter hook prerouting priority mangle; policy accept;
iifname "wg0" ct state new ct mark set 0x1
}
chain output {
type route hook output priority mangle; policy accept;
ct mark 0x1 meta mark set 0x1
}
}
ip rule add fwmark 0x1 lookup 100
ip route add default dev wg0 table 100
Теперь ответы на соединения, пришедшие через туннель, уходят обратно в туннель, а весь остальной трафик машины продолжает ходить через домашнего провайдера. Хранить это надо не в командах, а в конфигурации сети — в systemd-networkd через RoutingPolicyRule и [Route], либо в PostUp-строках wg-quick.
PF, если входная точка на FreeBSD
Здесь важна версия, и это тот случай, когда конфигурация из статьи трёхлетней давности просто не загрузится. FreeBSD 14 и старше используют синтаксис трансляции, унаследованный от OpenBSD 4.5: отдельные правила rdr и nat со стрелкой. В FreeBSD 15 подтянут современный синтаксис OpenBSD, где трансляция стала модификатором обычного правила — rdr-to и nat-to.
FreeBSD 14 и раньше:
ext_if = "vtnet0"
tun_if = "wg0"
internal = "10.100.0.2"
rdr pass on $ext_if proto tcp from any to any port { 80, 443 } -> $internal
nat on $tun_if from any to $internal -> ($tun_if)
pass out on $tun_if
FreeBSD 15:
ext_if = "vtnet0"
tun_if = "wg0"
internal = "10.100.0.2"
pass in quick on $ext_if proto tcp to port { 80, 443 } rdr-to $internal
pass out on $tun_if to $internal nat-to ($tun_if)
Скобки вокруг имени интерфейса — не украшение: они означают «взять адрес динамически» и нужны там, где адрес интерфейса может смениться. Форвардинг включается через net.inet.ip.forwarding=1 в /etc/sysctl.conf, а проверка набора правил делается как pfctl -nf /etc/pf.conf.
Реальный адрес клиента и где терминировать TLS
Симптом «в логах у всех один и тот же адрес» имеет две разные причины, и лечатся они по-разному.
Если на VPS стоит SNAT, адрес теряется на сетевом уровне, и никакими заголовками его не вернуть — информации об оригинальном источнике в пакете просто нет. Решение — либо перейти на схему с policy routing, либо поставить на VPS обратный прокси, который добавит адрес в заголовок.
Если на VPS стоит обратный прокси, адрес теряется потому, что соединение к домашней машине устанавливает прокси от своего имени. Но здесь информация не утрачена: прокси знает настоящий адрес и передаёт его в X-Forwarded-For. Дальше вопрос в том, доверяет ли внутренний сервер этому заголовку и правильно ли настроена цепочка — тема разобрана в заметке про обратный прокси, там же про то, почему доверять X-Forwarded-* можно только от контролируемых адресов.
Для не-HTTP протоколов заголовков нет, и вместо них используется PROXY protocol: прокси перед началом обмена отправляет короткий заголовок с оригинальными адресами и портами. Работает на уровне TCP, поддерживается nginx (модуль stream), HAProxy и большинством современных серверов приложений. Включать его нужно с обеих сторон согласованно — принимающая сторона обязана ожидать заголовок, иначе он попадёт в поток как мусорные байты и сломает протокол.
Где терминировать TLS — отдельное решение с ясным критерием: доверяете ли вы провайдеру VPS.
Терминация на VPS удобнее: сертификаты выпускаются там, где виден порт 80 и куда указывает DNS, ACME работает без дополнительных ухищрений, внутрь туннеля идёт обычный HTTP. Но приватный ключ и расшифрованный трафик находятся на арендованной машине, к которой у провайдера есть физический доступ.
Сквозная терминация на домашней машине означает, что VPS проксирует TLS вслепую, не имея ключа. На уровне TCP это делается пробросом порта 443 без разбора содержимого; ACME при этом требует либо DNS-01, либо проброса 80-го порта внутрь. Это правильный вариант для чувствительных данных и лишняя сложность для панели управления торрент-клиентом.
Альтернативы
Самодельная схема — не единственный и не всегда лучший путь.
| Решение | Что нужно | Свой домен | Область | Когда честно лучше |
|---|---|---|---|---|
ssh -R |
только SSH-доступ к VPS | да | один-два порта | разовая задача, ничего не хочется настраивать |
| frp | VPS + демон с обеих сторон | да | TCP/UDP/HTTP, P2P-режим | нужен проброс портов, но не нужен L3-туннель |
| Tailscale | ничего своего | Funnel, ограниченно | mesh между своими устройствами | личный доступ, а не публикация |
| Headscale | свой сервер управления | нет Funnel | то же, но без внешней зависимости | mesh без доверия внешнему сервису |
| Cloudflare Tunnel | ничего своего | да | HTTP(S) | нет VPS и не нужен медиатрафик |
ssh -R — самый короткий путь: ssh -N -R 8080:localhost:80 vps открывает на VPS порт, ведущий на локальный сервис. По умолчанию проброшенный порт слушает только на loopback, так что для публикации наружу на сервере нужен GatewayPorts yes (или clientspecified) в sshd_config. Обвязка обязательна: голый ssh умирает вместе с сетью и не возвращается, поэтому используют autossh с ServerAliveInterval либо юнит systemd с Restart=always. Годится для разовых задач и административного доступа; для постоянной публикации проигрывает WireGuard по накладным расходам и по устойчивости.
frp — специализированный демон обратного проксирования: frps на VPS, frpc дома. Умеет TCP, UDP, HTTP и HTTPS с виртуальными хостами, имеет режим stcp с предварительным ключом и xtcp с прямым P2P-соединением между клиентами. Разумный выбор, когда задача — именно опубликовать несколько сервисов, а полноценная L3-связность между сетями не нужна.
Tailscale и Headscale решают в первую очередь другую задачу — mesh-сеть между вашими устройствами с автоматическим обходом NAT. Публикация наружу у Tailscale называется Funnel и работает только по HTTPS. Существенная деталь для тех, кто рассматривает самостоятельный хостинг: в Headscale, открытой реализации сервера управления, Funnel не реализован. То есть Headscale даёт независимость от внешнего сервиса, но публиковать сервисы наружу с ним придётся тем же способом, что и в этой статье.
Cloudflare Tunnel убирает необходимость в VPS вообще: демон cloudflared на домашней машине устанавливает исходящее соединение к сети Cloudflare, публичных портов не открывается ни одного. Это лучшее решение по безопасности из перечисленных — публичной поверхности атаки просто нет. Ограничение существенное и касается ровно медиасерверов: правило о непропорциональной доле не-HTML-контента, раньше жившее в разделе 2.8 пользовательского соглашения, перенесено в отдельные условия для CDN, но продолжает действовать для трафика, проходящего через CDN, а публичные маршруты Tunnel идут именно через него. Видео и крупные файлы, размещённые вне сервисов Cloudflare, под ограничение подпадают. Для панелей, API и обычных сайтов — отличный вариант, для раздачи медиатеки наружу — нет.
Грабли
MTU и фрагментация
Самая коварная проблема схемы, потому что она проявляется избирательно. Симптом: короткие запросы проходят, страницы открываются, а скачивание больших файлов виснет намертво; ping работает, ping -s 1400 — нет.
Механика такая. Пакет, идущий в туннель, обрастает внешним заголовком: IP, UDP, служебные поля WireGuard и метка аутентификации. wg-quick берёт MTU маршрута до эндпоинта (или 1500 по умолчанию) и вычитает 80 байт — отсюда типовые 1420 на интерфейсе wg0. Число 80 взято по худшему случаю: 40 байт заголовка IPv6, 8 UDP, 16 служебных полей WireGuard и 16 байт тега Poly1305. Для IPv4 накладные расходы на 20 байт меньше, так что 1420 — консервативная оценка.
Проблема возникает, когда где-то на пути MTU оказывается ещё меньше — PPPoE у провайдера, дополнительный туннель, экзотическая сеть у клиента. Отправитель узнаёт об этом через ICMP-сообщение «требуется фрагментация», и если этот ICMP отфильтрован (а фильтруют его повсеместно, «на всякий случай»), обнаружение MTU пути ломается: отправитель шлёт большие пакеты, они молча отбрасываются, соединение зависает. Явление известно как чёрная дыра PMTU.
Надёжное лекарство — не полагаться на ICMP, а править MSS в SYN-пакетах на входной точке, приводя его к MTU исходящего маршрута. Это то самое правило из набора выше:
tcp flags syn tcp option maxseg size set rt mtu
Диагностика — поиск максимального проходящего размера пакетом с запретом фрагментации:
ping -M do -s 1400 -c 2 10.100.0.2 # уменьшать, пока не начнёт проходить
ip link show wg0 | grep -o 'mtu [0-9]*'
tracepath 10.100.0.2 # покажет, где MTU уменьшается
Если после MSS-клампинга проблема осталась, MTU на wg0 понижается вручную через параметр MTU в конфигурации — 1380 или 1360 решают почти все случаи ценой небольшой потери эффективности.
Лимиты трафика
Тарифы дешёвых VPS почти всегда включают квоту: от терабайта в месяц у бюджетных провайдеров. Превышение стоит денег либо приводит к обрезанию скорости до символической. Считать надо реалистично: один вечер просмотра фильма в 1080p снаружи — это 5–10 ГБ, и месячная квота в 1 ТБ исчерпывается парой активных зрителей.
Мониторинг ставится сразу, а не после первого счёта:
vnstat -i eth0 -m # помесячная статистика
nft list counters # если счётчики заведены в правилах
Вывод для медиасервера: раздавать видео наружу через такую схему — плохая идея по деньгам и по полосе. Разумнее ограничить публикацию управляющими интерфейсами, а собственно доступ к медиа оставить внутри VPN.
Безопасность
Главный сдвиг модели угроз: VPS становится единственной публичной поверхностью, и всё, что на нём открыто, открыто всему интернету.
Минимум открытых портов — 51820/udp для туннеля и то, что публикуется по существу. SSH после поднятия туннеля переводится на прослушивание изнутри wg0 либо вовсе на адрес туннеля через ListenAddress 10.100.0.1 в sshd_config: тогда перебор паролей снаружи технически невозможен. Парольная аутентификация отключается в пользу ключей.
Разделение сетей важнее, чем кажется. Компрометация VPS не должна давать доступ ко всей домашней сети — а даёт, если AllowedIPs на домашней стороне открывает подсеть целиком и firewall дома пропускает всё из wg0. Правильная настройка ограничивает доступ из туннеля конкретными адресами и портами:
# на домашней машине: из туннеля можно только к опубликованным сервисам
iifname "wg0" tcp dport { 80, 443 } accept
iifname "wg0" drop
Публикуемое приложение должно иметь собственную аутентификацию. Схема с VPS не добавляет никакой защиты — она ровно наоборот выносит сервис в интернет, и панель без пароля будет найдена сканерами в течение суток.
Наконец, обновления. Входная точка — машина, которую обязательно надо держать в актуальном состоянии и желательно с автоматической установкой обновлений безопасности, потому что именно она принимает удар первой.
Источники
- WireGuard — wg(8) —
AllowedIPs,PersistentKeepaliveи рекомендованные 25 секунд - WireGuard — wg-quick(8) и исходник
wg-quick/linux.bash— автоопределение MTU как «MTU маршрута минус 80» - Документация ядра Linux: сетевая подсистема — форвардинг, conntrack и его параметры
- nftables wiki — приоритеты хуков, синтаксис DNAT/SNAT и MSS-клампинга; приведённые наборы правил проверены
nft -c -fна nftables 1.0.9 - FreeBSD: pf.conf(5) — синтаксис трансляции; расхождение между ветками проверено по дереву исходников
stable/14(правилаrdr/nat) иstable/15(rdr-to/nat-to) - frp — README — типы прокси, режимы
stcpиxtcp - Tailscale Funnel и Headscale — публикация наружу и её отсутствие в открытой реализации сервера управления
- Cloudflare: доставка видео и обновление условий использования — перенос ограничения на не-HTML-контент в условия для CDN
- PROXY protocol — спецификация HAProxy — передача адреса клиента на уровне TCP
Связанные заметки
- Linux — сеть: стек, конфигурация, firewall — nftables, policy routing и сетевые tunables в общем виде
- Обратный прокси и TLS: nginx vs Caddy — что делать с трафиком после того, как он попал внутрь; доверие к
X-Forwarded-* - OpenVPN против WireGuard — выбор туннеля и разбор
AllowedIPsкак множества маршрутов - Медиасервер: Transmission + Sonarr/Radarr + Plex — типовой набор сервисов, ради которых схема и строится, и причина считать трафик
- SSH углублённо — обратные туннели
-R,GatewayPortsи ограниченные ключи для входной точки - FreeBSD — bhyve: виртуализация после jails — изолированный мост с NAT для виртуальных машин, та же конструкция
- AEAD: аутентифицированное шифрование, nonce и лимиты — откуда берутся 16 байт тега Poly1305 в расчёте MTU туннеля
- Обмен ключами: X25519, KEM, вывод ключей и привязка к транскрипту — что происходит в том самом рукопожатии, по времени которого проверяется здоровье туннеля
Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.
Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.