Как это работает: Схема скрытия зарубежного VPS
Ну давай разбираться вместе. У тебя есть забугорный VPS, на котором настроен VPN. Назовем его VPSEU. Ты хочешь, чтобы пользователи коннектились не напрямую к нему, а к другому VPS внутри РФ — назовем его VPSRU.
В такой связке раскрытие IP основного сервера (VPSEU) будет пофиг. Расходным материалом становится VPSRU: если его вдруг раскроют, мы его просто меняем.
Основные настройки всех инбаундов с пользователями и прочим лучше держать на VPSEU, чтобы легко и просто в случае чего поменять VPSRU с минимумом перенастроек. Логично?
Сценарий с маскировкой
Допустим, у тебя на VPSEU на порту 443 висит какой-нибудь REALITY. На 80 порту висит тот же сайт, что и на 443 REALITY — для полноты маскировки.
Тогда тебе нужно сделать Port Mapping — отобразить порты так, чтобы:
VPSRU:443 → VPSEU:443
VPSRU:80 → VPSEU:80
Это попадает под определение «Ingress forwarding»: удаленное отображение портов (remote port mapping), которое маппит публичный порт входа на удаленный внутренний веб-сервис.
Что мы делаем на VPSRU
На российском сервере (я хз, как это через панель, тут руками маленький конфиг):
{
"inbounds": [
{
"listen": "::",
"port": 8443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "VPSEU-SERVER",
"flow": "xtls-rprx-vision",
"reverse": {
"tag": "reverse-out"
}
}
]
}
},
{
"listen": "::",
"port": "443,80",
"protocol": "tunnel",
"tag": "portal"
}
],
"routing": {
"rules": [
{
"inboundTag": ["portal"],
"outboundTag": "reverse-out"
}
]
},
"outbounds": [
{
"protocol": "freedom"
}
]
}
Что здесь имеем:
Порт 8443 — это порт, по которому VPSEU сервер будет коннектиться к нашему VPSRU серверу. Конкретные настройки (REALITY, просто TLS или вообще голый VLESS) на работу схемы не сказываются. Я бы сделал TLS с Vision и самоподписанным сертификатом, но смотри сам, как хочешь…
Есть волшебный инбаунд portal, который слушает на VPSRU порты 443 и 80 и «как есть» перенаправляет трафик через туннель, который открыл VPSEU в тот момент, когда подключился к нашему порту 8443.
Что имеем на VPSEU
{
// Other forward-proxy-related configuration is omitted...
"routing": {
"rules": [
{
"ruleTag": "reverse-direct-rule",
"inboundTag": ["reverse-in"],
"outboundTag": "reverse-direct"
}
]
},
"outbounds": [
{
"protocol": "freedom"
},
{
"protocol": "freedom",
"tag": "reverse-direct",
"settings": {
"redirect": "127.0.0.1:0",
"finalRules": [
{
"action": "allow",
"network": "tcp",
"ip": "127.0.0.1",
"port": "80,443"
}
]
}
},
{
"protocol": "vless",
"settings": {
"address": "IP_OF_VPSRU",
"port": 8443,
"id": "VPSEU-SERVER",
"flow": "xtls-rprx-vision",
"reverse": {
"tag": "reverse-in"
}
}
}
]
}
Что это означает:
Правило reverse-direct-rule перенаправит всё, что прилетело с сервера VPSRU, на специальный аутбаунд reverse-direct. Этот аутбаунд перепишет адрес назначения на 127.0.0.1, но оставит порт назначения нетронутым. Финальное правило отрубит UDP и все порты, кроме 80 и 443.
Итого:
Все запросы, которые прилетают на порты 443 и 80 сервера VPSRU, оказываются на твоем забугорном VPSEU на локальном 127.0.0.1 на тех же портах. А там на 443 — твой REALITY, на 80 — тот же сайт для маскировки.
Вот описание проблемы и пошаговый алгоритм для проверки бага. Терминология заменена: VPSRU (вместо Portal) и VPSEU (вместо Bridge).
Проблема: Рассинхронизация состояний Reverse Proxy при перезагрузках
Модуль Reverse Proxy в Xray-core некорректно восстанавливает соединение, если один из серверов (VPSRU или VPSEU) перезагружается. Система входит в состояние «deadlock»: либо VPSRU удерживает устаревшие маппинги туннелей, либо VPSEU не может перерегистрироваться после перезагрузки VPSRU. Это приводит к «зависанию» соединений или ошибкам Empty reply from server. Проблема указывает на отсутствие механизмов самовосстановления (heartbeat или автоматической очистки пула туннелей).
Шаги для воспроизведения (Тест на стабильность туннеля)
Попробуй воспроизвести это у себя по следующим шагам:
- Исходное состояние: Запусти Xray сначала на VPSRU, затем на VPSEU.
- Проверка связи: Выполни запрос на VPSRU:
curl 127.0.0.1:80.
- Ожидаемый результат: Успех (получен ответ от веб-сервиса за VPSEU).
- Симуляция сбоя VPSEU: Убей процесс Xray на VPSEU. Снова запусти
curl 127.0.0.1:80 на VPSRU.
- Результат: Запрос висит (это нормально).
- Ошибка восстановления (Stale State): Снова запусти Xray на VPSEU.
- Результат: Тот
curl, который завис на шаге 3, продолжает висеть и не оживает.
- Призрачная сессия: Убей зависший
curl и попробуй сделать новый запрос: curl 127.0.0.1:80.
- Результат: Всё равно висит. (Баг: VPSRU не направляет новые запросы через переподключенный VPSEU).
- Рассинхронизация VPSRU: Останови
curl. Перезапусти процесс Xray на VPSRU, при этом VPSEU пусть продолжает работать. Сделай curl 127.0.0.1:80 на VPSRU.
- Результат: Ошибка
curl: (52) Empty reply from server. (Баг: VPSEU не понимает, что сервер перезагрузился, и не пересоздает туннели).
- Полный сброс: Перезапусти Xray на VPSEU. Снова проверь
curl на VPSRU.
- Результат: Успех (связь восстановилась только после перезагрузки обоих узлов).
Что ожидается от системы
- VPSRU должен инвалидировать или очищать старые туннели, когда тот же самый VPSEU (с тем же доменом) подключается заново.
- VPSEU должен иметь механизм проверки связи (keep-alive/heartbeat), чтобы мгновенно перерегистрироваться, если VPSRU упал и поднялся.
Проверь, подтверждается ли у тебя такое поведение на последней версии ядра.