Freedom — Xray-core
Freedom — это исходящее подключение Xray для прямого выхода: трафик отправляется на реальный адрес назначения без какого-либо прокси-протокола посередине. Кроме того, оно несёт две функции противодействия DPI: фрагментацию TCP/TLS и внедрение произвольных шумовых пакетов.
Исходящий
settings для исходящего подключения с "protocol": "freedom":
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
targetStrategy | string | asis | asis | useip | useipv4 | useipv6 | useipv4v6 | useipv6v4 | forceip | forceipv4 | forceipv6 | forceipv4v6 | forceipv6v4 | Устарело — при запуске значение, отличное от asis, с предупреждением переносится в streamSettings.sockopt.domainStrategy (те же значения); задавайте его там. Как разрешается адрес назначения перед установкой соединения. asis передаёт адрес в том виде, в каком его выдал движок маршрутизации; useip* разрешает в IP только при необходимости; forceip* всегда разрешает и подставляет IP. Суффиксы *v4v6 / *v6v4 задают, какое семейство адресов пробуется первым. |
domainStrategy | string | (inherits targetStrategy) | <same values> | Устаревший псевдоним для targetStrategy. Читается только когда targetStrategy пуст. Устарело вместе с targetStrategy. |
redirect | string | (unset) | <host:port> | Переопределяет адрес назначения каждого соединения. Полезно для пересылки на локальный сервис независимо от маршрутизации. |
userLevel | uint32 | 0 | <uint32> | Уровень политики по умолчанию для соединений, проходящих через это исходящее подключение. |
fragment | *Fragment | (disabled) | Fragment | Посегментная фрагментация TCP для обхода DPI, анализирующего длины пакетов. |
noise | *Noise | (unsupported) | (use noises) | Не поддерживается — используйте массив noises. Установка noise приводит к явной ошибке при сборке конфигурации. |
noises | []*Noise | (unset) | [Noise] | Список шумовых пакетов, отправляемых перед реальными пакетами (или между ними), чтобы сбить сопоставление шаблонов. |
proxyProtocol | uint32 | 0 | 0 | 1 | 2 | Добавляет заголовок PROXY protocol к исходящим соединениям. 0 — отключено; 1 / 2 — версия v1 (текстовая) или v2 (двоичная). |
ipsBlocked | *StringList | (ignored) | (use finalRules) | Не поддерживается — задавайте блокировку IP через finalRules; установка лишь пишет предупреждение в журнал и ни на что не влияет. |
finalRules | []*FreedomFinalRuleConfig | (unset) | [FreedomFinalRuleConfig] | Правила allow/block для каждого соединения, вычисляемые в момент подключения, — лёгкий межсетевой экран на самом исходящем подключении с сопоставлением по сети / порту / IP. Игнорируется (с предупреждением), если задан streamSettings.sockopt.dialerProxy. |
Исходный код: infra/conf/freedom.go:19-30 · зафиксировано на v26.9.9 (52a412d)
fragment
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
packets | string | (all) | tlshello | <from-to> | | Какие пакеты фрагментировать. tlshello фрагментирует только TLS ClientHello (менее заметно, полезно для маскировки SNI). Диапазон вида "1-3" фрагментирует пакеты с этими порядковыми номерами. Пустое значение фрагментирует каждый пакет — самый агрессивный вариант. |
length | *Int32Range | (required) | {from, to} | Диапазон байтов на фрагмент. Минимум должен быть > 0. |
interval | *Int32Range | (required) | {from, to} | Диапазон задержки между фрагментами в миллисекундах. |
maxSplit | *Int32Range | (unbounded) | {from, to} | Диапазон общего числа разбиений на пакет. Необязательное ограничение. |
Исходный код: infra/conf/freedom.go:32-37 · зафиксировано на v26.9.9 (52a412d)
noises[]
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
type | string | (required) | rand | str | hex | base64 | Форма полезной нагрузки пакета. rand генерирует случайные байты, длина которых берётся из packet (строка-диапазон). str/hex/base64 интерпретируют packet буквально. |
packet | string | (required) | <bytes or range> | Содержимое полезной нагрузки. Формат зависит от type. |
delay | *Int32Range | (unset) | {from, to} | Диапазон ожидания в миллисекундах перед отправкой этого шумового пакета. |
applyTo | string | ip | ip | all | ipv4 | ipv6 | Ограничивает внедрение шума одним семейством IP. ip и all применяются к обоим. |
Исходный код: infra/conf/freedom.go:39-44 · зафиксировано на v26.9.9 (52a412d)
finalRules[]
Небольшой межсетевой экран allow/block, который исходящее подключение freedom применяет при установке соединения. Правила вычисляются по порядку; решает первое совпадение. Блокировка IP задаётся здесь — поле ipsBlocked игнорируется.
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
action | string | (required) | allow | block | Что делать с совпавшим соединением. block отклоняет его; allow пропускает — размещайте правила allow первыми, чтобы вырезать исключения из более широкого block. |
network | *NetworkList | (any) | tcp | udp | tcp,udp | Сопоставлять только эти сети. |
port | *PortList | (any) | <port / range list> | Сопоставлять только эти порты назначения. |
ip | *StringList | (any) | <IP / CIDR / geoip:> | Сопоставлять только эти IP назначения. Принимает категории geoip:. |
blockDelay | *Int32Range | (immediate) | {from, to} | Для действия block — выждать случайную задержку в этом диапазоне миллисекунд перед разрывом соединения; вместо мгновенного отказа зондирующий вынужден ждать. |
Исходный код: infra/conf/freedom.go:46-52 · зафиксировано на v26.9.9 (52a412d)
Примеры
Простое исходящее подключение freedom (сквозная передача):
{
"outbounds": [
{ "tag": "direct", "protocol": "freedom", "settings": {} }
]
}Принудительное разрешение сначала в IPv4, затем в IPv6:
{
"outbounds": [
{
"tag": "direct-v4",
"protocol": "freedom",
"settings": {},
"streamSettings": { "sockopt": { "domainStrategy": "forceipv4v6" } }
}
]
}Фрагментация TLS ClientHello (хорошая отправная точка для маскировки SNI):
{
"outbounds": [
{
"tag": "frag",
"protocol": "freedom",
"settings": {
"fragment": {
"packets": "tlshello",
"length": { "from": 10, "to": 20 },
"interval": { "from": 10, "to": 20 }
}
}
}
]
}Внедрение шума (4 случайных байта перед каждым IPv4-соединением с задержкой 0–1 мс):
{
"outbounds": [
{
"tag": "noisy",
"protocol": "freedom",
"settings": {
"noises": [
{
"type": "rand",
"packet": "4-4",
"delay": { "from": 0, "to": 1 },
"applyTo": "ipv4"
}
]
}
}
]
}Полностью заблокировать QUIC (UDP/443) и затягивать соединения к приватным диапазонам, чтобы замедлить зондирование:
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"finalRules": [
{ "action": "block", "network": "udp", "port": "443" },
{ "action": "block", "ip": ["geoip:private"], "blockDelay": { "from": 1000, "to": 3000 } }
]
}
}
]
}Переслать весь трафик на локальный сервис (удобно для тестирования):
{
"outbounds": [
{
"tag": "redir",
"protocol": "freedom",
"settings": { "redirect": "127.0.0.1:8080" }
}
]
}Примечания
targetStrategy/domainStrategyвsettingsfreedom устарели. При запуске Xray переносит значение, отличное отasis, вstreamSettings.sockopt.domainStrategyи пишет предупреждение;targetStrategyуровня исходящего у исходящего freedom переносится так же (infra/conf/xray.go:341-364). Перенесённое значение перезаписывает заданный вамиsockopt.domainStrategy, поэтому задавайте что-то одно.domainStrategyпо-прежнему читается лишь как запасной вариант, когдаtargetStrategyпуст (infra/conf/freedom.go:46-48).- При
finalRulesи доменном назначении freedom сначала разрешает домен (черезsockopt.domainStrategy, а приAsIs— системным резолвером), чтобы проверить правилаblock, а затем повторно проверяет адрес, к которому фактически подключился. - Если задан
streamSettings.sockopt.dialerProxy, freedom не является последним звеном:finalRulesигнорируются (пишется предупреждение), а домен заранее не разрешается. - freedom отклоняет
streamSettings.sockopt.addressPortStrategyпри запуске. - Неизвестные строки стратегии приводят к ошибке при запуске, а не к тихому откату к значению по умолчанию (
infra/conf/freedom.go:72-73). noise(в единственном числе) не поддерживается: его установка приводит к ошибке при запуске с указанием наnoises = [ { ... } ](infra/conf/freedom.go:145-147).ipsBlockedне поддерживается — задайте его как правило{ "action": "block", "ip": [...] }вfinalRules; само поле лишь пишет предупреждение в журнал и в остальном игнорируется.- Действия
finalRules— толькоallow/block(неизвестные действия дают ошибку при запуске).ipпринимает категорииgeoip:;blockDelayприменяется только к правиламblock. fragment.packets: "tlshello"— рекомендуемая отправная точка: фрагментация только TLS ClientHello ломает DPI по SNI, не затрагивая остальную часть соединения (накладные расходы в байтах — разовые).fragment.length.fromиfragment.intervalобязательны, когда заданfragment(infra/conf/freedom.go:102-118). ДиапазонmaxSplitнеобязателен.- Значения
proxyProtocolвне1..2молча игнорируются — заголовок формируется только для этих двух значений (infra/conf/freedom.go:162-164).
Сравнение с другими ядрами
- sing-box называет это Direct, и у этого исходящего подключения почти нет собственных параметров — полей переопределения адреса назначения нет; используйте для этого действия маршрутизации. См. Direct — sing-box.
- В mihomo есть столь же минимальный тип Direct; встроенный прокси
DIRECTнеявно присутствует в каждой конфигурации. См. Direct — mihomo.
Исходный код: infra/conf/freedom.go:19-52 · v26.9.9 (52a412d)
