👻 freedom: TLS fragmentation and socket options
Since v1.19.33-r2 there is a proxy type freedom. It is DIRECT, the connection goes straight to the site, plus the fragment and sockopt settings of the Xray-core freedom outbound. Two fragmentation modes are taken from sing-box (tls_fragment, tls_record_fragment).
Fragmentation splits the TLS ClientHello so that the site name (SNI) never travels in one piece. It helps against DPI that matches the ClientHello as a whole. Use freedom through rules or groups only for the sites that need it.
proxies: - name: FRAGMENT type: freedom fragment: packets: tlshello length: "1-1" interval: "0" sockopt: tcp-congestion: bbr tcp-keep-alive-idle: 300 tcp-keep-alive-interval: 60 tcp-user-timeout: 10000 custom-sockopt: - { opt: "1", type: int, value: "1" }
rules: - DOMAIN-SUFFIX,example.com,FRAGMENTThis is the same as the Xray outbound below:
{ "protocol": "freedom", "settings": { "fragment": { "packets": "tlshello", "length": "1-1", "interval": "0" } }, "streamSettings": { "sockopt": { "customSockopt": [{ "opt": "1", "type": "int", "value": "1" }], "tcpcongestion": "bbr", "tcpKeepAliveIdle": 300, "tcpKeepAliveInterval": 60, "tcpUserTimeout": 10000 } }, "tag": "FRAGMENT"}The usual DIRECT options also work: interface-name, routing-mark, ip-version, tfo, mptcp. UDP goes out as with DIRECT.
fragment
Section titled “fragment”| Parameter | Values | What it does |
|---|---|---|
packets | tlshello, "N-M" or empty | tlshello rewrites the first ClientHello into several TLS records. "1-3" cuts the first three writes of the connection into TCP segments, empty cuts every write |
length | "N" or "N-M", bytes | Size of a piece. Required with split: length |
interval | "N" or "N-M", ms | Pause between pieces. With tlshello and 0 all records go out in one write |
max-split | "N" or "N-M" | At most this many pieces, the last one takes the rest. Empty or 0 means no limit |
split | length (default) or sni | sni: one random cut inside every label of the site name but the top-level one, as in sing-box; length is not needed then |
wait | interval (default) or ack | ack: every piece goes in its own TCP segment and the next one waits until the server acknowledged it, as in sing-box |
fallback-delay | ms, 500 by default | The pause for wait: ack where the acknowledgement can’t be seen |
- Ranges work as in Xray: the upper bound is not included, so
"100-200"gives 100 to 199. - A large ClientHello (with post-quantum keys) often comes in several writes.
freedomholds it until the record is complete and only then cuts it. Xray in this case sends it uncut. - After the fragmented part the connection works at full speed: data is copied between the sockets directly again.
- With
wait: ackthe acknowledgement is read on Linux, Android, macOS and iOS. On Windows and other systemsfallback-delayis used. An acknowledgement that comes back faster than 20 ms is taken for one from a middlebox, not from the server, andfallback-delayis waited too. For nearby servers lower it, otherwise every piece costs 500 ms.
sockopt
Section titled “sockopt”| Parameter | Values | What it does |
|---|---|---|
tcp-congestion | bbr, cubic, … | TCP congestion control. Linux and Android only |
tcp-user-timeout | ms | How long sent data may stay unacknowledged before the connection is closed. Linux and Android only |
tcp-keep-alive-idle | seconds | Idle time before the first keep-alive probe. A negative value turns keep-alive off |
tcp-keep-alive-interval | seconds | Interval between keep-alive probes |
custom-sockopt | list | Any socket option, as customSockopt in Xray |
custom-sockopt fields:
opt: option number;value: its value;type:int(default) orstr;level:6(TCP) by default;system:linux,windows,darwinor empty for every system;linuxalso applies on Android;network:tcp,tcp4,tcp6or empty.
Numbers can be decimal or 0x…. On Windows only int values work.
An option the system or the kernel does not support, for example bbr on many Android phones, is skipped with one warning in the log. The connection works without it.