Skip to content

Freedom — Xray-core ​

Freedom 是 Xray 的旁路出站 —— 把流量直接送往真实目标,中间不加任何代理协议层。另外它还携带两个反 DPI 功能:TCP / TLS 分片与任意噪声包注入。

出站 ​

"protocol": "freedom" 出站的 settings:

字段类型默认值允许值描述
targetStrategystringasisasis | useip | useipv4 | useipv6 | useipv4v6 | useipv6v4 | forceip | forceipv4 | forceipv6 | forceipv4v6 | forceipv6v4已弃用 —— 启动时非 asis 的值会被迁移到 streamSettings.sockopt.domainStrategy(取值相同)并记录警告;请改为直接设置后者。拨号前如何解析目的地址。asis 透传路由引擎给出的值;useip* 仅在必要时解析为 IP;forceip* 总是解析并替换。*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 协议头。0 关闭;1 / 2 分别使用 v1(文本)或 v2(二进制)。
ipsBlocked*StringList(ignored)(use finalRules)不受支持 —— 请用 finalRules 表达 IP 拦截;设置它只会记录一条警告,没有实际作用。
finalRules[]*FreedomFinalRuleConfig(unset)[FreedomFinalRuleConfig]在拨号时按连接求值的放行 / 拦截规则 —— 即出站自身上的一个轻量防火墙,按 network / port / 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[] ​

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-hello 分片(SNI 混淆的良好起点):

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

噪声注入(每条 IPv4 连接前 4 字节随机数据,延迟 0–1 ms):

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" }
    }
  ]
}

说明 ​

  • freedom settings 中的 targetStrategy / domainStrategy 已弃用。启动时 Xray 会把非 asis 的值迁移到 streamSettings.sockopt.domainStrategy 并记录警告;freedom 出站上的出站级 targetStrategy 也以同样方式迁移(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 不受支持 —— 请在 finalRules 中以 { "action": "block", "ip": [...] } 规则表达;该字段本身只会记录一条警告,其余被忽略。
  • finalRules 的动作仅有 allow / block(未知动作会在启动时报错)。ip 接受 geoip: 类目;blockDelay 仅对 block 规则生效。
  • fragment.packets: "tlshello" 是推荐起点 —— 只分片 TLS ClientHello 能击穿基于 SNI 的 DPI,又不影响连接其余部分(开销是一次性的)。
  • 启用 fragment 时 fragment.length.from 与 fragment.interval 必填(infra/conf/freedom.go:102-118)。maxSplit 范围可选。
  • 1..2 之外的 proxyProtocol 会被静默忽略 —— 只有这两个值会输出头(infra/conf/freedom.go:162-164)。

跨内核说明 ​

  • sing-box 把这种能力命名为 Direct,出站本身几乎没有自身选项 —— 没有目的地覆盖字段;同等效果请使用 route action。参见 Direct — sing-box。
  • mihomo 也有同样精简的 Direct 类型;每个配置中都隐含内置的 DIRECT 代理。参见 Direct — mihomo。

源码: infra/conf/freedom.go:19-52 · v26.9.9 (52a412d)

由 Argsment 出品的 Core Tutorial