MAATRIX / Блог / VPN-сервер за NAT: проброс портов и особые случаи

VPN-сервер за NAT: проброс портов и особые случаи

MAATRIX

Вы подняли WireGuard или OpenVPN дома или в офисе, конфиг выглядит правильно, а клиент снаружи не подключается — таймаут на handshake, «connection refused» или просто тишина. В девяти случаях из десяти причина не в самом VPN, а в том, что сервер сидит за NAT: у него нет собственного публичного IP, и входящий трафик просто не знает, куда идти. Дальше — рабочие способы решить это: от обычного проброса порта на роутере до реверс-туннеля через внешний VPS для случаев, когда провайдер не даёт белый IP вообще.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Сначала выясните, за каким NAT вы стоите

Прежде чем настраивать проброс, нужно понять, с чем вы имеете дело — это не всегда «просто роутер».

Сравните IP на самом сервере с тем, что видит внешний мир:

# На сервере
ip addr show | grep inet
# или для клиента за роутером
curl -4 ifconfig.me

Затем зайдите в веб-интерфейс роутера и посмотрите его WAN IP (обычно раздел «Интернет» → «Статус подключения» или «Internet» → «Status»). Возможны три ситуации:

  • WAN IP роутера совпадает с тем, что показал curl ifconfig.me — у вас один уровень NAT, роутер домашний/офисный, публичный IP есть, проброс портов сработает штатно.
  • WAN IP роутера — приватный адрес (10.x.x.x, 172.16–31.x.x, или из диапазона 100.64.0.0/10) — вы за двойным NAT или CGNAT провайдера. Проброс на своём роутере ничего не даст, потому что перед вами есть ещё один слой NAT, которым вы не управляете.
  • WAN IP меняется при каждой перезагрузке роутера — это отдельная проблема динамического IP, она решается DDNS и не отменяет проброс, но усложняет схему с сертификатами и белыми списками.

Если попали во второй сценарий — сразу переходите к разделу про CGNAT ниже, проброс портов вас не спасёт, сколько бы вы ни возились с настройками роутера.

Проброс портов на роутере: классический способ

Если публичный IP есть и проблема только в том, что роутер не пускает трафик внутрь, — это обычный port forwarding (DNAT).

Сначала закрепите за сервером статический локальный IP — либо через DHCP-резервацию по MAC-адресу, либо статикой на самом сервере. Без этого проброс слетит после ребута сервера или роутера, когда DHCP выдаст другой адрес.

На бытовых роутерах (Keenetic, TP-Link, ASUS и подобные) логика одна и та же, меняются только названия пунктов меню:

  • Keenetic: «Интернет-фильтр» → «Переадресация» (Port Forwarding), указываете внешний порт, внутренний IP и порт, протокол UDP/TCP.
  • TP-Link/ASUS: «NAT Forwarding» → «Virtual Servers» / «Port Forwarding», аналогично.

Для WireGuard пробрасываете UDP 51820 (или свой кастомный порт) на внутренний IP сервера. Для OpenVPN — TCP или UDP 1194, в зависимости от того, какой протокол выбрали в конфиге сервера.

На MikroTik проброс делается правилом NAT напрямую:

/ip firewall nat add chain=dstnat protocol=udp dst-port=51820 \
  in-interface=ether1-wan action=dst-nat to-addresses=192.168.88.10 to-ports=51820 \
  comment="WireGuard forward"

/ip firewall filter add chain=forward protocol=udp dst-port=51820 \
  dst-address=192.168.88.10 action=accept comment="Allow WireGuard"

Обратите внимание на второе правило — одного DNAT часто недостаточно, если у вас есть отдельная политика forward-цепочки, которая по умолчанию всё режет.

Если сервер в облаке за виртуальным NAT-шлюзом (некоторые облачные провайдеры по умолчанию сажают инстансы в приватную подсеть) — проброс делается не в панели роутера, а в security group / файрволе облака: привяжите публичный IP к инстансу и откройте нужный порт в правилах группы безопасности отдельно от правил ОС. На обычном VPS с реальным белым IP такой прослойки нет, и порт, открытый в файрволе ОС, сразу доступен извне. После проброса проверяйте порт именно снаружи — локальная проверка почти всегда лжёт, подробнее в статье про проверку открытых портов.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

UPnP: автоматический проброс без ручной настройки

Если роутер поддерживает UPnP (Universal Plug and Play) и он включён, сервер может попросить роутер открыть порт сам — без похода в веб-интерфейс. Это удобно, но не всегда надёжно и не всегда безопасно.

Проверить и открыть порт вручную с сервера можно утилитой miniupnpc:

