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:
| Node | Use |
|---|---|
TcpListener | Accept inbound TCP connections. |
UdpListener | Accept UDP traffic with per-peer state. |
TcpUdpListener | Combined TCP/UDP listener style. |
TunDevice | Read and write IP packets through a TUN interface. |
RawSocket | Work with raw IP packets. |
UdpStatelessSocket | Bind one UDP socket without per-peer connection state. |
Typical exit adapters:
| Node | Use |
|---|---|
TcpConnector | Open outbound TCP connections. |
UdpConnector | Send UDP traffic to one or more destinations. |
TcpUdpConnector | Combined TCP/UDP connector style. |
UdpStatelessSocket | Send 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 side | Server side | Purpose |
|---|---|---|
MuxClient | MuxServer | Multiplex multiple logical lines over fewer transport connections. |
EncryptionClient | EncryptionServer | AEAD-encrypt framed payloads. |
TlsClient | TlsServer | Use real TLS on the wire. |
HttpClient | HttpServer | Carry payload through HTTP/1.1, HTTP/2, or WebSocket-style flows. |
VlessClient | VlessServer | VLESS client/server framing. |
TrojanClient | TrojanServer | Trojan-style client/server framing. |
RealityClient | RealityServer | Reality-style client/server behavior. |
Socks5Client | Socks5Server | Connect to or expose SOCKS5 behavior. |
ReverseClient | ReverseServer | Build reverse tunnels when the server side cannot accept direct inbound connections. |
HalfDuplexClient | HalfDuplexServer | Split upload and download over separate directions. |
KeepAliveClient | KeepAliveServer | Add 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:
| Node | Use |
|---|---|
Router | Branch a connection to different targets based on source, destination, protocol, domain, or credentials. |
SniffRouter | Route based on sniffed traffic metadata. |
Bridge | Connect two separately declared chain sections inside one config. |
SpeedLimit | Limit throughput. |
BlackHole | Drop traffic or terminate a path intentionally. |
LoggerTunnel | Log payload or traffic events for debugging. |
Disturber | Simulate loss, corruption, or delay for tests. |
TesterClient / TesterServer | Generate and validate test traffic. |
SpeedTestClient / SpeedTestServer | Run 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:
| Node | Use |
|---|---|
TunDevice | Create or use a TUN interface for IP packets. |
RawSocket | Send and receive raw IP packets. |
WireGuardDevice | Implement WireGuard crypto and peer handling inside a WaterWall chain. |
IpOverrider | Override packet source or destination addresses. |
IpManipulator | Apply packet-level manipulations for special routing or testing cases. |
PingClient / PingServer | Carry packet payload through ICMP-like wrapping. |
PacketSender / PacketReceiver | Packet 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.
| Node | Direction |
|---|---|
PacketsToStream | Packet side to stream side. |
StreamToPackets | Stream side back to packet side. |
PacketsToConnection | Packet/lwIP traffic to normal WaterWall connection lines. |
PacketSplitStream | Split 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:
| Node | Responsibility |
|---|---|
TunDevice | Inner IP packet interface. |
WireGuardDevice | WireGuard handshake, encryption, peer state, allowed IP routing, keepalive. |
UdpStatelessSocket | Outer 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.