Skip to content

Freedom — Xray-core

Freedom — это исходящее подключение Xray для прямого выхода: трафик отправляется на реальный адрес назначения без какого-либо прокси-протокола посередине. Кроме того, оно несёт две функции противодействия DPI: фрагментацию TCP/TLS и внедрение произвольных шумовых пакетов.

Исходящий

settings для исходящего подключения с "protocol": "freedom":

ПолеТипПо умолчаниюДопустимые значенияОписание
targetStrategystringasisasis | useip | useipv4 | useipv6 | useipv4v6 | useipv6v4 | forceip | forceipv4 | forceipv6 | forceipv4v6 | forceipv6v4Как разрешается адрес назначения перед установкой соединения. `asis` передаёт адрес в том виде, в каком его выдал движок маршрутизации; `useip*` разрешает в IP только при необходимости; `forceip*` всегда разрешает и подставляет IP. Суффиксы `*v4v6` / `*v6v4` задают, какое семейство адресов пробуется первым.
domainStrategystring(inherits targetStrategy)<same values>Устаревший псевдоним для `targetStrategy`. Читается только когда `targetStrategy` пуст.
redirectstring(unset)<host:port>Переопределяет адрес назначения каждого соединения. Полезно для пересылки на локальный сервис независимо от маршрутизации.
userLeveluint320<uint32>Уровень политики по умолчанию для соединений, проходящих через это исходящее подключение.
fragment*Fragment(disabled)FragmentПосегментная фрагментация TCP для обхода DPI, анализирующего длины пакетов.
noise*Noise(removed)(use noises)Удалённое поле. Используйте массив `noises`. Установка `noise` приводит к явной ошибке при сборке конфигурации.
noises[]*Noise(unset)[Noise]Список шумовых пакетов, отправляемых перед реальными пакетами (или между ними), чтобы сбить сопоставление шаблонов.
proxyProtocoluint3200 | 1 | 2Добавляет заголовок PROXY protocol к исходящим соединениям. 0 — отключено; 1 / 2 — версия v1 (текстовая) или v2 (двоичная).
ipsBlocked*StringList(removed)(use finalRules)Удалённое поле. Перенесено в `finalRules`; его установка лишь пишет предупреждение в журнал и ни на что не влияет.
finalRules[]*FreedomFinalRuleConfig(unset)[FreedomFinalRuleConfig]Правила allow/block для каждого соединения, вычисляемые в момент подключения, — лёгкий межсетевой экран на самом исходящем подключении с сопоставлением по сети / порту / IP.

Исходный код: infra/conf/freedom.go:19-30 · зафиксировано на v26.7.28 (5ca6f4b)

fragment

ПолеТипПо умолчаниюДопустимые значенияОписание
packetsstring(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.7.28 (5ca6f4b)

noises[]

ПолеТипПо умолчаниюДопустимые значенияОписание
typestring(required)rand | str | hex | base64Форма полезной нагрузки пакета. `rand` генерирует случайные байты, длина которых берётся из `packet` (строка-диапазон). `str`/`hex`/`base64` интерпретируют `packet` буквально.
packetstring(required)<bytes or range>Содержимое полезной нагрузки. Формат зависит от `type`.
delay*Int32Range(unset){from, to}Диапазон ожидания в миллисекундах перед отправкой этого шумового пакета.
applyTostringipip | all | ipv4 | ipv6Ограничивает внедрение шума одним семейством IP. `ip` и `all` применяются к обоим.

Исходный код: infra/conf/freedom.go:39-44 · зафиксировано на v26.7.28 (5ca6f4b)

finalRules[]

Небольшой межсетевой экран allow/block, который исходящее подключение freedom применяет при установке соединения. Правила вычисляются по порядку; решает первое совпадение. Это замена удалённого поля ipsBlocked.

ПолеТипПо умолчаниюДопустимые значенияОписание
actionstring(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.7.28 (5ca6f4b)

Примеры

Простое исходящее подключение freedom (сквозная передача):

json
{
  "outbounds": [
    { "tag": "direct", "protocol": "freedom", "settings": {} }
  ]
}

Принудительное разрешение сначала в IPv4, затем в IPv6:

json
{
  "outbounds": [
    {
      "tag": "direct-v4",
      "protocol": "freedom",
      "settings": { "targetStrategy": "forceipv4v6" }
    }
  ]
}

Фрагментация TLS ClientHello (хорошая отправная точка для маскировки SNI):

json
{
  "outbounds": [
    {
      "tag": "frag",
      "protocol": "freedom",
      "settings": {
        "fragment": {
          "packets": "tlshello",
          "length":   { "from": 10, "to": 20 },
          "interval": { "from": 10, "to": 20 }
        }
      }
    }
  ]
}

Внедрение шума (4 случайных байта перед каждым IPv4-соединением с задержкой 0–1 мс):

json
{
  "outbounds": [
    {
      "tag": "noisy",
      "protocol": "freedom",
      "settings": {
        "noises": [
          {
            "type": "rand",
            "packet": "4-4",
            "delay": { "from": 0, "to": 1 },
            "applyTo": "ipv4"
          }
        ]
      }
    }
  ]
}

Полностью заблокировать QUIC (UDP/443) и затягивать соединения к приватным диапазонам, чтобы замедлить зондирование:

json
{
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {
        "finalRules": [
          { "action": "block", "network": "udp", "port": "443" },
          { "action": "block", "ip": ["geoip:private"], "blockDelay": { "from": 1000, "to": 3000 } }
        ]
      }
    }
  ]
}

Переслать весь трафик на локальный сервис (удобно для тестирования):

json
{
  "outbounds": [
    {
      "tag": "redir",
      "protocol": "freedom",
      "settings": { "redirect": "127.0.0.1:8080" }
    }
  ]
}

Примечания

  • targetStrategy — современное поле; domainStrategy читается лишь как запасной вариант, когда targetStrategy пуст (infra/conf/freedom.go:46-48). В новых конфигурациях задавайте только targetStrategy.
  • Неизвестные строки стратегии приводят к ошибке при запуске, а не к тихому откату к значению по умолчанию (infra/conf/freedom.go:72-73).
  • noise (в единственном числе) удалено. Сообщение об ошибке при запуске предлагает мигрировать на noises = [ { ... } ] (infra/conf/freedom.go:145-147).
  • ipsBlocked удалено и влито в finalRules. Замените его правилом { "action": "block", "ip": [...] }; старое поле теперь лишь пишет предупреждение в журнал и в остальном игнорируется.
  • Действия 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, и у этого исходящего подключения почти нет собственных параметров — переопределения адреса назначения были удалены в 1.13; используйте для этого действия маршрутизации. См. Direct — sing-box.
  • В mihomo есть столь же минимальный тип Direct; встроенный прокси DIRECT неявно присутствует в каждой конфигурации. См. Direct — mihomo.

Исходный код: infra/conf/freedom.go:19-52 · v26.7.28 (5ca6f4b)

Core Tutorial от Argsment