sudo apt install miniupnpc
upnpc -l                                  # список текущих проброшенных портов
upnpc -a 192.168.1.10 51820 51820 UDP     # добавить проброс

Некоторые VPN-демоны (например, часть реализаций OpenVPN-клиентских роутеров, торрент-клиенты) умеют дергать UPnP автоматически при старте — тогда ручной команды не нужно, проброс появляется и исчезает вместе с процессом.

Минусы, из-за которых на постоянку UPnP не рекомендую: многие бюджетные и провайдерские роутеры отключают его по умолчанию или не поддерживают вовсе (тогда upnpc -l просто не найдёт шлюз); проброс живёт, пока жив запросивший его процесс или до истечения lease-времени (обычно час-два), и после перезапуска без переоткрытия правила порт закрывается сам; любое приложение в локальной сети теоретически может попросить роутер открыть произвольный порт — это общая особенность UPnP как протокола, а не что-то специфичное для VPN.

Практический вывод: UPnP хорош для быстрой проверки «а заработает ли вообще», но для постоянного VPN-сервера статический проброс из предыдущего раздела надёжнее.

Двойной NAT и CGNAT: когда проброс невозможен

CGNAT (Carrier-Grade NAT) — это когда провайдер сам стоит за NAT и раздаёт клиентам не публичные, а приватные IP из общего пула, экономя дефицитные IPv4-адреса. Типично для мобильных операторов и части фиксированных провайдеров, особенно там, где белый IP — платная опция или её вообще не продают частным лицам.

Определить CGNAT просто: WAN-адрес на роутере не совпадает с тем, что показывает curl ifconfig.me, и часто лежит в диапазоне 100.64.0.0/10 — это специально зарезервированный блок именно для CGNAT (RFC 6598). Если видите такой адрес — проброс портов на своём роутере физически не сработает, потому что вы не единственный, кто сидит за этим внешним IP, и провайдер не даёт вам управлять его NAT-таблицей.

Варианты в этой ситуации: запросить у провайдера статический публичный IP (у многих операторов это отдельная услуга — иногда бесплатная по запросу, иногда платная опция в личном кабинете, начинать стоит именно с этого); если публичный IP не дают в принципе (частая практика у мобильных операторов) — реверс-туннель через внешний сервер с белым IP, разбираем его ниже. DDNS здесь не поможет — это частое заблуждение: сервис вроде DuckDNS решает проблему «IP меняется», но не «IP не публичный». За CGNAT DDNS будет исправно резолвить домен в тот же недоступный извне адрес.

Реверс-туннель через внешний VPS: универсальный обход

Идея простая: вместо того чтобы пытаться пробить NAT снаружи внутрь, сервер сам инициирует исходящее соединение к VPS с публичным IP, а VPS уже перенаправляет входящий трафик клиентов внутрь этого туннеля. Исходящие соединения NAT не блокирует практически никогда, это и используется.

Для UDP-протоколов вроде WireGuard самый предсказуемый способ — сделать сам WireGuard транспортом туннеля, а сверху UDP-релеем перенаправить внешний порт на домашний узел.

На VPS (публичный IP, недорогой инстанс подойдёт с запасом) поднимаете обычный WireGuard-интерфейс, где домашний сервер выступает клиентом:

# /etc/wireguard/wg0.conf на VPS
[Interface]
Address = 10.20.0.1/24
ListenPort = 51821
PrivateKey = <приватный ключ VPS>

[Peer]
# Домашний сервер
PublicKey = <публичный ключ домашнего сервера>
AllowedIPs = 10.20.0.2/32

На домашнем сервере — обычный клиентский конфиг с постоянным keepalive, чтобы соединение не рвалось NAT-таблицей роутера или провайдера по таймауту:

# /etc/wireguard/wg0.conf на домашнем сервере
[Interface]
Address = 10.20.0.2/24
PrivateKey = <приватный ключ домашнего сервера>

[Peer]
PublicKey = <публичный ключ VPS>
Endpoint = <публичный IP VPS>:51821
AllowedIPs = 10.20.0.1/32
PersistentKeepalive = 25

Теперь есть приватный туннель 10.20.0.0/24 между VPS и домашним сервером, и поднимается он изнутри — NAT дома для него прозрачен. Дальше нужно, чтобы реальные VPN-клиенты, подключающиеся к вашему рабочему VPN-серверу (тому же WireGuard, но на порту 51820, отдельным инстансом), достигали домашней машины через этот туннель. Проще всего пробросить внешний порт на VPS через socat, потому что честный DNAT здесь не годится — трафик после туннеля уже не «внешний», а внутренний для VPS:

