Конфигурация Xray в XKeen устроена модульно — несколько JSON-файлов в директории /opt/etc/xray/configs/, каждый отвечает за свою часть. Грузятся они в алфавитном порядке, отсюда и нумерация: 01, 03, 04, 05. Разберём каждый по делу.
Файл отвечает за логирование работы Xray:
{
"log": {
"access": "/opt/var/log/xray/access.log",
"error": "/opt/var/log/xray/error.log",
"loglevel": "none",
"dnsLog": false
}
}
Параметры:
access — путь к логу доступа. Сюда летят записи обо всех обработанных соединениях.error — путь к логу ошибок.loglevel — уровень логирования. "none" отключает логи полностью — роутер не резиновый, ресурсы экономим. Когда что-то идёт не так, переключайтесь на "warning" или "info".dnsLog — логирование DNS-запросов. В продакшене держим выключенным (false).
Совет из практики: при первом запуске поставьте loglevel в "warning" — сразу увидите, если что-то пошло не так. Когда всё стабильно заработает, переключайте на "none".
Этот файл описывает, как Xray принимает трафик, перенаправленный от Netfilter. Настраиваются два обработчика — для TCP и UDP раздельно:
{
"inbounds": [
{
"tag": "redirect",
"port": 61219,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp",
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
},
{
"tag": "tproxy",
"port": 61219,
"protocol": "dokodemo-door",
"settings": {
"network": "udp",
"followRedirect": true
},
"streamSettings": {
"sockopt": {
"tproxy": "tproxy"
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
]
}
По ключевым моментам:
- redirect — обработчик TCP-трафика. Протокол
dokodemo-door («дверь куда угодно») принимает любое входящее соединение и дальше маршрутизирует его по правилам. - tproxy — обработчик UDP-трафика. Тот же протокол, но режим tproxy (transparent proxy) — нужен именно для прозрачного проксирования UDP, иначе не взлетит.
- Порт 61219 — оба обработчика висят на одном порту, просто для разных протоколов: TCP и UDP.
- sniffing — включён у обоих. Xray смотрит внутрь соединения — анализирует HTTP-заголовки и TLS SNI — и вытаскивает домен назначения, даже если клиент ломится напрямую по IP.
- followRedirect — говорит обработчику использовать оригинальный адрес назначения из iptables-перенаправления, а не подменять его.
Самый главный файл во всей конфигурации. Здесь решается, куда именно уходит трафик с роутера. Три исходящих подключения — три разных сценария:
{
"outbounds": [
{
"tag": "vless-reality",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "ВАШ_СЕРВЕР",
"port": 443,
"users": [
{
"id": "ВАШ_UUID",
"flow": "xtls-rprx-vision",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"fingerprint": "chrome",
"serverName": "ВАШ_SNI_ДОМЕН",
"publicKey": "ВАШ_PUBLIC_KEY",
"shortId": "ВАШ_SHORT_ID"
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
}
]
}
Разбираем каждый outbound:
1. vless-reality — основной VPN-канал. VLESS поверх Reality — на сегодня один из самых стойких к детектированию вариантов. Почему именно он? Трафик практически неотличим от обычного HTTPS:
address — IP или домен вашего VPN-сервера. Весь трафик к заблокированным ресурсам пойдёт именно туда.port — порт сервера. Стандартно 443 — тот же, что и обычный HTTPS. Глубокая инспекция трафика не поможет отличить его от браузерного.id — UUID пользователя, сгенерированный на сервере. Без него аутентификация не пройдёт.flow: "xtls-rprx-vision" — алгоритм XTLS, который срезает лишние накладные расходы на шифрование. На слабом железе роутера это ощутимо.fingerprint: "chrome" — Xray притворяется Chrome'ом на уровне TLS-отпечатка. Снифер видит браузерный трафик — и проходит мимо.serverName — SNI, домен в TLS-handshake. Обычно ставят что-то популярное — Microsoft, Google и подобное. Выглядит как обращение к легитимному сервису.publicKey — публичный ключ Reality. Генерируется на сервере при настройке.shortId — короткий идентификатор для дополнительной аутентификации на уровне Reality.
2. direct — прямой канал через протокол freedom. Трафик идёт к адресату напрямую, никакого VPN. Для российских сервисов и локальных ресурсов — самое то.
3. block — чёрная дыра через протокол blackhole. Что попало сюда — то пропало: пакеты просто отбрасываются. Удобно резать телеметрию, рекламные трекеры и прочий мусор.
Откуда брать параметры для vless-reality? Нужен VPN-сервер с Xray и настроенным VLESS Reality — как правило, VPS где-нибудь в Нидерландах, Германии или Финляндии. Настройка серверной части — отдельная большая тема, но все параметры (UUID, publicKey, shortId, serverName) генерируются там же, при конфигурации Xray на сервере.
Этот файл — мозг всей системы. Именно здесь решается, какой трафик куда пойдёт:
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"inboundTag": ["redirect", "tproxy"],
"outboundTag": "block",
"type": "field",
"network": "udp",
"port": "135,137,138,139"
},
{
"inboundTag": ["redirect", "tproxy"],
"outboundTag": "block",
"type": "field",
"domain": ["appcenter.ms"]
},
{
"inboundTag": ["redirect", "tproxy"],
"outboundTag": "vless-reality",
"type": "field",
"domain": [
"ext:geosite_v2fly.dat:google",
"ext:geosite_v2fly.dat:speedtest",
"ext:geosite_v2fly.dat:tiktok",
"ext:geosite_zkeen.dat:domains",
"ext:geosite_zkeen.dat:other",
"2ip.ru",
"2ip.io"
]
},
{
"inboundTag": ["redirect", "tproxy"],
"outboundTag": "vless-reality",
"type": "field",
"ip": [
"ext:geoip_v2fly.dat:google",
"ext:geoip_v2fly.dat:twitter"
]
},
{
"inboundTag": ["redirect", "tproxy"],
"outboundTag": "direct",
"type": "field"
}
]
}
}
Пройдёмся по каждому правилу (они обрабатываются сверху вниз — срабатывает первое совпавшее):
Правило 1 — блокировка SMB-портов: UDP-трафик на порты 135, 137, 138, 139 режем сразу. Это порты Windows-сервисов — NetBIOS, SMB. Им за пределы локальной сети делать нечего.
Правило 2 — блокировка определённых доменов: здесь блокируется appcenter.ms — Microsoft App Center. На практике этот сервис может генерировать весьма ощутимый поток телеметрии, который нам совершенно не нужен.
Правило 3 — маршрутизация доменов через VPN: здесь перечислены категории доменов, трафик к которым идёт через VLESS Reality:
ext:geosite_v2fly.dat:google — все домены Google: google.com, googleapis.com, youtube.com и остальныеext:geosite_v2fly.dat:speedtest — сервисы измерения скоростиext:geosite_v2fly.dat:tiktok — TikTok и связанная с ним инфраструктураext:geosite_zkeen.dat:domains — заблокированные домены из базы AntiZapret/zkeenext:geosite_zkeen.dat:other — прочие заблокированные домены, не попавшие в основную категорию2ip.ru и 2ip.io — сервисы определения IP-адреса; добавили их специально, чтобы быстро проверять, работает ли VPN
Правило 4 — маршрутизация по IP через VPN: трафик к IP-адресам Google и Twitter тоже уходит через VPN. Это подстраховка к правилу по доменам — на случай, когда клиент лезет напрямую по IP, минуя DNS.
Правило 5 — всё остальное напрямую: финальная ловушка. Всё, что не совпало ни с одним правилом выше, идёт напрямую через обычное интернет-подключение.
Параметр domainStrategy: "IPIfNonMatch" работает так: если домен не попал ни под одно правило, Xray резолвит его в IP и пробует правила уже по IP-адресу. На практике это заметно повышает точность маршрутизации — особенно для сервисов, которые сидят на общих CDN-адресах.
Для кейса НетВорк Консалтинг мы дописали в правило 3 ещё несколько доменов:
"domain": [
"ext:geosite_v2fly.dat:google",
"ext:geosite_v2fly.dat:speedtest",
"ext:geosite_zkeen.dat:domains",
"ext:geosite_zkeen.dat:other",
"github.com",
"github.io",
"githubusercontent.com",
"ghcr.io",
"docker.io",
"docker.com",
"registry-1.docker.io",
"hub.docker.com",
"npmjs.org",
"npmjs.com",
"registry.npmjs.org",
"yarnpkg.com",
"2ip.ru",
"2ip.io"
]
Это закрыло вопрос со стабильным доступом ко всем сервисам, которыми пользуются разработчики.