Files
vpn-raspberry/server/wg0.conf
Maxim 538414f2c8 Стабильная работа туннеля: anti-RST, --fix-gro, QUIC-блок, автозагрузка
Проверено на живом стенде: 0% потерь на 10.66.66.1 и 8.8.8.8, выход через
сервер (curl -> 95.174.102.77).

Транспорт (устранение разрывов faketcp):
- anti-RST вписан в конфиги вместо хрупкого -a+flush:
  клиент — первой строкой chain input (ip saddr 95.174.102.77 tcp sport 25565 drop),
  сервер — в таблице wgfwd (ip daddr 192.168.31.163 tcp dport 25565 drop, переживает ufw reload).
  Причина: RST от ядра убивал CGNAT-маппинг оператора -> direction timeout и смена порта.
- --fix-gro на обоих концах: чинит дроп GRO «супер-пакетов» (huge packet > max_data_len).

Клиент:
- nftables.conf: flush ruleset (убирает дубли), reject QUIC/UDP 443 (откат браузера на TCP).
- udp2raw-client.service: After=nftables.service (anti-RST применяется до старта udp2raw).

Автозагрузка/порядок (обе службы udp2raw):
- After=network-online.target, Before=wg-quick@wg0.service.

README: раздел 5 «Известные нюансы» (anti-RST vs flush, CGNAT/RST, GRO),
сниппеты и таблицы приведены в соответствие.
2026-07-08 11:35:46 +03:00

38 lines
2.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# СЕРВЕР (Ubuntu, за NAT: enp2s0 = 192.168.31.163, шлюз 192.168.31.1)
# Публичный вход: 95.174.102.77:25565 (TCP) --проброс на роутере--> 192.168.31.163:25565
# (443 не используем — его держит nginx/Gitea; см. udp2raw-server.service)
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.66.66.1/24
ListenPort = 51820
# Приватный ключ Сервера (из файла server_private.key)
PrivateKey = KMcPBI6LAY/NC1zFNYopsvNXqQ8w8ssluDj4yOh3skk=
# Симметрично клиенту: транспорт идёт внутри faketcp, держим запас на оверхед
MTU = 1200
# Всё хозяйство WG держим в отдельной nft-таблице wgfwd, чтобы:
# - не конфликтовать с правилами Docker/UFW в главных таблицах;
# - на PostDown снести одной командой (идемпотентно).
# NAT: маскарадим ТОЛЬКО подсеть туннеля (не трогаем docker и трафик хоста).
PostUp = nft add table ip wgfwd
PostUp = nft add chain ip wgfwd postrouting { type nat hook postrouting priority 100 \; policy accept \; }
PostUp = nft add rule ip wgfwd postrouting ip saddr 10.66.66.0/24 oifname "enp2s0" masquerade
# MSS-clamp для пакетов, входящих В туннель (SYN-ACK от внешних серверов),
# чтобы large-TCP не «залипал» из-за MTU 1200 и заблокированного PMTUD.
PostUp = nft add chain ip wgfwd mangle { type filter hook forward priority -150 \; policy accept \; }
PostUp = nft add rule ip wgfwd mangle oifname "wg0" tcp flags syn tcp option maxseg size set rt mtu
# udp2raw faketcp anti-RST (дубль к флагу -a): прячем входящий транспорт от TCP-стека,
# иначе ядро шлёт RST на faketcp -> туннель рвётся. Матч по СВОЕМУ IP+порту (стабильно,
# не зависит от динамического мобильного IP клиента). Приоритет -300 = раньше ufw/docker.
# udp2raw читает через AF_PACKET (до netfilter), так что drop ему не мешает.
# В своей таблице wgfwd — переживает ufw reload (в отличие от правила -a в table ip filter).
PostUp = nft add chain ip wgfwd prerst { type filter hook input priority -300 \; policy accept \; }
PostUp = nft add rule ip wgfwd prerst ip daddr 192.168.31.163 tcp dport 25565 drop
PostDown = nft delete table ip wgfwd
[Peer]
# Публичный ключ Raspberry Pi (из файла client_public.key)
PublicKey = WWFhoYfIgIhGOsvdJ/F9eWx7hPksrV6riiqo5lFPExI=
AllowedIPs = 10.66.66.2/32