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 tables below are a selection guide rather than a complete inventory. Use All Nodes when you need to find a specialized node, then read that node's reference page before putting it in a chain.
The most common chain shape is:
entry adapter -> middle transforms -> exit adapter
For TCP:
TcpListener -> MuxClient -> VlessClient -> TlsClient -> TcpConnector
For packets:
UdpStatelessSocket -> WireGuardDevice -> TunDevice
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 and transport nodes:
| Client side | Server side | Purpose |
|---|---|---|
MuxClient | MuxServer | Multiplex multiple logical lines over fewer transport connections. |
EncryptionClient | EncryptionServer | AEAD-encrypt framed payloads. |
ObfuscatorClient | ObfuscatorServer | Apply matching lightweight XOR obfuscation; this is not encryption. |
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. |
HeaderClient | HeaderServer | Carry WaterWall port metadata or trusted IPv4 PROXY-protocol information. |
Bgp4Client | Bgp4Server | Use BGP-like stream framing; these nodes do not implement BGP routing. |
ReverseClient | ReverseServer | Build reverse tunnels when the server side cannot accept direct inbound connections. |
ConnectionFisherClient | ConnectionFisherServer | Race candidate paths and retain the first one confirmed by its peer. |
HalfDuplexClient | HalfDuplexServer | Split upload and download over separate directions. |
KeepAliveClient | KeepAliveServer | Add heartbeat behavior to detect broken paths. |
TcpOverUdpClient | TcpOverUdpServer | Carry a stream over a packet-preserving UDP path using KCP. |
UdpOverTcpClient | UdpOverTcpServer | Preserve UDP-style datagram boundaries over a stream transport. |
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. |
AuthenticationClient / AuthenticationServer | Synchronize and serve authenticated-user data for participating nodes; this is a control path, not ordinary data forwarding. |
SoftIpLimiter | Limit the source IPs that can use the same early VLESS or Trojan identity. |
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. |
JunkDatagramSender | Send generated noise before real traffic on a datagram-preserving path. |
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 IPv4 packets through paired ICMP Echo Requests and exact Echo Reply acknowledgements. |
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, Stream, and Connection Bridges
Some deployments need to cross packet, stream, and connection-oriented boundaries. Boundary nodes handle those conversions.
| Node | Boundary or role |
|---|---|
ConnectionToPackets | Connection with a destination context to raw IPv4 TCP/UDP packets. |
PacketsToConnection | Raw IPv4 packets to normal WaterWall TCP/UDP connection lines. |
PacketsToStream | Packet side to stream side. |
StreamToPackets | Stream side back to packet side. |
PacketSplitStream | Special packet-line split helper for named upload and return branches. |
PacketsToStream and StreamToPackets are a framing pair. They are currently
IPv4-only, add no custom length header, write raw IPv4 packets into the stream,
and recover packet boundaries from each packet's IPv4 total-length field.
ConnectionToPackets and PacketsToConnection are a flow bridge instead. They
use the in-process lwIP stack to turn normal WaterWall TCP/UDP lines into raw
IPv4 packets and back again. ConnectionToPackets needs a configured virtual
source-ipv4, only supports IPv4, and needs a return path for that address.
PacketSplitStream is more specialized: it does not frame or convert packets by
itself, but splits a packet-line layout into named upload and return branches.
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:
UdpStatelessSocket -> WireGuardDevice -> TunDevice
UdpStatelessSocket is chain-head-only. Keep it before WireGuardDevice; this
socket cannot be placed after WireGuard. The layer solver still determines
which adjacent side carries the L3 packets and which carries the L4 transport.
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 an IPv4, rootless SOCKS CONNECT-to-packet path:
local application branch: TcpListener -> Socks5Server -> ConnectionToPackets -> Bridge A
local UDP branch: UdpStatelessSocket -> WireGuardDevice -> Bridge B
remote: UdpStatelessSocket -> WireGuardDevice -> PacketsToConnection -> TcpUdpConnector
Pair Bridge A and Bridge B so the connection-to-packet branch joins the
WireGuard packet side. Each UdpStatelessSocket stays at the head of its own
chain.
Socks5Server supplies the requested destination for ConnectionToPackets.
Configure its source-ipv4 as a unique virtual address that the remote peer
allows and routes back. This is a userspace flow bridge, not a replacement for
capturing arbitrary host traffic; use TunDevice when you need an OS-level
packet interface.
For WireGuard:
UdpStatelessSocket -> WireGuardDevice -> TunDevice
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.