PacketReceiver
PacketReceiver is an endpoint IPv4 packet counter. It consumes raw IPv4
packets, groups them by source IP and selected protocol number, and writes a
report file with per-IP totals and per-protocol counts.
Paired with PacketSender, it is useful for finding good, reachable, or
whitelisted source IPs in IP-restricted environments. PacketSender generates
traffic from candidate source ranges; PacketReceiver shows which source IPs
actually arrived.
Typical Placement
Receive raw IPv4 packets from a capture/output node:
RawSocket -> PacketReceiver
Receive packets from a tunnel path:
UdpStatelessSocket -> WireGuardDevice -> PacketReceiver
PacketReceiver can consume packets from upstream or downstream callbacks. It
can therefore be placed at the end of a packet chain, or at the start of a chain
where packets arrive from its next-side peer.
What It Does
- Tracks one IPv4 CIDR range or an array of IPv4 CIDR ranges.
- Allocates one counter per tracked source IP and selected protocol.
- Counts packets whose IPv4 source address and protocol match the configuration.
- Counts packets outside the configured ranges or protocols as unexpected.
- Recycles every consumed packet buffer.
- Writes a report after
report-after-ms. - Writes a final report during destroy if one has not already been written.
- Does not depend on packet-line
Finishfor completion.
The IPv4 source address and protocol number are used for matching. Port, destination address, and payload are not used for the counters.
Source-IP Allowlist Testing
For IP-restricted or allowlisted environments:
- Configure
PacketSender.source-ipv4-rangewith candidate source IP ranges. - Configure
PacketReceiver.source-ipv4-rangewith the same ranges. - Select the expected protocols with
protocol-numberand setexpected-packets-per-ipto the sender'spackets-per-ip. - Run the test and wait for the receiver report.
- Look for source IPs with low loss or full delivery.
The best candidates are the source IPs whose received count is close to
expected and whose loss-percent is low.
Configuration Example
{
"name": "packet-receiver",
"type": "PacketReceiver",
"settings": {
"source-ipv4-range": [
"198.51.100.0/24",
"203.0.113.0/24"
],
"protocol-number": ["TCP", "UDP", 253],
"expected-packets-per-ip": 100,
"report-after-ms": 7000,
"output-file": "packet-receiver-report.txt"
}
}
For a matching PacketSender using protocol-number: "ALL" and
packets-per-ip: 100, use:
{
"protocol-number": "ALL",
"expected-packets-per-ip": 100
}
The receiver multiplies by 255 for per-IP and report-wide expected totals.
Required Fields
Top-level fields:
| Field | Type | Description |
|---|---|---|
name | string | User-chosen node name. Must be unique inside the config file. |
type | string | Must be exactly "PacketReceiver". |
settings | object | Required and must not be empty. |
Required settings fields:
| Field | Type | Description |
|---|---|---|
source-ipv4-range | string or array of strings | One IPv4 CIDR range, or an array of IPv4 CIDR ranges to track. |
protocol-number | string, integer, or array | TCP, UDP, ICMP, ALL, a protocol number from 0 to 255, or a nonempty mixed array of names and numbers. ALL is only valid by itself and selects 0–254. Duplicate numbers, including named aliases, are invalid. |
The node must have either a previous or next tunnel so packets can reach it.
Optional Settings
| Setting | Type | Default | Description |
|---|---|---|---|
expected-packets-per-ip | integer | 1 | Positive expected packet count for each selected protocol at each tracked source IP. This scales loss and histograms; received counts are never capped. |
report-after-ms | integer | 1000 | Positive delay before writing the report and terminating the program. Set this longer than sender duration plus expected tunnel delay. |
output-file | string | packet-receiver-report.txt | Non-empty path for the report file. |
Pairing With PacketSender
Set receiver expected-packets-per-ip to sender packets-per-ip for every
mode, including ALL. Select the same protocols on both ends. Arrays can
select several protocols, such as [6, 17] or ["TCP", "UDP"].
report-after-ms should usually be greater than:
PacketSender duration-ms + network delay + reordering/jitter window
If the report is written too early, late packets will be counted as lost because
PacketReceiver stops updating counts after the report is marked written.
Report Format
The report is written only to output-file. It starts with summary fields:
PacketReceiver report
output-file: packet-receiver-report.txt
source-ip-count: ...
expected-packets-per-ip: ...
selected-protocol-count: ...
expected-total-packets: ...
received-total-packets: ...
lost-total-packets: ...
unexpected-packets: ...
Then it writes a total row and one row for each selected protocol per tracked
source IP. Array order is preserved; ALL uses numeric order:
source-ip | protocol-number | expected | received | lost | loss-percent | histogram
198.51.100.1 | total | 200 | 150 | 70 | 35.00% | [########################--------]
198.51.100.1 | 6 | 100 | 120 | 0 | 0.00% | [################################]
198.51.100.1 | 17 | 100 | 30 | 70 | 70.00% | [#########-----------------------]
The histogram is 32 characters wide. # represents received share and -
represents missing share relative to the expected count. Excess packets remain
in received totals while the histogram stops at full width. Per-IP loss sums
the shortfall of each selected protocol, so excess on one cannot hide another's
loss.
unexpected-packets counts packets with an unselected protocol or a source IP
outside configured ranges, plus non-IPv4 or too-short packets consumed by this node.
Direction Behavior
| Incoming callback | Behavior |
|---|---|
upstream Payload | Counts/recycles the packet. |
downstream Payload | Counts/recycles the packet. |
Init, Est, Pause, Resume, Finish | No-op. Completion is timer/report based, not line-lifecycle based. |
PacketReceiver is created with WaterWall's packet-tunnel API and has no
per-line tunnel state.
Buffer And Padding Notes
Node metadata advertises:
required_padding_left = 0
layer_group = kNodeLayer3
layer_group_next_node = kNodeLayer3
layer_group_prev_node = kNodeLayer3
The node does not prepend, frame, rewrite, or forward payloads. It consumes and recycles packet buffers after counting them.
Practical Notes
- Use the same source ranges on
PacketSenderandPacketReceiver. - Keep ranges and protocol selections small enough that one counter per source-IP/protocol pair is reasonable.
- Use a longer
report-after-msfor high-latency, high-jitter, or multi-hop tunnel paths. - In source-IP restricted environments, source IPs with low loss are the likely usable or whitelisted candidates.
- This node is for packet tests and reports, not for forwarding application traffic.
Node Metadata
Source-backed metadata:
| Property | Value |
|---|---|
| node flags | kNodeFlagChainHead | kNodeFlagChainEnd |
can_have_prev | true |
can_have_next | true |
layer_group | kNodeLayer3 |
layer_group_prev_node | kNodeLayer3 |
layer_group_next_node | kNodeLayer3 |
required_padding_left | 0 bytes |