Xray на OPNsense: установка
Если у вас уже стоит OPNsense как основной шлюз, ставить Xray прямо на хост-систему — плохая идея: любой сторонний демон на самом фаерволе увеличивает поверхность атаки на устройство, которое защищает всю сеть. Правильный путь — изолировать Xray в отдельном FreeBSD jail со своим IP, а фаервол настроить так, чтобы наружу торчал только нужный порт. Ниже — как это сделать: от подготовки джейла и установки бинарника до автоматического сертификата через встроенный ACME-плагин и правил NAT, которые связывают всё это с внешним миром.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Почему не на хосте, а в джейле
OPNsense — это FreeBSD с надстройкой конфигурации поверх. Технически ничего не мешает поставить Xray прямо в базовую систему и запустить его как обычный rc-сервис. Но у этого решения есть цена: если в Xray найдут уязвимость (а сложный TLS-парсинг — это всегда потенциальная поверхность), скомпрометированным окажется не отдельный сервис, а сама машина, которая держит все firewall-правила, VPN-туннели и NAT вашей сети.
Jail в FreeBSD — встроенная изоляция на уровне ядра: у процессов внутри свой корень файловой системы и ограниченная видимость остальной системы. Это не полноценная виртуальная машина — оверхед минимальный, — но компрометация сервиса внутри джейла не даёт автоматом доступа к хост-системе и её конфигурации. Разумная страховка для сервиса, который по своей природе устроен так, чтобы выглядеть неотличимым от чужого HTTPS-трафика.
Если в вашей сборке OPNsense установлен плагин управления джейлами через веб-интерфейс — он просто автоматизирует шаги ниже (мастер создания, автостарт по чекбоксу, привязка датасета). Если плагина нет или вы предпочитаете консоль, тот же результат получается через штатный jail(8) и /etc/jail.conf, доступные в базовой системе всегда — именно этот путь описан дальше как основной, потому что он не зависит от конкретной версии сборки плагинов.
Подготовка: сеть и сертификатный плагин
Прежде чем создавать джейл, решите две вещи.
Сеть для джейла. Проще всего выделить джейлу собственный IP на внутреннем интерфейсе (отдельный VLAN или OPT-интерфейс уровня «DMZ»), а наружу трафик пускать через NAT-правило фаервола — так джейл физически не имеет прямого пути в LAN, и весь трафик к нему и от него проходит через видимые вам правила. Заведите для интерфейса отдельную подсеть, если её ещё нет: Interfaces → Assignments, дайте интерфейсу IP вида 10.10.20.1/24 — это будет шлюз для джейла.
Сертификат. Установите плагин os-acme-client через System → Firmware → Plugins — официальный ACME-клиент OPNsense для Let's Encrypt, с UI для аккаунтов, доменов и автопродления. Поставьте его заранее, чтобы не прерывать процесс на середине. Домен, на который будете выпускать сертификат, должен А-записью указывать на публичный IP, за которым окажется джейл — обычно это WAN-адрес самого OPNsense.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверСоздание джейла
Через консоль (Diagnostics → Command Prompt или SSH на OPNsense) заведите датасет и базовую систему. Если у вас ZFS-пул zroot, типичная схема такая:
zfs create -o mountpoint=/usr/jails zroot/jails
zfs create /usr/jails/xray
Base-систему возьмите той же версии FreeBSD, на которой собран ваш OPNsense — несовпадение версий не всегда фатально, но лишний источник проблем ни к чему. Проверить версию хоста:
freebsd-version
Скачайте и распакуйте base.txz соответствующей версии в подготовленный каталог (замените версию на актуальную для вашей сборки):
fetch https://download.freebsd.org/releases/amd64/14.2-RELEASE/base.txz -o /tmp/base.txz
tar -xf /tmp/base.txz -C /usr/jails/xray --unlink
Опишите джейл в /etc/jail.conf:
xray {
host.hostname = "xray.jail";
path = "/usr/jails/xray";
ip4.addr = "10.10.20.10/24";
interface = "opt3";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
allow.raw_sockets = 0;
}
Важный нюанс именно для OPNsense: система периодически перегенерирует часть конфигурационных файлов из config.xml при применении настроек. /etc/jail.conf этим механизмом не управляется, поэтому редактировать его напрямую безопасно — но держите копию отдельно (например, в /root/jail-backup/), чтобы быстро восстановить после переустановки или отката конфигурации.
Включите джейлы и автостарт вашего джейла в /etc/rc.conf:
sysrc jail_enable="YES"
sysrc jail_list="xray"
service jail start xray
Проверьте, что джейл поднялся и виден в списке:
jls
Установка Xray внутри джейла
Xray на момент написания не входит в официальный репозиторий пакетов FreeBSD/OPNsense, поэтому ставится не через pkg, а из готового бинарника с GitHub-релизов проекта — там публикуются сборки под freebsd-64. Зайдите в джейл и скачайте актуальный релиз:
jexec xray sh
fetch -o /tmp/xray.zip https://github.com/XTLS/Xray-core/releases/latest/download/Xray-freebsd-64.zip
mkdir -p /usr/local/xray
tar -xf /tmp/xray.zip -C /usr/local/xray
chmod +x /usr/local/xray/xray
Сгенерируйте UUID клиента — это единственный секрет, который решает, пустит ли сервер подключение:
/usr/local/xray/xray uuid
Соберите /usr/local/etc/xray/config.json с входящим VLESS поверх XTLS-Vision на порту 443, указав UUID и пути к сертификату (положим их на следующем шаге). Логика конфига та же, что и при установке Xray и XTLS на обычном VPS — разница только в окружении вокруг сервиса.
Поскольку в базовой системе джейла нет systemd, обычный install-release.sh со скриптом-юнитом не подойдёт — нужен свой rc.d-скрипт. Создайте /usr/local/etc/rc.d/xray:
#!/bin/sh
# PROVIDE: xray
# REQUIRE: NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name="xray"
rcvar="xray_enable"
pidfile="/var/run/${name}.pid"
command="/usr/sbin/daemon"
command_args="-f -p ${pidfile} /usr/local/xray/xray run -config /usr/local/etc/xray/config.json"
load_rc_config $name
: ${xray_enable:="NO"}
run_rc_command "$1"
chmod +x /usr/local/etc/rc.d/xray
sysrc xray_enable="YES"
service xray start
daemon(8) здесь оборачивает Xray, который сам не форкается в фон, и пишет pid-файл — без этого rc.subr не сможет корректно останавливать и перезапускать сервис. Проверьте, что процесс жив и слушает порт:
service xray status
sockstat -4l | grep xray
Сертификат через ACME-плагин OPNsense
Дальше настройте os-acme-client на хосте: Services → ACME Client → Accounts — заведите аккаунт Let's Encrypt, затем в Certificates добавьте сертификат на домен с валидацией HTTP-01 (если 80/tcp временно открыт наружу) или DNS-01 через API вашего DNS-провайдера. DNS-01 удобнее на шлюзе — не нужно пробрасывать порт 80 ради одной проверки.
Ключевая деталь для связки с джейлом — вкладка Automations. Она позволяет выполнить произвольную команду на хосте после каждого выпуска или продления сертификата. Задайте команду, которая копирует свежие файлы сертификата и ключа в файловую систему джейла и перезапускает сервис через jexec:
cp /var/etc/acme-client/xray.example.com/cert.pem /usr/jails/xray/usr/local/etc/xray/cert.pem
cp /var/etc/acme-client/xray.example.com/key.pem /usr/jails/xray/usr/local/etc/xray/key.pem
jexec xray service xray restart
Точные пути к файлам сертификата зависят от версии плагина — проверьте их в интерфейсе Automations или логе выпуска сертификата перед тем, как прописывать команду. Дальше плагин сам следит за сроком действия и повторяет продление и деплой без вашего участия — единственное, что нужно, это одноразово убедиться, что автоматизация реально сработала (смотрите ниже, раздел про проверку).
Интеграция с фаерволом
Это центральная часть настройки — то, ради чего вообще стоит держать Xray за OPNsense, а не на голом VPS. Сначала заведите алиас на IP джейла: Firewall → Aliases, тип Host(s), имя Xray_Jail, значение 10.10.20.10. Дальше все правила ссылаются на алиас, а не на голый IP — если джейл когда-нибудь переедет на другой адрес, поправить нужно будет только алиас.
Перед тем как пробрасывать 443 снаружи, проверьте один частый источник проблем: по умолчанию сам веб-интерфейс OPNsense тоже слушает HTTPS на 443. Если не сменить порт админки, вы либо не сможете отдать 443 джейлу, либо рискуете потерять доступ к панели управления. Смените его в System → Settings → Administration → TCP port на что-то вроде 8443 — и только после этого настраивайте проброс.
Дальше добавьте правила:
| Правило | Интерфейс | Протокол | Источник | Назначение | Порт | Действие |
|---|---|---|---|---|---|---|
| Проброс на Xray | WAN | TCP | any | WAN address | 443 | NAT → Xray_Jail:443 |
| Xray наружу | OPT_JAILS | any | Xray_Jail | any | any | Pass |
| Запрет прямого LAN→джейл | LAN | any | LAN net | Xray_Jail | 22 | Block |
Первое правило — стандартный Port Forward (Firewall → NAT → Port Forward): интерфейс WAN, протокол TCP, назначение WAN address, порт 443, redirect target — алиас Xray_Jail, redirect port 443. OPNsense автоматически создаст парное разрешающее правило на WAN — проверьте, что оно появилось на вкладке Firewall Rules → WAN.
Второе правило разрешает джейлу инициировать исходящие соединения — без него отвалится не только связь с клиентами, но и собственные запросы Xray наружу. Третье — необязательное, но полезное: закрыть управляющие порты джейла (SSH и подобные) от остальной локальной сети, оставив доступ только с вашей рабочей станции или вообще только с хоста через jexec.
Если у вас на OPNsense уже работает os-haproxy для reverse-proxy нескольких HTTPS-сервисов по одному порту 443 через SNI, Xray с XTLS в эту схему аккуратно не встраивается: HAProxy обычно терминирует TLS сам, а смысл XTLS в том, что TLS остаётся нетронутым и уходит клиенту как есть. В этой ситуации либо выносите Xray на отдельный публичный IP/порт, либо настраивайте HAProxy в режиме TCP passthrough по SNI без терминации — это отдельная, более тонкая настройка, выходящая за рамки базовой установки.
Проверка и мониторинг
После применения правил проверьте с внешней машины, что порт действительно открыт и до него достаёт TLS:
openssl s_client -connect xray.example.com:443 -servername xray.example.com
Если хендшейк проходит и виден сертификат от Let's Encrypt — цепочка «домен → WAN → NAT → джейл → Xray» рабочая. Дальше подключите обычный клиент (v2rayN, v2rayNG, Shadowrocket, NekoRay — тот же UUID, порт 443, XTLS-Vision, SNI вашего домена) и проверьте смену IP на сервисе определения адреса.
Живые соединения удобно смотреть прямо в OPNsense: Diagnostics → States, фильтр по адресу Xray_Jail — видно каждое активное соединение с клиента к джейлу и обратно, что полезно, чтобы понять, действительно ли клиент подключился или трафик теряется по пути. Логи прохождения NAT — в Firewall → Log Files → Live View с тем же фильтром: если Port Forward не сработал, пакеты на 443 будут видны заблокированными на default deny.
Внутри джейла за состоянием сервиса следит service xray status и системный лог:
jexec xray tail -n 50 /var/log/messages
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Обязательно ли использовать джейл, а не ставить Xray прямо в базовую систему OPNsense?
Формально нет — технически ничего не помешает. Но фаервол — это точка отказа для всей сети за ним, и добавлять на неё сторонний сетевой сервис без изоляции — осознанный риск, которого стоит избегать, если нет веской причины.
Есть ли Xray в официальном репозитории пакетов FreeBSD/OPNsense?
На момент написания нет, поэтому используется готовый бинарник с GitHub-релизов проекта Xray-core под freebsd-64, а не pkg install. Проверьте pkg search xray в своей версии — если пакет появится, установка через pkg внутри джейла будет проще.
Можно ли обойтись без домена и сертификата, используя Reality?
Да, Reality заменяет собственный сертификат маскировкой под чужой популярный сайт по SNI и не требует ACME-плагина вообще. Для серверов в отдельных локациях эта схема разобрана в статье о VLESS Reality на сервере в США — сам процесс установки Xray в джейле от этого не меняется, меняется только содержимое config.json.
Что если 443 занят другим сервисом на OPNsense?
Чаще всего это веб-интерфейс самого OPNsense — переносите его на другой порт через System → Settings → Administration. Если 443 нужен ещё и другому HTTPS-сервису за фаерволом, разводите их по разным публичным IP или переносите один из сервисов на нестандартный порт.
Как обновить Xray внутри джейла?
Остановите сервис, скачайте свежий Xray-freebsd-64.zip тем же способом, перезапишите бинарник в /usr/local/xray/ и запустите снова — конфиг и сертификаты трогать не нужно, они лежат отдельно.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →