Skip to main content

TcpUdpListener

TcpUdpListener is a chain-head adapter wrapper around TcpListener and UdpListener. It creates one internal TCP listener and one internal UDP listener with the same listener settings, so a single WaterWall entry node can accept both TCP and UDP traffic on the same address and port set.

This node does not translate TCP into UDP, and it does not translate UDP into TCP. It only lets both transport adapters feed one shared next node.

Typical Placement

Use TcpUdpListener when the same service entry should accept both TCP and UDP:

TcpUdpListener -> SpeedTestServer
TcpUdpListener -> SniffRouter -> TcpUdpConnector
TcpUdpListener -> Router -> ...

The next node must be valid for the traffic you expect. If both TCP and UDP will arrive in production, the next node must understand both normal TCP lines and UDP peer lines, or it must route them by protocol.

Basic Example

[
{
"name": "mixed-in",
"type": "TcpUdpListener",
"settings": {
"address": "0.0.0.0",
"port": 443,
"nodelay": true,
"large-send-buffer": true,
"large-recv-buffer": true
},
"next": "mixed-out"
},
{
"name": "mixed-out",
"type": "TcpUdpConnector",
"settings": {
"address": "127.0.0.1",
"port": 8443,
"reuseaddr": true,
"nodelay": true
}
}
]

In this example, inbound TCP on port 443 is forwarded through the internal TcpListener, and inbound UDP on port 443 is forwarded through the internal UdpListener. The shared TcpUdpConnector at the end chooses its own TCP or UDP child connector from the line protocol metadata.

Multiport Example

{
"name": "mixed-public-entry",
"type": "TcpUdpListener",
"settings": {
"address": "0.0.0.0",
"port": [
443,
8443
],
"nodelay": true,
"large-send-buffer": true,
"large-recv-buffer": true,
"interface": "eth0",
"fwmark": 10,
"balance-group": "public-mixed",
"balance-interval": 30000,
"multiport-backend": "socket",
"whitelist": [
"192.0.2.0/24",
"2001:db8::/64"
],
"blacklist": [
"192.0.2.99/32"
]
},
"next": "next-node"
}

The same port list is used for both TCP and UDP. TCP port 443 and UDP port 443 are different socket protocols, so they can be bound at the same time.

Required Fields

Top-level fields:

FieldTypeDescription
namestringUser-chosen node name. Must be unique inside the config file.
typestringMust be exactly "TcpUdpListener".
settingsobjectShared listener settings passed to both internal child listeners. Must be a non-empty object.
nextstringThe node that receives both TCP lines and UDP peer lines.

Required settings fields:

FieldTypeDescription
addressstringLocal bind address for both child listeners.
port or port-rangenumber, array, or range arrayPort definition used by both TCP and UDP listeners. Exactly one of these fields is required.

Port Configuration

TcpUdpListener inherits the listener port syntax from TcpListener and UdpListener.

Single Port

{
"settings": {
"address": "0.0.0.0",
"port": 443
}
}

Explicit Port List

{
"settings": {
"address": "0.0.0.0",
"port": [
443,
8443,
2083
]
}
}

This listens only on the listed ports for both TCP and UDP.

Contiguous Port Range

{
"settings": {
"address": "0.0.0.0",
"port-range": [
40000,
40100
]
}
}

port-range must be a two-item array: [min, max].

Optional Settings

Because the same settings object is passed to both child listeners, most options are the same options documented on TcpListener and UdpListener.

SettingApplies toDescription
nodelayTCP childEnables TCP_NODELAY on accepted TCP sockets.
large-send-bufferTCP and UDP childrenSets SO_SNDBUF where supported.
large-recv-bufferTCP and UDP childrenSets SO_RCVBUF where supported.
interfaceTCP and UDP childrenRestricts sockets to a local network interface where supported.
fwmarkTCP and UDP childrenApplies a Linux-style socket mark where supported.
balance-groupTCP and UDP childrenGroups compatible same-port listeners for sticky distribution.
balance-intervalTCP and UDP childrenSticky interval for repeated clients or peers in a balance group.
initial-idle-timeout-msTCP childInitial idle timeout before listener-side TCP payload activity.
active-idle-timeout-msTCP childIdle timeout after TCP payload activity has started.
multiport-backendTCP and UDP childrenBackend used for contiguous port ranges: "iptables" or "socket".
whitelistTCP and UDP childrenAllowed client or peer IPs and CIDR ranges.
blacklistTCP and UDP childrenBlocked client or peer IPs and CIDR ranges.

For exact socket behavior, timeout defaults, and multiport implementation details, see the TcpListener and UdpListener pages.

Runtime Flow

At startup, TcpUdpListener creates two internal child tunnels:

  • TcpListener, named like <node-name>.tcp-listener
  • UdpListener, named like <node-name>.udp-listener

Both children are inserted into the chain. They own the real sockets and line lifecycle:

  • the internal TcpListener accepts TCP sockets and creates TCP lines
  • the internal UdpListener creates UDP peer lines
  • upstream callbacks from either child enter TcpUdpListener
  • TcpUdpListener forwards upstream Init, Payload, Pause, Resume, Est, and Finish to next

On the downstream path, the next node calls back into TcpUdpListener. The wrapper checks the line source protocol:

Source protocol metadataDownstream child
TCPinternal TcpListener
UDPinternal UdpListener
missing or ambiguous TCP/UDP flagsfatal configuration or routing error

This is why nodes after TcpUdpListener should preserve the line source protocol metadata.

Line Ownership

TcpUdpListener itself has no per-line state. It never creates lines and never calls lineDestroy().

Line ownership stays with the child adapter that created the line:

  • TCP lines are owned by the internal TcpListener
  • UDP peer lines are owned by the internal UdpListener

Node Metadata

PropertyValue
Node flagkNodeFlagChainHead
Previous nodeNot allowed
Next nodeRequired
Layer groupkNodeLayer4
required_padding_left0
Line state size0

Common Mistakes

  • Do not use TcpUdpListener as a protocol converter. It accepts both protocols, but it does not convert between them.
  • Do not point it at a next node that only works for TCP if UDP traffic can arrive.
  • Do not configure different TCP and UDP port sets on this wrapper; both child listeners receive the same settings.
  • Do not remove or corrupt source protocol metadata before callbacks return downstream to this node.