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 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:

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 and transport nodes:

Client sideServer sidePurpose
MuxClientMuxServerMultiplex multiple logical lines over fewer transport connections.
EncryptionClientEncryptionServerAEAD-encrypt framed payloads.
ObfuscatorClientObfuscatorServerApply matching lightweight XOR obfuscation; this is not encryption.
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.
HeaderClientHeaderServerCarry WaterWall port metadata or trusted IPv4 PROXY-protocol information.
Bgp4ClientBgp4ServerUse BGP-like stream framing; these nodes do not implement BGP routing.
ReverseClientReverseServerBuild reverse tunnels when the server side cannot accept direct inbound connections.
ConnectionFisherClientConnectionFisherServerRace candidate paths and retain the first one confirmed by its peer.
HalfDuplexClientHalfDuplexServerSplit upload and download over separate directions.
KeepAliveClientKeepAliveServerAdd heartbeat behavior to detect broken paths.
TcpOverUdpClientTcpOverUdpServerCarry a stream over a packet-preserving UDP path using KCP.
UdpOverTcpClientUdpOverTcpServerPreserve 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:

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.
AuthenticationClient / AuthenticationServerSynchronize and serve authenticated-user data for participating nodes; this is a control path, not ordinary data forwarding.
SoftIpLimiterLimit the source IPs that can use the same early VLESS or Trojan identity.
SpeedLimitLimit throughput.
BlackHoleDrop traffic or terminate a path intentionally.
LoggerTunnelLog payload or traffic events for debugging.
DisturberSimulate loss, corruption, or delay for tests.
JunkDatagramSenderSend generated noise before real traffic on a datagram-preserving path.
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 IPv4 packets through paired ICMP Echo Requests and exact Echo Reply acknowledgements.
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, Stream, and Connection Bridges​

Some deployments need to cross packet, stream, and connection-oriented boundaries. Boundary nodes handle those conversions.

NodeBoundary or role
ConnectionToPacketsConnection with a destination context to raw IPv4 TCP/UDP packets.
PacketsToConnectionRaw IPv4 packets to normal WaterWall TCP/UDP connection lines.
PacketsToStreamPacket side to stream side.
StreamToPacketsStream side back to packet side.
PacketSplitStreamSpecial 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:

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 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.