ObfuscatorServer
ObfuscatorServer is the server-side peer for ObfuscatorClient. It uses the
same reversible payload transform and must be configured with the same method,
key, and header options.
In the current implementation, the only supported method is XOR. This node is a traffic-shaping and obfuscation layer, not an encryption layer.
ObfuscatorServer is created with WaterWall's packet-tunnel API and has no
per-line tunnel state. Payload bytes are transformed in place, except when the
optional TLS-like header mode needs to clone a buffer to get enough left
padding.
Typical Placement
Simple TCP path:
client side: TcpListener -> ObfuscatorClient -> TcpConnector
server side: TcpListener -> ObfuscatorServer -> TcpConnector
UDP path:
client side: UdpListener -> ObfuscatorClient -> UdpConnector
server side: UdpListener -> ObfuscatorServer -> UdpConnector
Raw packet path:
packet transport -> ObfuscatorServer -> RawSocket
Use the same skip and tls_record_header settings as the client side.
What It Does
- Requires
settings.method: "xor". - Requires
settings.xor_key. - Applies XOR to upstream payload bytes before forwarding to
next. - Optionally prepends a 5-byte TLS-like record header after upstream XOR.
- Optionally strips the 5-byte TLS-like header before downstream XOR.
- Applies XOR to downstream payload bytes before forwarding to the previous node.
- Can leave the IPv4 header, or IPv4 plus TCP/UDP header, unobfuscated.
- Marks packet-line payloads for checksum recalculation after changing bytes.
- Does not buffer payloads and does not keep per-line state.
The server implementation mirrors the client implementation. The client/server names describe deployment role; the transform itself is symmetric.
Configuration Example
{
"name": "obfuscator-server",
"type": "ObfuscatorServer",
"settings": {
"method": "xor",
"xor_key": 90,
"skip": "transport",
"tls_record_header": true
},
"next": "service-node"
}
Matching client:
{
"name": "obfuscator-client",
"type": "ObfuscatorClient",
"settings": {
"method": "xor",
"xor_key": 90,
"skip": "transport",
"tls_record_header": true
},
"next": "transport-node"
}
Required Fields
Top-level fields:
| Field | Type | Description |
|---|---|---|
name | string | User-chosen node name. Must be unique inside the config file. |
type | string | Must be exactly "ObfuscatorServer". |
settings | object | Required. Must contain method and xor_key. |
next | string | Required in normal use. The next node receives transformed upstream payloads. |
Required settings fields:
| Field | Type | Description |
|---|---|---|
method | string | Must be "xor" in the current implementation. |
xor_key | integer | XOR key. The value is stored as one byte, so values outside 0..255 are converted to uint8_t. |
Optional Settings
| Setting | Type | Default | Description |
|---|---|---|---|
skip | string | "none" | Leading packet headers to leave clear before XOR. Accepted values are "none", "ipv4", and "transport". |
tls_record_header | boolean | false | Adds/removes a 5-byte TLS-like application-data record header on the transport-facing payload. |
tls_header | boolean | unset | Deprecated compatibility alias for tls_record_header. If present, it is accepted and a warning is logged. |
Skip Modes
skip controls how many leading bytes are not XORed:
| Value | Behavior |
|---|---|
"none" | XOR the whole payload. |
"ipv4" | If the payload starts with a valid IPv4 packet, leave the IPv4 header clear and XOR bytes after it. |
"transport" | If the payload starts with a valid IPv4 TCP/UDP packet, leave the IPv4 header and TCP/UDP header clear. For other IPv4 protocols, leave only the IPv4 header clear. |
If the payload is too short or not a valid IPv4 packet, the skip length becomes
0 and the whole payload is XORed.
For malformed or incomplete TCP/UDP headers under skip: "transport", the
implementation falls back to leaving only the IPv4 header clear.
TLS-Like Record Header
When tls_record_header is enabled, transport-facing payloads are sent as:
17 03 03 + length(2 bytes, big-endian) + obfuscated payload
The bytes imitate a TLS application-data record header:
| Field | Value |
|---|---|
| content type | 23 / 0x17 |
| legacy version | 0x0303 |
| length | obfuscated payload length, 16-bit big-endian |
On the receive path, the header is validated and stripped before XOR runs.
This is not TLS. It has no handshake, no certificates, no SNI, no ALPN, no encryption, and no authentication. It only imitates the shape of a post-handshake TLS application-data record.
Important limits:
- payloads larger than
65535bytes are dropped when wrapping - truncated headers are dropped when stripping
- records whose declared length does not exactly match the current payload buffer length are dropped
- there is no record reassembly buffer, so receive-side payload callbacks should contain exactly one complete TLS-like record
Direction Behavior
| Incoming callback | Behavior |
|---|---|
upstream Payload | XORs according to skip, optionally prepends the TLS-like header, marks packet-line checksum recalculation, then forwards to next. |
downstream Payload | Optionally validates and strips the TLS-like header, XORs according to skip, marks packet-line checksum recalculation, then forwards to the previous node. |
downstream Init | Forwards to the previous node. |
| other lifecycle callbacks | Uses packet-tunnel default behavior. Payload transformation is the meaningful behavior of this node. |
The source also contains ordinary pass-through lifecycle callback files, but the
current create path installs only the downstream Init override plus upstream
and downstream payload overrides on top of packet-tunnel defaults.
Buffer And Padding Notes
Node metadata advertises:
required_padding_left = 5
layer_group = kNodeLayerAnything
The 5 bytes are for the optional TLS-like header. If a buffer does not have
enough left padding when tls_record_header is enabled, the node clones the
payload into a new buffer with enough padding, recycles the original buffer, and
then prepends the header.
When the current line is the worker packet line, the node sets
recalculate_checksum = true after transforming payload bytes.
Implementation Notes
The XOR helper has optimized paths:
- AVX2 when available
- aligned 64-bit chunk processing on 64-bit builds
- aligned 32-bit or byte-wise fallback otherwise
These paths change performance only; visible behavior is still byte-wise XOR with the configured one-byte key.
Practical Notes
ObfuscatorServerandObfuscatorClientmust use the samemethod,xor_key,skip, andtls_record_headersettings.- This is obfuscation, not cryptographic security.
skip: "none"is simplest for ordinary byte streams.skip: "transport"is useful for raw IPv4 TCP/UDP packets whose IP and transport headers need to remain readable.- If you only need secure encryption, use
EncryptionClientandEncryptionServerinstead.