sudo apt install socat
socat UDP4-LISTEN:51820,fork,reuseaddr UDP4:10.20.0.2:51820 &

И на VPS отдельно откройте порт 51820/udp в файрволе для внешних клиентов. Клиенты подключаются к VPS на 51820, socat перекладывает пакеты в туннель, туннель доставляет их на домашний сервер — а домашний сервер отвечает тем же путём назад. Задержка вырастет на один лишний хоп, но для большинства сценариев (личный доступ, обход блокировок, доступ к домашней сети) это не критично.

Для TCP-based решений (OpenVPN в режиме TCP, SoftEther, часть настроек Outline) даже проще — подойдёт классический SSH reverse tunnel:

autossh -M 0 -N -R 0.0.0.0:1194:127.0.0.1:1194 user@vps-ip \
  -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \
  -o "ExitOnForwardFailure=yes"

Команда выполняется на домашнем сервере, а GatewayPorts yes должен быть включён в /etc/ssh/sshd_config на VPS — иначе туннель забиндится только на loopback VPS и снаружи будет недоступен.

Если сценарий постоянный, а не разовый тест, для этой задачи логичнее взять отдельный небольшой VPS именно под роль публичной точки входа — брать под неё производительный тариф не нужно, важны только стабильный белый IP и низкий пинг до основной массы ваших клиентов. Как поднять сам WireGuard на такой машине с нуля, если делаете это впервые — в отдельной статье про установку WireGuard на VPS.

Автозапуск и надёжность туннеля

Ручной запуск команды в терминале умирает при первом разрыве сессии — для рабочей схемы нужен systemd-юнит с автоперезапуском.

Для WireGuard автозапуск встроен, достаточно:

sudo systemctl enable --now wg-quick@wg0

Для SSH-туннеля через autossh — отдельный юнит:

# /etc/systemd/system/reverse-tunnel.service
[Unit]
Description=Reverse SSH tunnel to VPS
After=network-online.target
Wants=network-online.target

[Service]
User=tunneluser
ExecStart=/usr/bin/autossh -M 0 -N -R 0.0.0.0:1194:127.0.0.1:1194 user@vps-ip \
  -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \
  -o "ExitOnForwardFailure=yes" -i /home/tunneluser/.ssh/id_ed25519
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now reverse-tunnel.service

Для socat-релея на VPS — аналогичный юнит с ExecStart, указывающим на команду socat, и Restart=always.

Отдельно проверьте, что провайдерский роутер не убивает долгоживущие UDP-сессии агрессивным таймаутом NAT-таблицы — PersistentKeepalive = 25 обычно с запасом перекрывает типичные таймауты (30–60 секунд у большинства провайдеров), но если туннель периодически «отваливается» без видимой причины, это первое, что стоит проверить, вместе с общими причинами из статьи про частые ошибки WireGuard на сервере. Критерии выбора узла под роль такой точки входа — в статье про VPS для VPN и обхода блокировок.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Как узнать, что у меня именно CGNAT, а не просто роутер плохо настроен?

Сравните WAN IP роутера с результатом curl ifconfig.me с устройства за этим роутером. Если адреса разные — между вами и интернетом есть ещё один NAT. Особенно характерен диапазон 100.64.0.0/10.

UPnP включён, но проброса всё равно нет — почему?

Либо роутер стоит вторым за CGNAT-адресом провайдера (UPnP бессилен перед внешним NAT), либо реализация UPnP на прошивке отключена или ограничена. Проверьте upnpc -l — если утилита не находит IGD-шлюз, UPnP на этом роутере недоступен.

Реверс-туннель через VPS замедлит VPN?

Добавится один лишний хоп и немного задержки — насколько именно, зависит от географии VPS, универсальной цифры нет, надо измерять на своей паре точек. Для повседневных задач прирост некритичен, но для пинг-чувствительных сценариев размещайте VPS ближе к клиентам, а не к дому.

Можно ли обойтись без второго сервера, если провайдер не даёт белый IP?

Только через сторонние relay-сервисы (некоторые mesh-VPN с встроенным relay-функционалом), но это чужая инфраструктура с чужими лимитами и доверием к оператору. Собственный VPS даёт полный контроль над каналом.

Нужно ли открывать порт и в файрволе ОС, и пробрасывать на роутере?

Да, это два разных уровня: проброс говорит внешнему миру, куда слать пакеты внутри сети, а файрвол ОС (ufw/iptables) решает, пропускать ли их дальше. Забытое ufw allow — частая причина, когда проброс настроен верно, а подключения всё равно не проходят.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →