WireGuard вместо SSH-reverse: как я выкинул костыль на три сервиса

🔧 Исходные данные
Роутер и сервер у меня в разных сетях: сервер живёт за чужим NAT без белого IP, а у роутера на даче белый IP есть. Все домашние сервисы наружу торчали через SSH reverse-туннель — sshd на роутере, keepalive каждые 30 секунд, dstnat 443→8443 и 8080→8080. Работало, но жило своей жизнью: одно длинное TCP-соединение, которое надо держать живым, ключ от роутера лежит на сервере, а TCP-поверх-TCP на потере пакетов ведёт себя так себе.
Как и что делали
Завёл WireGuard — и упёрся в три грабли.
Грабли 1: интерфейс «есть», а трафика нет. Поднял wg0, handshake 0, пакеты не идут. Оказалось, интерфейс висел без приватного ключа — туннель формально создался, но обменяться ключами не мог.
Грабли 2: wg-quick в LXC падает в segfault. Непривилегированный контейнер без /dev/net/tun. Поднимаю руками через wg setconf + свой systemd-юнит:
wg setconf wg0 /etc/wireguard/wg0.conf
ip link set wg0 up
ip addr add 10.100.0.2/30 dev wg0
Грабли 3: wg setconf не создаёт маршрут до LAN. Туннель поднялся, но до локальной сети за роутером пакеты не доезжали. Добавил маршрут руками:
ip route add 10.0.0.0/24 dev wg0
Отдельный сюрприз — реальные IP клиентов. Снял masquerade на роутере, чтобы видеть, кто стучится, — и всё легло. WG резал входящие пакеты, чей source не в AllowedIPs. Лечение — расширить AllowedIPs до 0.0.0.0/0 и добавить policy-routing, чтобы ответы Caddy уходили обратно в туннель:
ip rule add from 10.100.0.2 lookup 200
ip route add default via 10.100.0.1 dev wg0 table 200
На роутере — peer и dstnat прямо в туннель:
/interface wireguard peers add interface=wg-lab allowed-address=10.100.0.2/32
/ip firewall nat add chain=dstnat protocol=tcp dst-port=443 action=dst-nat to-addresses=10.100.0.2
Что получили
- SSH-reverse снесён: ни sshd на роутере, ни keepalive, ни dstnat 443→8443/8080→8080
- Порты на роутере теперь dstnat-ятся прямо в туннель: 443→10.100.0.2:443
- Сайт отвечает за ~100 мс, реальные IP клиентов видны в логах, ACL работают
- Один сервис вместо трёх, ноль keepalive, UDP вместо TCP-поверх-TCP
Мораль
WireGuard — это просто, пока не начнёшь. Но когда выкидываешь костыль из трёх сервисов и получаешь один файл конфига — оно того стоит.
А у тебя туннели до сих пор на SSH-reverse, или уже переехал на WireGuard?