11. Lawful Interception and LEA validation
This test validates that the BNG sends intercepted traffic to the LIG/LEA and that both the web UI and the APIs reflect the flows for subscriber ONT-001.
11.0 Select the scenario before starting
Before enabling LI, confirm which scenario you are in:
| Scenario | How the subscriber appears on the BNG | Primary WAN for ATP 11 | Script |
|---|---|---|---|
| Normal RADIUS | ONT-001 | wan2 | ont1-subscriber-traffic.sh |
| LUDB fallback | usually <MAC>|<SAP> | wan1 | ont1-subscriber-traffic.sh |
| PPPoE alternative | ONT-002 / test@test.com | ppp0 | ont2-subscriber-traffic.sh |
Recommended pre-check:
A:admin@MASTER# show service active-subscribers
Expected result:
- without AAA fallback to LUDB,
ONT-001should appear under its normal alias and the simplest ATP 11 path iswan2 - with LUDB fallback, use the exact active
subscriber-idreturned by the BNG and keep the whole run on that same WAN
All traffic scripts referenced in this section are located under configs/cbot/scripts/.
Practical rule for li-source:
- before LUDB fallback, the identifier that works consistently is the subscriber alias, for example
subscriber "ONT-001" - after LUDB fallback, that alias may stop resolving and the correct identifier becomes the exact active
subscriber-idreturned by the BNG, for example00:d0:f6:01:01:01|1/1/c2/1:50.150 - there is no single
subscribervalue that is universal across both states - if you need a reusable workflow, first discover the real active identifier and then build
li-sourcewith that value
Important iperf3 note:
ont1-subscriber-traffic.shandont2-subscriber-traffic.shnow setIPERF_MSS=1400by default- this avoids the lab case where the TCP session negotiated a jumbo
MSSclose to9440, sent an initial burst, and then stalled with no sustained traffic - if you override
IPERF_MSS, keep a conservative value or validate yourself that the path can carry large TCP segments reliably
11.1 Start the TCP test server
Start iperf3 on the dns node:
bash configs/cbot/scripts/dns-iperf-server.sh start
Verify that it is listening on 2001:db8:aaaa::2:5201:
bash configs/cbot/scripts/dns-iperf-server.sh status
Expected result:
statusmust show aLISTENline for2001:db8:aaaa::2:5201- if
statusdoes not show the listener, do not continue withuploadordownload
11.2 Enable interception on the BNG
From the liadmin user on the active BNG:
- without LUDB fallback, the simplest validated flow is to use
subscriber "ONT-001" - if LUDB fallback has already been applied,
ONT-001stops appearing as an alias on the BNG; in that case use the exact activesubscriber-idreturned byshow service active-subscribers ONT-002can also be used as a PPPoE alternative, but the main ATP path remainsONT-001because it is the clearest IPoE validation
A:liadmin@MASTER# li private
[pr:/li]
A:liadmin@MASTER# li-source "li-dest-1" subscriber "ONT-001" ingress true
A:liadmin@MASTER# li-source "li-dest-1" subscriber "ONT-001" egress true
A:liadmin@MASTER# li-source "li-dest-1" subscriber "ONT-001" intercept-id 1001
A:liadmin@MASTER# li-source "li-dest-1" subscriber "ONT-001" session-id 1
A:liadmin@MASTER# log log-id "1" netconf-stream "li"
A:liadmin@MASTER# log log-id "1" source li true
A:liadmin@MASTER# log { log-id "1" destination netconf }
A:liadmin@MASTER# commit
Note:
- the LIG in this lab consumes the BNG UDP mirror (
ip-udp-shim) netconf-stream "li"is still operationally useful, but the LEA panel shown in this lab is fed by the UDP listener on port11111- if the ATP is executed while AAA is in LUDB fallback, the
subscriber-idmay stop beingONT-001and show up as<MAC>|<SAP>inshow service active-subscribers - in that scenario, the most precise way to enable LI is to use the rebuilt
subscriber-idreturned by the BNG; usingSAPcan mix traffic from other sessions if they share the same circuit - the capture scope depends on how
li-sourceis defined: by subscriber alias, by exactsubscriber-id, or by the real active session context - for ATP, using the exact identity returned by the BNG for that run is the safest way to avoid mixing traffic from other sessions
Example using the exact active subscriber in LUDB fallback:
A:liadmin@MASTER# li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" ingress true
A:liadmin@MASTER# li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" egress true
A:liadmin@MASTER# li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" intercept-id 2004
A:liadmin@MASTER# li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" session-id 1
A:liadmin@MASTER# commit
Exact configuration used in the validated tests for this run:
[pr:/li]
A:liadmin@MASTER# info flat
li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" ingress true
li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" egress true
li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" intercept-id 2101
li-source "li-dest-1" subscriber "00:d0:f6:01:01:01|1/1/c2/1:50.150" session-id 1
log log-id "1" netconf-stream "li"
log log-id "1" source li true
log { log-id "1" destination netconf }
Operational reading of that configuration:
- the capture was tied to the exact
subscriber-idforwan1 - that is why the correct API queries in this validation use
intercept-id 2101 - that is also why the functional traffic tests were aligned with
ONT_WAN=wan1 - that same syntax is not the recommended one while AAA is still in its normal state; in that case you should normally intercept
subscriber "ONT-001"
Important:
configs/cbot/scripts/ont1-subscriber-traffic.shacceptsONT_WAN=wan1|wan2|wan3and automatically resolves the active IPv6 on that WAN- without AAA fallback to LUDB, the simplest validated option is
ONT_WAN=wan2, because it matches the normal dual-stack path forONT-001 wan1can also be used without fallback if you interceptedONT-001and want to validate that specific WAN; it is not the primary ATP path becausewan2is a more representative normal dual-stack case- if you are coming from LUDB fallback, use the WAN that matches the rebuilt
subscriber-idyou selected - in the current lab validation, the correct case for
ONT-001under LUDB fallback isONT_WAN=wan1 - do not mix
wan1andwan2in the same ATP 11 run; if you intercepted00:d0:f6:01:01:01|1/1/c2/1:50.150, all traffic tests must usewan1 - run
upload,download, anddns64sequentially, not in parallel - use
PARALLEL=1for ATP; higher values make the test more fragile and add no functional value for LEA - the scripts already clamp
IPERF_MSS=1400by default to avoid the initial burst with no sustained TCP traffic configs/cbot/scripts/ont2-subscriber-traffic.shis also ready if you want an alternativeONT-002PPPoE validation
Quick check:
Without fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan2 bash configs/cbot/scripts/ont1-subscriber-traffic.sh show-bind
Alternative without fallback on wan1:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh show-bind
With LUDB fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh show-bind
Expected result:
- without fallback:
ONT_WAN=wan2INTERFACE=eth3.200ONT_BIND_V6=<active ONT-001 WAN IPv6 on wan2>
- valid alternative without fallback:
ONT_WAN=wan1INTERFACE=eth1.150ONT_BIND_V6=<active ONT-001 WAN IPv6 on wan1>
- with fallback:
ONT_WAN=wan1INTERFACE=eth1.150ONT_BIND_V6=<active ONT-001 WAN IPv6 on wan1>
11.3 Generate TCP traffic from ONT1
Case without LUDB fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan2 DURATION=12 PARALLEL=1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh upload
Alternative without fallback on wan1:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 DURATION=12 PARALLEL=1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh upload
Case with LUDB fallback using the rebuilt ONT-001 subscriber:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 DURATION=12 PARALLEL=1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh upload
Do not run this command in parallel with download or dns64.
If you need another session, change ONT_WAN or provide ONT_BIND_V6 explicitly. The important point is that traffic must exit through the same session you intercepted on the BNG.
Internally it runs:
iperf3 -6 -c 2001:db8:aaaa::2 -B <active-IPv6-on-the-selected-WAN> -p 5201 -t 12 -P 1 -M 1400
In LEA you should see events such as:
PROTO = TCPIP ORIGIN = active IPv6 on the selected WANIP DESTINATION = 2001:db8:aaaa::2P.ORIGwith high ephemeral portsP.DEST = 5201
Operational note:
- after the
MSSfix,iperf3should show sustained traffic instead of only an initial burst - exact throughput is not an ATP KPI; the important point is that the TCP session stays up and LEA records both
INGRESSandEGRESSevents - if you again see
256 KBytesin the first second and then0.00 bits/sec, verify that you did not overrideIPERF_MSS
Visual reference of the expected LEA result:

11.4 Generate reverse traffic
Without fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan2 DURATION=12 PARALLEL=1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh download
Alternative without fallback on wan1:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 DURATION=12 PARALLEL=1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh download
With fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 DURATION=12 PARALLEL=1 bash configs/cbot/scripts/ont1-subscriber-traffic.sh download
Expected result:
- the command must not end with
Connection refused - the command must not end with
control socket has closed unexpectedly - LEA must show TCP flows from
2001:db8:aaaa::2:5201towards the selected WAN IPv6 classified asEGRESS
11.5 Generate DNS64/UDP traffic
Without fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan2 DURATION=10 bash configs/cbot/scripts/ont1-subscriber-traffic.sh dns64
Alternative without fallback on wan1:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 DURATION=10 bash configs/cbot/scripts/ont1-subscriber-traffic.sh dns64
With fallback:
ONT_USER=user ONT_PASS=test ONT_WAN=wan1 DURATION=10 bash configs/cbot/scripts/ont1-subscriber-traffic.sh dns64
In LEA this is usually visible as:
PROTO = UDPIP DESTINATION = 2001:db8:aaaa::2P.DEST = 53
Visual reference of the expected LEA result for DNS64/UDP:

11.6 Stop and inspect the test server
Stop iperf3:
bash configs/cbot/scripts/dns-iperf-server.sh stop
Inspect the server logs:
bash configs/cbot/scripts/dns-iperf-server.sh logs
11.7 Query the LEA APIs
General summary:
curl -s http://10.99.1.12:8080/api/stats | jq
Latest events:
curl -s 'http://10.99.1.12:8080/api/events?limit=20' | jq
Events for a specific interception:
curl -s 'http://10.99.1.12:8080/api/events?limit=100&intercept_id=<INTERCEPT_ID_USED_IN_LI>' | jq
Interception summary:
curl -s http://10.99.1.12:8080/api/intercepts | jq
11.8 Useful event queries
Top observed protocols:
curl -s 'http://10.99.1.12:8080/api/events?limit=500&intercept_id=<INTERCEPT_ID_USED_IN_LI>' \
| jq -r 'group_by(.proto)[] | "\(.[0].proto): \(length)"'
Top source IPs:
curl -s 'http://10.99.1.12:8080/api/events?limit=500&intercept_id=<INTERCEPT_ID_USED_IN_LI>' \
| jq -r 'group_by(.src_ip)[] | "\(.[0].src_ip): \(length)"'
Top destination IPs:
curl -s 'http://10.99.1.12:8080/api/events?limit=500&intercept_id=<INTERCEPT_ID_USED_IN_LI>' \
| jq -r 'group_by(.dst_ip)[] | "\(.[0].dst_ip): \(length)"'
Top destination ports:
curl -s 'http://10.99.1.12:8080/api/events?limit=500&intercept_id=<INTERCEPT_ID_USED_IN_LI>' \
| jq -r 'map(select(.dst_port != null)) | group_by(.dst_port)[] | "\(.[0].dst_port): \(length)"'
Traffic split by INGRESS and EGRESS:
curl -s 'http://10.99.1.12:8080/api/events?limit=500&intercept_id=<INTERCEPT_ID_USED_IN_LI>' \
| jq -r 'group_by(.direction)[] | "\(.[0].direction): \(length)"'
Unique flows src_ip:src_port -> dst_ip:dst_port:
curl -s 'http://10.99.1.12:8080/api/events?limit=500&intercept_id=<INTERCEPT_ID_USED_IN_LI>' \
| jq -r '.[] | "\(.proto) \(.src_ip):\(.src_port) -> \(.dst_ip):\(.dst_port)"' \
| sort | uniq -c
11.9 Operational notes
- If the APIs return zero counters or empty lists, there is usually no intercepted traffic active at that moment.
- If
li-sourceis configured on the wrong BNG, the LIG will not receive packets even though the panel itself is operational. - If
ONT-001disappears because of LUDB fallback, do not automatically replace it withONT-002. First inspectshow service active-subscribersand use the exact activesubscriber-idforONT-001. - Without AAA fallback to LUDB, the main ATP 11 run for
ONT-001useswan2. wan1is also valid without fallback if you want to observe that specific session.- Under LUDB fallback, the validated ATP 11 run for
ONT-001useswan1. - The correct WAN must always match the identity intercepted in
li-source. - If you intercept by exact
subscriber-id, query the API with that realintercept-idand generate traffic on that same session. - If AAA is still normal, do not assume a
<MAC>|<SAP>stylesubscriber-idwill work for LI; in that state use the subscriber alias exposed by the BNG, for exampleONT-001. - If you want a generic method, the right approach is not to hardcode one string but to resolve the currently active subscriber identity first and use that identity in the capture.
- If you test
wan3or mixwan1andwan2in the same run, that is a different validation and must not be mixed with the main ATP path. ONT-002can also be validated now because the LIG parser decodes PPPoE session traffic with IPv6/IPv4.- For the clearest LEA validation, combine one TCP test (
iperf3) and one UDP test (dns64) to quickly distinguish protocols in the UI. - If
iperf3falls back into an initial burst followed by0.00 bits/sec, the most likely reason is that an overly largeMSSis being used on that lab path. Retry with the defaultIPERF_MSS=1400.