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, с предупреждением переносится в streamSettings.sockopt.domainStrategy (те же значения); задавайте его там. Как разрешается адрес назначения перед установкой соединения. asis передаёт адрес в том виде, в каком его выдал движок маршрутизации; useip* разрешает в IP только при необходимости; forceip* всегда разрешает и подставляет IP. Суффиксы *v4v6 / *v6v4 задают, какое семейство адресов пробуется первым.
domainStrategystring(inherits targetStrategy)<same values>Устаревший псевдоним для targetStrategy. Читается только когда targetStrategy пуст. Устарело вместе с targetStrategy.
redirectstring(unset)<host:port>Переопределяет адрес назначения каждого соединения. Полезно для пересылки на локальный сервис независимо от маршрутизации.
userLeveluint320<uint32>Уровень политики по умолчанию для соединений, проходящих через это исходящее подключение.
fragment*Fragment(disabled)FragmentПосегментная фрагментация TCP для обхода DPI, анализирующего длины пакетов.
noise*Noise(unsupported)(use noises)Не поддерживается — используйте массив noises. Установка noise приводит к явной ошибке при сборке конфигурации.
noises[]*Noise(unset)[Noise]Список шумовых пакетов, отправляемых перед реальными пакетами (или между ними), чтобы сбить сопоставление шаблонов.
proxyProtocoluint3200 | 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 ​

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

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.9.9 (52a412d)

finalRules[] ​

Небольшой межсетевой экран allow/block, который исходящее подключение freedom применяет при установке соединения. Правила вычисляются по порядку; решает первое совпадение. Блокировка IP задаётся здесь — поле 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.9.9 (52a412d)

Примеры ​

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

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

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

json
{
  "outbounds": [
    {
      "tag": "direct-v4",
      "protocol": "freedom",
      "settings": {},
      "streamSettings": { "sockopt": { "domainStrategy": "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 в settings freedom устарели. При запуске 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)

Core Tutorial от Argsment