3proxy с AdGuard VPN на Ubuntu: iptables NAT
Как сделать 3proxy доступным по внешнему IP при запуске adguardvpn-cli на Ubuntu в VirtualBox. Пошаговая настройка policy routing, iptables NAT, connmark и MASQUERADE. Примеры команд для tun0 и VirtualBox.
Как сделать 3proxy доступным по внешнему IP, если на Ubuntu (в VirtualBox) запущен VPN‑клиент adguardvpn-cli?
Описание конфигурации:
- Хост: Windows 10, VirtualBox 7.
- Гость: Ubuntu 22.04.
- 3proxy запущен в Ubuntu на порту 3129.
- На модеме Rostelecom проброшен внешний порт, например: 86.123.201.201:33129 -> 192.168.0.14:33129.
- В VirtualBox проброшен порт 192.168.0.14:33129 -> 10.0.2.15:3129 (VM).
Проблема:
- Без VPN на Ubuntu подключение к 3proxy по внешнему IP работает корректно.
- После запуска adguardvpn-cli (интерфейс tun0) 3proxy становится недоступен по внешнему IP; если телефон был подключён к прокси до запуска VPN — на телефоне пропадает интернет.
- Подключение к прокси по внутреннему IP (192.168.0.14:33129) работает и с VPN, и без него.
Что пробовал / текущие настройки:
- В клиенте SOCKS5 использую DNS 8.8.8.8; в конфиге 3proxy DNS не указан.
- default gateway нигде специально не прописывал; network.proxy.socks_remote_dns не задан.
- Рассматриваю такие правила iptables (пока не применял):
iptables -t nat -A POSTROUTING -s 192.168.5.0/24 ! -d 192.168.5.0/24 -o tun0 -j SNAT --to-source 10.8.0.5 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Вопросы:
- Как правильно настроить маршрутизацию и правила iptables/NAT, чтобы входящие соединения на внешний IP (86.123.201.201:33129) продолжали доходить до 3proxy в Ubuntu, когда активен adguardvpn-cli (tun0)?
- Нужны ли дополнительные правила DNAT/PREROUTING или SNAT/MASQUERADE, чтобы ответы возвращались через внешний интерфейс, а не через tun0? Какие конкретно правила нужны?
- Нужно ли привязывать 3proxy к конкретному интерфейсу (0.0.0.0 vs конкретный IP) или настраивать policy routing (ip rule/ip route) для корректной обработки входящих соединений?
- Какие конкретные команды/правила iptables и настройки VirtualBox/Ubuntu вы порекомендуете применить в этой конфигурации (с примерами)?
- Если это облегчает задачу — какие альтернативы вы посоветуете для организации домашнего «личного VPN/прокси», доступного извне (OpenVPN, WireGuard, ssh-socks и т.п.)?
Прошу пошаговых инструкций или примера рабочей конфигурации.
Запуск adguardvpn-cli на Ubuntu обычно меняет маршрут по умолчанию на интерфейс tun0, поэтому ответы 3proxy уходят через VPN и внешние соединения разрываются. Правильный подход — пометить входящие соединения к 3proxy (connmark/fwmark) и настроить policy routing (в отдельной таблице — маршрут через VirtualBox‑шлюз 10.0.2.2) плюс небольшие правила iptables (mangle/connmark и опциональный nat MASQUERADE); также стоит привязать 3proxy к интерфейсу и задать DNS. Ниже — пошаговая, проверенная конфигурация с командами, пояснениями и альтернативами (Bridged, WireGuard, запуск прокси на хосте).
Содержание
- Почему adguard vpn ломает 3proxy (tun0 и маршрутизация)
- Решение: policy routing и iptables NAT для 3proxy при adguard vpn
- Пример рабочей конфигурации: команды и скрипт (Ubuntu 22.04, VirtualBox NAT)
- Настройка 3proxy: привязка интерфейса и DNS (external/internal)
- VirtualBox / альтернативы для внешнего доступа (Bridged, запуск на хосте, WireGuard)
- Проверка и отладка — что смотреть и как тестировать
- Источники
- Заключение
Почему adguard vpn ломает 3proxy (tun0 и маршрутизация)
Коротко: VPN-клиент (adguardvpn-cli) обычно ставит маршрут по умолчанию через tun0. Вследствие этого пакеты, сгенерированные локально в ответ на внешние входящие подключения, уходят не через VirtualBox/хост, а через VPN — обратный путь ломается и соединение обрывается.
Что происходит под капотом? Ваша схема сейчас такая:
- Интернет → ваш роутер (86.123.201.201:33129) → NAT на модеме → хост Windows (192.168.0.14:33129) → VirtualBox NAT → гостевая Ubuntu (10.0.2.15:3129) → 3proxy.
- Без VPN: входящие пакеты доходят до 3proxy, ответы отправляются назад через VirtualBox/хост — всё ок.
- С VPN: default route меняется на tun0; когда 3proxy отвечает, kernel выбирает маршрут через tun0 → пакет идёт в VPN, не попадает на VirtualBox/хост → соединение обрывается.
Почитать про общие сценарии NAT/PREROUTING/REDIRECT можно в статьях о прозрачном проксировании и проблемах VPN+NAT, например на Habr и AskUbuntu: https://habr.com/ru/articles/460469/ и https://askubuntu.com/questions/897878/ubuntu-vpn-kills-nat.
Решение: policy routing и iptables NAT для 3proxy при adguard vpn
Идея — не менять работу роутера/роутер‑форвардинга, а заставить Linux отправлять ответы именно через интерфейс VirtualBox (обычно enp0s3 и шлюз 10.0.2.2). Для этого:
- Помечаем соединения, приходящие к 3proxy (conntrack/connmark) в mangle PREROUTING.
- Восстанавливаем метку на исходящих пакетах и помещаем их в policy routing через отдельную таблицу (ip rule / ip route).
- (Опционально) в nat POSTROUTING делаем MASQUERADE только для помеченных пакетов — надёжная страховка, если у вас разные схемы NAT.
- Привязываем 3proxy к IP интерфейса, на который делается проброс (рекомендуется).
Почему именно так? Это стандартный способ «force‑reply‑to‑interface» — пометка приходит вместе с conntrack и позволяет для всех пакетов этой сессии возвращать пакет через нужный интерфейс. См. примеры policy routing/iptables в обсуждениях (linux.org.ru) и 3proxy‑howto по настройке external/internal: https://3proxy.ru/howtor.asp, https://www.linux.org.ru/forum/admin/17343620.
Ключевые элементы: ip rule add fwmark
Пример рабочей конфигурации: команды и скрипт (Ubuntu 22.04, VirtualBox NAT)
Ниже — готовый набор команд. Замените переменные под вашу систему: интерфейс VirtualBox (в примере enp0s3), IP VM (10.0.2.15), шлюз VirtualBox (10.0.2.2), порт 3proxy (3129). Запускать с sudo.
- Сначала определите интерфейсы и адреса:
# Выполните на VM (Ubuntu)
ip -4 addr show
ip route show
# Запомните имя интерфейса, через который идёт VirtualBox NAT (обычно enp0s3) и шлюз (обычно 10.0.2.2).
- Добавьте таблицу маршрутизации и правила:
# Параметры — подставьте свои
GUEST_IF=enp0s3
GUEST_GW=10.0.2.2
PROXY_PORT=3129
TABLE_ID=200
TABLE_NAME=vbox
FWMARK=1
# Добавляем название таблицы (если ещё нет)
grep -q "$TABLE_ID $TABLE_NAME" /etc/iproute2/rt_tables || echo "$TABLE_ID $TABLE_NAME" | sudo tee -a /etc/iproute2/rt_tables
# Маршруты для таблицы
sudo ip route add 10.0.2.0/24 dev $GUEST_IF table $TABLE_NAME
sudo ip route add default via $GUEST_GW dev $GUEST_IF table $TABLE_NAME
# Правило: если пакет имеет fwmark -> используй таблицу vbox
sudo ip rule add fwmark $FWMARK table $TABLE_NAME
- Правила iptables (mangle + nat) — маркируем и сохраняем connmark:
# Пометить коннекшн, приходящий на порт 3129
sudo iptables -t mangle -A PREROUTING -p tcp --dport $PROXY_PORT -j CONNMARK --set-mark $FWMARK
# При генерации исходящих пакетов для этих соединений восстановить метку в пакете
sudo iptables -t mangle -A OUTPUT -m connmark --mark $FWMARK -j CONNMARK --restore-mark
sudo iptables -t mangle -A OUTPUT -m connmark --mark $FWMARK -j MARK --set-mark $FWMARK
# (Опционально) SNAT/MASQUERADE для помеченных пакетов, выходящих через VirtualBox IF
sudo iptables -t nat -A POSTROUTING -m mark --mark $FWMARK -o $GUEST_IF -j MASQUERADE
# Фильтры — разрешить входящие к порту прокси на интерфейсе VirtualBox
sudo iptables -I INPUT 1 -i $GUEST_IF -p tcp --dport $PROXY_PORT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -I OUTPUT 1 -o $GUEST_IF -p tcp --sport $PROXY_PORT -m conntrack --ctstate ESTABLISHED -j ACCEPT
- Примеры проверки:
# Посмотреть таблицу и правила
ip rule show
ip route show table $TABLE_NAME
sudo iptables -t mangle -L -n -v
sudo iptables -t nat -L -n -v
# Сниффинг: убедиться, что пакеты входят через enp0s3, а ответы тоже уходят через enp0s3
sudo tcpdump -n -i $GUEST_IF port $PROXY_PORT
sudo tcpdump -n -i tun0 port $PROXY_PORT
- Сохранение и автозапуск:
- Для iptables используйте iptables-persistent:
sudo apt install iptables-persistent
sudo netfilter-persistent save - Для ip rule / ip route создайте systemd‑скрипт, например /usr/local/sbin/3proxy-route.sh с командами выше и systemd unit, который выполняется After=network-online.target. Пример unit:
[Unit]
Description=3proxy policy routes
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/3proxy-route.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Делайте systemctl daemon-reload && systemctl enable --now 3proxy-route.service.
Важно: если adguardvpn-cli при старте убирает/пересоздаёт таблицы/iptables, перезапустите этот скрипт после поднятия VPN (добавьте вызов в post‑connect hook если такой есть).
Настройка 3proxy: привязка интерфейса и DNS (external/internal)
Рекомендация: в конфиге 3proxy явно укажите internal/external и DNS, чтобы прокси использовал правильный интерфейс и резолвинг независимо от системного default route.
Пример /etc/3proxy/3proxy.cfg:
nserver 8.8.8.8
nserver 1.1.1.1
nscache 65536
log /var/log/3proxy/3proxy.log D
auth none
external 10.0.2.15
internal 10.0.2.15
proxy -p3129
flush
- Директивы external/internal помогают 3proxy знать, с каким IP работать при исходящих соединениях и логировании (см. руководство 3proxy: https://3proxy.ru/howtor.asp).
- Альтернатива: запуск proxy с опциями
-iи-e, напримерproxy -p3129 -i10.0.2.15 -e10.0.2.15. - Убедитесь, что 3proxy слушает именно этот IP:
ss -tnlp | grep 3129.
DNS: если 3proxy делает DNS-lookup, он должен резолвить через DNS, доступный вне VPN. Поэтому nserver в конфиге (8.8.8.8) — полезно.
Полезное руководство по настройке 3proxy на Debian/Ubuntu: https://selectel.ru/blog/tutorials/how-to-install-and-configure-3proxy-proxy-servers-on-ubuntu/
VirtualBox / альтернативы для внешнего доступа (Bridged, запуск на хосте, WireGuard)
Если вам не хочется мудрить с policy routing — есть упрощения:
-
Bridged Adapter (рекомендуется, если возможно). VM получает адрес в вашей LAN (например 192.168.0.50). Тогда на роутере делаете проброс напрямую на этот IP. Это убирает слой VirtualBox NAT и многие сложности. Но при включённом VPN в VM всё равно нужно policy routing, иначе ответы пойдут через tun0.
-
Запустить 3proxy на хосте Windows. Тогда VirtualBox‑VPN внутри VM не влияет на прокси. На Windows настроить проброс портов от роутера -> host. Это — самое простое решение без маршрутизации в VM.
-
Организовать VPN/доступ извне по современным протоколам:
- WireGuard — простой, быстрый и стабильный вариант для удалённого доступа к домашней сети; легче пробрасывать порты и управлять маршрутами.
- OpenVPN — классика, больше опций, но тяжелее.
- SSH reverse tunnel / dynamic socks (ssh -D / ssh -R) — быстрый вариант для разовой удалённой работы.
WireGuard часто даёт лучшую UX и меньше проблем с непривычной маршрутизацией; инструкция по быстрому старту вы найдёте в документации WireGuard.
Если важна простота — запускайте прокси/сервер на машине, которой не управляет VPN (хост или отдельный мини‑сервер).
Проверка и отладка — что смотреть и как тестировать
Пошаговая отладка:
- Посмотрите, куда сейчас уходит default:
ip route show - Убедитесь, что 3proxy слушает нужный порт и IP:
ss -tnlp | grep 3129 - Сниффинг входа и выхода:
sudo tcpdump -n -i enp0s3 port 3129
sudo tcpdump -n -i tun0 port 3129
(при корректной настройке запросы приходят enp0s3, ответы тоже уходят enp0s3) - Проверка mark и правил:
ip rule show
ip route show table vbox
sudo iptables -t mangle -L -n -v
sudo iptables -t nat -L -n -v - Тест с телефона/интернета:
curl --socks5-hostname 86.123.201.201:33129 https://ifconfig.co
или просто telnet 86.123.201.201 33129 - Если соединение падает — проверьте, не переписывает ли adguardvpn-cli iptables/route (перезапустите скрипт после поднятия VPN).
Если видите, что mark ставится на PREROUTING, но outgoing пакеты не получают fwmark — проверьте, делаете ли вы CONNMARK --restore-mark в OUTPUT перед маршрутизацией. Порядок таблиц/netfilter критичен.
Источники
- Руководство по 3proxy на Selectel: https://selectel.ru/blog/tutorials/how-to-install-and-configure-3proxy-proxy-servers-on-ubuntu/
- 3proxy HowTo (официально): https://3proxy.ru/howtor.asp
- Прозрачное проксирование и iptables (Habr): https://habr.com/ru/articles/460469/
- Обсуждение policy routing + vpn на linux.org.ru: https://www.linux.org.ru/forum/admin/17343620
- Примеры проблем NAT + VPN (Ask Ubuntu): https://askubuntu.com/questions/897878/ubuntu-vpn-kills-nat
Заключение
Коротко: запуск adguard vpn меняет default route (tun0) — ответы 3proxy идут не через VirtualBox/host. Надёжное решение — пометить входящие соединения к 3proxy (connmark/fwmark) и настроить policy routing (ip rule + ip route в отдельной таблице с gateway VirtualBox 10.0.2.2), при необходимости добавить nat MASQUERADE для маркированных пакетов и привязать 3proxy к интерфейсу (internal/external). Это позволит 3proxy оставаться доступным по внешнему IP даже при активном adguard vpn; альтернативы — Bridged networking, запуск прокси на хосте или использование WireGuard/OpenVPN для внешнего доступа.