Есть сервер (далее — локальный) с WireGuard-сервером (wg0), к которому подключён клиент (телефон, ноутбук). Есть промежуточный прокси-сервер, доступный из туннеля. Есть внешний прокси-сервер, через который нужно выпускать трафик клиента в интернет.
Задача: завернуть весь TCP-трафик клиента (порты 80 и 443) через цепочку прокси, не затрагивая существующий туннель между серверами.
Схема
Клиент (10.X.X.3)
│ WireGuard
▼
Локальный сервер (10.X.X.2)
│ REDIRECT tcp 80/443 → :12345
│ DROP udp 443 (QUIC)
▼
3proxy tcppm :12345
│ parent → 10.X.X.1:3128
▼
Промежуточный прокси (10.X.X.1:3128)
│ parent → 10.Y.Y.2:3128
▼
Внешний прокси (10.Y.Y.2:3128)
│ NAT
▼
Интернет
Предварительные требования
- WireGuard установлен,
wg0поднят, клиент подключён. Вwg0.confесть peer клиента сAllowedIPs = 10.X.X.3/32. - 3proxy собран из master-ветки (в релизе 1.0.0 из
.debкомандыtransparentнет — её добавили в 1.0.1+). Проверить:3proxy -? 2>&1 | grep -i transparent. Если пусто — версия старая,transparentне заработает. ip_forward = 1:sysctl net.ipv4.ip_forwardдолжен вернуть1.- Известны IP всех участников в туннеле:
10.X.X.3— клиент10.X.X.2— локальный сервер10.X.X.1— промежуточный прокси10.Y.Y.2— внешний прокси
- NAT для подсети туннеля (
10.X.X.0/24) настроен на выход через физический интерфейс (enp3s0).
Пошаговая настройка
Шаг 1: Конфиг 3proxy (/etc/3proxy/3proxy.cfg)
nserver 8.8.8.8 nscache 65536 timeouts 1 5 30 60 180 1800 15 60 log /var/log/3proxy/3proxy.log D rotate 30 auth iponly allow * 10.X.X.3,192.168.0.0/24,127.0.0.1 parent 1000 connect 10.X.X.1 3128 deny * proxy -p3128 -a socks -p1080 transparent tcppm -e10.X.X.2 12345 127.0.0.1 11111 notransparent
Ключевые моменты:
parent 1000 connect 10.X.X.1 3128— все запросы уходят на промежуточный прокси.transparent+tcppm— приём перенаправленного трафика на порт12345.-e10.X.X.2— source IP для исходящих соединений к parent. Должен быть IP локального сервера в туннеле, а не физический (иначе пакеты уходят не туда).proxy -p3128— обычный HTTP-прокси (для ПК в локальной сети).socks -p1080— SOCKS5 (опционально).
Шаг 2: Перезапуск 3proxy
systemctl restart 3proxy systemctl is-active 3proxy ss -tlnp | grep -E '3128|1080|12345'
Должны слушаться все три порта.
Шаг 3: nftables — REDIRECT (table ip transparent)
table ip transparent {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
iifname "wg0" ip saddr 10.X.X.3
ip daddr != { 10.0.0.0/8, 127.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 }
tcp dport { 80, 443 } counter redirect to :12345
iifname "wg0" ip saddr 10.X.X.3 udp dport 443 counter drop
}
}
Ключевые моменты:
iifname "wg0"— только трафик из туннеля.ip saddr 10.X.X.3— только от клиента.ip daddr != { ... }— исключить локальные сети (иначе петля).tcp dport { 80, 443 }— только веб-трафик.redirect to :12345— в transparent-прокси 3proxy.udp dport 443 drop— блокировка QUIC. Без этого важные сервисы и программы ходят через UDP и игнорируют REDIRECT.
Шаг 4: nftables — NAT (table ip nat)
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 10.X.X.0/24 oifname "enp3s0" masquerade
}
}
Ключевые моменты:
ip saddr 10.X.X.0/24— вся подсеть туннеля.oifname "enp3s0"— физический интерфейс (заменить на свой).masquerade— подмена source IP на IP сервера.
Шаг 5: UFW
ufw allow in on wg0 to any port 12345 proto tcp ufw allow in on wg0 to any port 3128 proto tcp ufw route allow in on wg0 ufw reload
Ключевой момент: после REDIRECT пакеты попадают в INPUT с iifname = wg0 и dport = 12345. UFW должен их пропустить.
Шаг 6: ip_forward
sysctl -w net.ipv4.ip_forward=1 echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
Почему не работают другие подходы
| Подход | Почему не подходит |
|---|---|
| TPROXY | 3proxy не ставит флаг IP_TRANSPARENT на сокет. TPROXY — для xray, sing-box. |
| REDIRECT через iptables | В Ubuntu 24.04 iptables — обёртка над nftables. Правила уходят в «несовместимую» таблицу. |
DNAT на 127.0.0.1:3128 | 3proxy на 3128 — обычный прокси, ждёт HTTP-запрос, а не transparent-соединение. |
tcppm ... 0 0 | 3proxy падает с code 40. Нужны заглушки 127.0.0.1 11111. |
| Без DROP UDP 443 | многие важные программы используют QUIC (UDP 443), игнорируя REDIRECT для TCP. |
Диагностика
Проверка REDIRECT
nft -a list table ip transparent
Счётчик packets должен расти при трафике от клиента.
Проверка 3proxy
netstat -anp | grep 12345
Должны быть ESTABLISHED от IP клиента.
Проверка parent
curl -x http://10.X.X.1:3128 -s ifconfig.me
Должен вернуть IP внешнего прокси.
Проверка цепочки через локальный 3proxy
curl -x http://127.0.0.1:3128 -s ifconfig.me
Должен вернуть IP внешнего прокси.
Проверка логов 3proxy
tail -20 /var/log/3proxy/3proxy.log*
В логе должны быть строки с байтами в обе стороны (не 0 0):
10.X.X.3:PORT → 10.X.X.1:3128 1234 5678 1 destination_ip
Если видите 0 0 1 — parent недоступен или -e указан неверно.
Проверка QUIC
nft -a list table ip transparent tcpdump -i wg0 udp port 443 -n
Счётчик у правила с udp dport 443 drop должен расти.
Проверка маршрутизации source IP
ip route get 10.X.X.1 from 192.168.0.200 # покажет, что маршрут идёт не через wg0 ip route get 10.X.X.1 from 10.X.X.2 # покажет, что маршрут идёт через wg0
Автозагрузка
Не через nftables.service (сохраняет весь ruleset и ломает UFW). А через PostUp в wg0.conf:
[Interface]
PrivateKey = ...
Address = 10.X.X.2/32
ListenPort = 51820
PostUp = nft add table ip transparent
PostUp = nft add chain ip transparent prerouting { type nat hook prerouting priority -100 \; policy accept \; }
PostUp = nft add rule ip transparent prerouting iifname "wg0" ip saddr 10.X.X.3 ip daddr != { 10.0.0.0/8, 127.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } tcp dport { 80, 443 } redirect to :12345
PostUp = nft add rule ip transparent prerouting iifname "wg0" ip saddr 10.X.X.3 udp dport 443 drop
PostUp = nft add table ip nat
PostUp = nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; policy accept \; }
PostUp = nft add rule ip nat postrouting ip saddr 10.X.X.0/24 oifname "enp3s0" masquerade
PostDown = nft delete table ip transparent
PostDown = nft delete table ip nat
Тогда при подъёме wg0 правила создаются автоматически.
Ограничения решения
- Только TCP 80/443. Другие порты (
8080,8443, игры) не редиректятся. - Только IPv4. IPv6 не обрабатывается.
- QUIC отключён. Важные сервисы работают через TCP — чуть медленнее, но работает.
- Приложения без TCP (некоторые игры, VoIP) — не заработают.
- DNS не заворачивается. Если нужен — добавить правило для UDP/TCP 53.
Откат
nft delete table ip transparent nft delete table ip nat systemctl restart 3proxy
Что проверить в первую очередь, если отвалилось
wg show— поднят лиwg0.systemctl is-active 3proxy— работает ли 3proxy.nft list tables— есть ли таблицыtransparentиnat.
Если таблиц нет — systemctl restart wg-quick@wg0 (правила создадутся через PostUp).
Если 3proxy упал — systemctl restart 3proxy.
Если ничего не помогает — откатить (nft delete table ip transparent; nft delete table ip nat) и настроить заново по шагам.
Итог
Рабочая конфигурация:
- 3proxy с
transparent+tcppmна отдельном порту (12345) - REDIRECT в nftables для TCP 80/443 от клиента
- DROP UDP 443 (QUIC)
- NAT masquerade для подсети туннеля
- UFW разрешает входящие на порты 12345 и 3128
ip_forward = 1
Существующий туннель между серверами не затрагивается.