Skip to main content

Part 4: Choosing Nodes

WaterWall nodes are small pieces that become useful when they are composed into a chain. Before writing a config, decide what kind of traffic you have and which side owns the socket or interface.

The most common chain shape is:

entry adapter -> middle transforms -> exit adapter

For TCP:

TcpListener -> MuxClient -> VlessClient -> TlsClient -> TcpConnector

For packets:

TunDevice -> WireGuardDevice -> UdpStatelessSocket

Entry and Exit Adapters

Adapters connect WaterWall to the outside world.

Typical entry adapters:

NodeUse
TcpListenerAccept inbound TCP connections.
UdpListenerAccept UDP traffic with per-peer state.
TcpUdpListenerCombined TCP/UDP listener style.
TunDeviceRead and write IP packets through a TUN interface.
RawSocketWork with raw IP packets.
UdpStatelessSocketBind one UDP socket without per-peer connection state.

Typical exit adapters:

NodeUse
TcpConnectorOpen outbound TCP connections.
UdpConnectorSend UDP traffic to one or more destinations.
TcpUdpConnectorCombined TCP/UDP connector style.
UdpStatelessSocketSend UDP datagrams using routing context.

Listeners usually appear at the beginning of a stream chain. Connectors usually appear at the end. Packet adapters can appear on either side depending on the topology.

Transform Nodes

Transform nodes sit in the middle and change how data is carried.

Common paired transforms:

Client sideServer sidePurpose
MuxClientMuxServerMultiplex multiple logical lines over fewer transport connections.
EncryptionClientEncryptionServerAEAD-encrypt framed payloads.
TlsClientTlsServerUse real TLS on the wire.
HttpClientHttpServerCarry payload through HTTP/1.1, HTTP/2, or WebSocket-style flows.
VlessClientVlessServerVLESS client/server framing.
TrojanClientTrojanServerTrojan-style client/server framing.
RealityClientRealityServerReality-style client/server behavior.
Socks5ClientSocks5ServerConnect to or expose SOCKS5 behavior.
ReverseClientReverseServerBuild reverse tunnels when the server side cannot accept direct inbound connections.
HalfDuplexClientHalfDuplexServerSplit upload and download over separate directions.
KeepAliveClientKeepAliveServerAdd heartbeat behavior to detect broken paths.

Paired nodes must face the correct counterpart. For example, do not put EncryptionClient on both sides of the same encrypted tunnel.

Utility Nodes

Utility nodes help with policy, testing, and debugging:

NodeUse
RouterBranch a connection to different targets based on source, destination, protocol, domain, or credentials.
SniffRouterRoute based on sniffed traffic metadata.
BridgeConnect two separately declared chain sections inside one config.
SpeedLimitLimit throughput.
BlackHoleDrop traffic or terminate a path intentionally.
LoggerTunnelLog payload or traffic events for debugging.
DisturberSimulate loss, corruption, or delay for tests.
TesterClient / TesterServerGenerate and validate test traffic.
SpeedTestClient / SpeedTestServerRun throughput-oriented tests.

These nodes are powerful because they can change chain behavior without changing the entry or exit adapters.

Router Branches

Router is a rule-based branch selector. It waits for the first upstream payload, tests ordered rules, and sends the connection to the first matching rule target. If no rule matches, it uses its top-level next as the default route.

Conceptually:

TcpListener -> Router
|-- rule: TLS domain match -> premium-path
|-- rule: SSH port match -> ssh-path
`-- default next -> direct-path

Example:

{
"name": "route-by-domain-or-port",
"type": "Router",
"settings": {
"sniffing": [
"http1",
"tls"
],
"rules": [
{
"destination-domain": [
"*.example.org"
],
"target": "premium-path"
},
{
"destination-port": 22,
"target": "ssh-path"
}
]
},
"next": "direct-path"
}

Each target is the name of another node in the same config. A rule can combine multiple conditions; conditions inside one rule are matched with logical AND, and values inside one condition are usually alternatives.

Use Router when one listener should feed multiple branch chains.

Packet Nodes

Packet nodes work with IP packets or packet-like datagrams instead of ordinary TCP streams.

Common packet nodes:

NodeUse
TunDeviceCreate or use a TUN interface for IP packets.
RawSocketSend and receive raw IP packets.
WireGuardDeviceImplement WireGuard crypto and peer handling inside a WaterWall chain.
IpOverriderOverride packet source or destination addresses.
IpManipulatorApply packet-level manipulations for special routing or testing cases.
PingClient / PingServerCarry packet payload through ICMP-like wrapping.
PacketSender / PacketReceiverPacket testing and bootstrap helpers.

Packet chains are not the same as TCP connection chains. Some packet paths use a worker-level packet line that persists across many packets. Do not design packet configs as if every packet creates and destroys a normal TCP-style connection.

Packet and Stream Bridges

Some deployments need to carry packet traffic through a stream transport such as TCP or TLS. Boundary nodes handle that conversion.

NodeDirection
PacketsToStreamPacket side to stream side.
StreamToPacketsStream side back to packet side.
PacketsToConnectionPacket/lwIP traffic to normal WaterWall connection lines.
PacketSplitStreamSplit one packet side into separate persistent upload and download stream lines.

Current PacketsToStream and StreamToPackets are IPv4-only. They do not add a custom length header; they write raw IPv4 packets into the stream and recover packet boundaries from each packet's IPv4 total-length field. IPv6 and non-IPv4 payloads are dropped by those two nodes.

Basic two-server packet-over-stream shape:

server A: TunDevice -> PacketsToStream -> TlsClient -> TcpConnector
server B: TcpListener -> TlsServer -> StreamToPackets -> TunDevice

The TLS nodes are optional in the abstract shape, but real deployments usually add encryption, authentication, or camouflage around the stream path.

WireGuard Inside WaterWall

WireGuardDevice performs WireGuard crypto and peer state, but it does not open the UDP socket by itself and it does not create an operating-system WireGuard interface.

A typical topology is:

TunDevice -> WireGuardDevice -> UdpStatelessSocket

Responsibilities are split:

NodeResponsibility
TunDeviceInner IP packet interface.
WireGuardDeviceWireGuard handshake, encryption, peer state, allowed IP routing, keepalive.
UdpStatelessSocketOuter UDP socket used to send and receive WireGuard packets.

This split is important: configure the UDP bind address and port on UdpStatelessSocket, and configure WireGuard keys and peers on WireGuardDevice.

Practical Selection Guide

For a simple TCP forward:

TcpListener -> TcpConnector

For an encrypted TCP tunnel between two servers:

client side: TcpListener -> EncryptionClient -> TcpConnector
server side: TcpListener -> EncryptionServer -> TcpConnector

For multiplexing many streams over one transport path:

client side: TcpListener -> MuxClient -> TcpConnector
server side: TcpListener -> MuxServer -> TcpConnector

For VLESS over TLS:

TcpListener -> MuxClient -> VlessClient -> TlsClient -> TcpConnector

For packet traffic over a stream:

packet side A: TunDevice -> PacketsToStream -> TcpConnector
packet side B: TcpListener -> StreamToPackets -> TunDevice

For WireGuard:

TunDevice -> WireGuardDevice -> UdpStatelessSocket

After choosing the high-level shape, read the node reference page for every node you use. The exact settings object is node-specific, and newer WaterWall builds often add fields before older tutorials mention them.