Зачем это нужно
У нас несколько офисов на роутерах Keenetic — и всем нужен единый выходящий IP в России. Без этого целый класс сервисов просто отваливается. Знакомая история, да?
Требование жёсткое: минимум возни на стороне офиса. Никаких клиентских программ, никакого «зайди на каждый компьютер и пропиши конфиг». Только VPN-подключение на самом Keenetic — и всё.
Проблема с обычными VPN
Стандартные решения мы перебрали и отмели — каждое по конкретной причине:
WireGuard (UDP 51820)
OpenVPN
Готовые VPN-сервисы
Наше решение: двойной туннель
В итоге мы сделали двухуровневую систему. Каждый слой — независимый, решает ровно одну задачу. Ломается один — другой продолжает работать.
Уровень 1 — Transport. Keenetic поднимает Cisco AnyConnect на порту 443. Да, обычный HTTPS-порт. Заблокировать его без отключения всего интернета невозможно физически — это мы проверяли на практике не раз.
Уровень 2 — Proxying. На шлюзе трафик от роутеров перехватывается через TPROXY прямо в ядре Linux — без каких-либо агентов на клиентах. Дальше xray прозрачно гонит всё через VLESS-туннель на выходной узел в России. VLESS при этом прикидывается обычным TLS-трафиком Chrome. Снаружи — ничем не отличается.
Что происходит под капотом
Покажу полный путь пакета, когда устройство в офисе открывает любой сайт:
| Шаг 1 | Запрос с устройства (телефон, ноутбук) поступает на Keenetic роутер. |
| Шаг 2 | Keenetic отправляет трафик через OpenConnect туннель на сервер-шлюз. |
| Шаг 3 | На шлюзе iptables перехватывает пакет через механизм TPROXY и помечает его fwmark 0x1 — без изменения содержимого. |
| Шаг 4 | xray получает помеченные пакеты через TPROXY listener (порт 12345) и прозрачно проксирует через VLESS на выходной узел. |
| Шаг 5 | Выходной узел делает реальный запрос в интернет — его IP видят все сайты. |
| Шаг 6 | Ответ идёт обратно по той же цепочке. |
Компоненты системы
| ocserv | Открытая реализация Cisco AnyConnect сервера. Принимает подключения от Keenetic на порту 443 TCP+UDP. Keenetic имеет встроенную поддержку этого протокола — никаких доп. прошивок. |
| xray (TPROXY) | Работает в двух режимах одновременно: TPROXY listener на порту 12345 (прозрачно принимает трафик от клиентов) и VLESS outbound (отправляет трафик на выходной узел). |
| iptables (OCVPN) | Кастомная цепочка. Перехватывает весь трафик от OpenConnect клиентов (интерфейсы vpns+) и перенаправляет в xray через механизм TPROXY ядра Linux. |
| ip routing (fwmark) | Специальные правила маршрутизации: fwmark 0x1 → table 100 → local route on lo. Позволяют ядру доставлять помеченные TPROXY пакеты в сокет xray. Без этих правил TPROXY физически не работает. |
| tproxy-routing.service | Systemd-сервис, который восстанавливает ip rule/ip route после каждой перезагрузки сервера. Без него всё работает до первого reboot. |
Установка шаг за шагом
Что понадобится: чистый Debian 12, отдельный VPS с xray в режиме VLESS+TLS — это выходной узел, — и root по SSH. Больше ничего.
Обновление системы
apt update && apt upgrade -y apt install -y curl wget iptables-persistent netfilter-persistent ocserv openssl
Установка xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
Конфиг xray
Создайте /usr/local/etc/xray/config.json. Внутри два inbound: socks на порту 10808 — для ручной проверки, и TPROXY на 12345 — для реального трафика. Плюс VLESS outbound, смотрящий на выходной узел.
{
"inbounds": [
{
"tag": "socks-in", // для тестирования через curl
"port": 10808, "listen": "127.0.0.1",
"protocol": "socks"
},
{
"tag": "tproxy-in", // прозрачный прокси для офисного трафика
"port": 12345, "listen": "0.0.0.0",
"protocol": "dokodemo-door",
"settings": { "network": "tcp,udp", "followRedirect": true },
"streamSettings": { "sockopt": { "tproxy": "tproxy" } }
}
],
"outbounds": [
{
"tag": "vless-out",
"protocol": "vless",
"settings": { "vnext": [{
"address": "ВАШ_VLESS_ДОМЕН", "port": 443,
"users": [{ "id": "ВАШ_UUID", "encryption": "none" }]
}]},
"streamSettings": {
"network": "tcp", "security": "tls",
"tlsSettings": {
"serverName": "ВАШ_VLESS_ДОМЕН",
"fingerprint": "chrome" // маскировка под браузер
}
}
}
]
}
systemctl enable --now xray
Проверяем VLESS — в ответе должен прийти IP выходного узла, не IP шлюза:
curl -s --socks5 127.0.0.1:10808 https://api.ipify.org
Установка и конфиг ocserv
# Самоподписанный сертификат mkdir -p /etc/ocserv/ssl && cd /etc/ocserv/ssl openssl req -x509 -newkey rsa:2048 -keyout server-key.pem -out server-cert.pem -days 3650 -nodes -subj "/CN=ВАШ_IP_СЕРВЕРА" # Создать пользователя ocpasswd -c /etc/ocserv/ocpasswd itfresh
auth = "plain[passwd=/etc/ocserv/ocpasswd]" tcp-port = 443 udp-port = 443 server-cert = /etc/ocserv/ssl/server-cert.pem server-key = /etc/ocserv/ssl/server-key.pem device = vpns ipv4-network = 192.168.8.0/24 dns = 8.8.8.8 route = default # Критично: исключить IP шлюза и VLESS-сервера из туннеля no-route = 155.212.159.202/255.255.255.255 no-route = 202.148.54.236/255.255.255.255 max-clients = 50 keepalive = 30 dpd = 60 systemctl enable --now ocserv
iptables TPROXY
# Создать цепочку OCVPN iptables -t mangle -N OCVPN iptables -t mangle -A PREROUTING -i vpns+ -j OCVPN # Не трогать приватные адреса iptables -t mangle -A OCVPN -d 0.0.0.0/8 -j RETURN iptables -t mangle -A OCVPN -d 10.0.0.0/8 -j RETURN iptables -t mangle -A OCVPN -d 127.0.0.0/8 -j RETURN iptables -t mangle -A OCVPN -d 172.16.0.0/12 -j RETURN iptables -t mangle -A OCVPN -d 192.168.0.0/16 -j RETURN iptables -t mangle -A OCVPN -d ВАШ_VLESS_IP/32 -j RETURN # Направить в xray iptables -t mangle -A OCVPN -p tcp -j TPROXY --on-port 12345 --on-ip 0.0.0.0 --tproxy-mark 0x1 iptables -t mangle -A OCVPN -p udp -j TPROXY --on-port 12345 --on-ip 0.0.0.0 --tproxy-mark 0x1 # Борьба с фрагментацией MTU iptables -t mangle -A FORWARD -i vpns+ -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu netfilter-persistent save
IP routing для fwmark — самый важный шаг
Это правило говорит ядру Linux: помеченные TPROXY-пакеты доставить в сокет xray. Пропустите его — клиенты подключатся, но интернета не будет. Мы теряли на этом час отладки, пока не разобрались.
ip rule add fwmark 0x1 table 100 ip route add local 0.0.0.0/0 dev lo table 100 # Проверка ip rule list | grep fwmark # 218: from all fwmark 0x1 lookup 100 ← должно быть так
Персистентность routing rules
Теперь systemd-сервис, который поднимает ip rule при каждой загрузке — иначе после перезагрузки правило пропадёт:
[Unit] Description=TPROXY IP routing rules for OpenConnect+VLESS After=network.target netfilter-persistent.service xray.service Requires=netfilter-persistent.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c "ip rule add fwmark 0x1 table 100 2>/dev/null || true; ip route add local 0.0.0.0/0 dev lo table 100 2>/dev/null || true" ExecStop=/bin/bash -c "ip rule del fwmark 0x1 table 100 2>/dev/null || true; ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null || true" [Install] WantedBy=multi-user.target
systemctl daemon-reload systemctl enable --now tproxy-routing # Финальная проверка всех сервисов systemctl is-enabled ocserv xray tproxy-routing netfilter-persistent # → enabled enabled enabled enabled
Настройка Keenetic
Вся красота архитектуры — именно здесь: настройка на стороне офиса занимает ровно 2 минуты.
| Интернет → VPN → Добавить | Тип подключения: Cisco AnyConnect |
| Сервер | 155.212.159.202 · Порт: 443 |
| Логин / Пароль | Указанные при создании пользователя через ocpasswd |
| Проверять сертификат | НЕТ — используется self-signed сертификат |
| Маршрутизация | «Использовать как шлюз по умолчанию» — ДА. Весь трафик офиса пойдёт через VPN. |
Диагностика после настройки
Живой трафик в логах xray выглядит так:
Известные грабли
После перезагрузки клиенты подключаются, но интернет не работает
Проверка:
ip rule list | grep fwmark — если пусто, вот причина.Быстрое исправление:
systemctl start tproxy-routingПостоянное: убедитесь, что
tproxy-routing.service enabled.
Все клиенты разом отвалились и не могут залогиниться
/etc/ocserv/ocpasswd изменился.Диагностика:
journalctl -u ocserv | grep "failed authentication"Решение:
ocpasswd -c /etc/ocserv/ocpasswd itfresh, затем systemctl restart ocserv.Keenetic'ы переподключатся автоматически в течение ~30 секунд.
Петля маршрутизации: xray → VLESS → через VPN → xray → ...
ocserv.conf нет строки no-route для IP VLESS-сервера.Без неё Keenetic пытается отправить трафик к самому VLESS-серверу тоже через VPN-туннель — и возникает бесконечная петля.
Решение: добавить в конфиг ocserv:
no-route = ВАШ_VLESS_IP/255.255.255.255no-route = ВАШ_ШЛЮЗ_IP/255.255.255.255
Результат
В итоге весь офисный трафик выходит через российский IP 202.148.54.236. Соединение по 443/TCP снаружи неотличимо от обычного HTTPS — никаких характерных признаков VPN. VLESS + TLS маскируется под Chrome через fingerprint: chrome. При перезагрузке шлюза все четыре сервиса поднимаются сами, без каких-либо ручных действий.
Часто задаваемые вопросы
Что такое Двойноетуннелирование:OpenConnect+ VLESS?
Двойноетуннелирование:OpenConnect+ VLESS — это важный аспект системного администрирования, который позволяет настроить и оптимизировать работу IT-инфраструктуры. В данной статье подробно рассматриваются все ключевые моменты.
Как правильно настроить Двойноетуннелирование:OpenConnect+ VLESS?
Для корректной настройки Двойноетуннелирование:OpenConnect+ VLESS необходимо следовать пошаговой инструкции, представленной в статье выше. Важно учитывать особенности вашей инфраструктуры и требования безопасности.
Какие типичные ошибки возникают при работе с Двойноетуннелирование:OpenConnect+ VLESS?
Наиболее частые ошибки при работе с Двойноетуннелирование:OpenConnect+ VLESS: некорректная конфигурация, недостаточные права доступа и несовместимость версий. Рекомендуем обратиться к специалистам ITFresh для профессиональной настройки.
Официальная документация: Telegram MTProto Documentation, Debian Wiki — iptables
Комментарии