Block IPv6 for selected BNG subscribers#
| Activity name | Block IPv6 for selected BNG subscribers |
| Short Description | Block IPv6 connectivity for subscribers that match a specific criteria |
| Difficulty | Intermediate |
| Tools used | MicroPython, Python policy |
| Topology Nodes | PE4 (BNG) |
| References | MD-CLI User Guide TPSDA Guide RADIUS Attributes Reference Guide Python policy overview SR BNG TPSDA Python 3 API BNG Blaster |
1. Objective#
You are a network administrator for an Internet Service Provider. A recent change in company policy requires IPv6 connectivity to be disabled for a specific category of subscribers, in line with business and service requirements.
A subscriber falls into this category if both of the following conditions are met:
- The IPv4 address is assigned by RADIUS (via the
Framed-IP-Addressattribute) - The assigned IPv4 address falls within the range 10.24.1.10–10.24.1.19
Assuming that the RADIUS server does not support the granularity required to enforce this requirement selectively, your goal is to implement this control on the 7750 SR BNG by leveraging the python-policy feature to inspect and modify RADIUS Access-Accept messages.
2. Technology explanation#
2.1 Subscribers, sessions and hosts#
In Nokia SROS subscriber management terminology, subscriber, subscriber-sessions and subscriber-hosts are related but distinct concepts:
- Subscriber: Represents a residential or small business user, uniquely identified by a
subscriber-id(a string of characters). A subscriber is composed by one or more sessions/hosts. - Subscriber-Host: Represents a single IP stack on an end-device (e.g. a PC, CPE or set-top box) requesting a service. It is identified by a unique combination that may include SAP ID, IP address, MAC address or PPPoE Session ID.
- Subscriber-Session: A grouping of one or more subscriber-hosts that represent the different IP stacks of the same end-device. An IPoE dual-stack client (having 1x IPv4 and 1x IPv6 address assigned by DHCP) is an example scenario of a subscriber session grouping 2 hosts.
2.2 Subscriber authentication via RADIUS#
RADIUS is common method used by ISPs to authenticate subscribers. The typical flow for an IPoE DHCP subscriber is:
- Subscriber host attempts to get an IP address (sends a DHCP Discover).
- BNG captures this request and, in the background, sends an Access-Request message to the RADIUS server for authentication.
- If authentication is successful, RADIUS replies with Access-Accept message to the BNG. This message may include attributes that BNG will then use to instantiate the subscriber host with the desired configuration.
- BNG (RADIUS client) reads the Access-Accept message and process the attributes inside.
- DHCP process continues (Offer, Request, Ack), and if there are no errors, the subscriber host is instantiated in the system.
2.3 Python policy#
User-defined python scripts can be used to intercept and modify RADIUS messages between the BNG RADIUS client and the RADIUS server. This is done via the SR OS python policy framework using the following base building blocks:
- python-script: Implements the logic to inspect the contents of RADIUS message and take actions.
- python-policy: Enables python-script evaluation for desired combination of RADIUS message types and direction (inbound or outbound).
3. Tasks#
You should read these tasks from top-to-bottom before beginning the activity.
It is tempting to skip ahead but tasks may require you to have completed previous tasks before tackling them.
3.1 Analyze the current situation#
Login to PE4, explore the subscribers and identify at least one that matches the target category.
Note
All subscriber-hosts are instantiated in the vprn service id 401 ("bng-vprn").
Tip
List of commands that may help you explore:
show service subscriber-using # list all subscribers
show service active-subscribers hierarchy # Display all subscribers, sessions and hosts in a hierarchical view
show service active-subscribers subscriber <id> # inspect hosts owned by a specific subscriber
show service active-subscribers subscriber <id> detail # inspect details about a specific subscriber
show service id "401" subscriber-hosts # list all subscriber hosts in the service
show service id "401" subscriber-hosts ip <ip_address> detail # list details about a particular host identified by the IP address.
show service id 401 dhcp[6] lease-state #list all dhcpv4 or dhcpv6 leases
show service id 401 dhcp[6] lease-state ip[v6]-address detail # display details about a particular host DHCPv4 or DHCPv6 lease
show service id "401" pppoe session [detail] # list pppoe hosts (optionally use detail to display more info)
show service id "401" ipoe session [detail] # list ipoe hosts (optionally use detail to display more info)
To know if a particular subscriber IPv4 address was explicitly assigned by RADIUS (via Framed-IP-Address attribute), look for fields such as Address Origin or IP Origin in the detailed outputs.
Following are 3 examples:
A:admin@g1-pe4# show service id "401" subscriber-hosts ip x.x.x.x detail
===============================================================================
Subscriber Host table
===============================================================================
Sap
IP Address
MAC Address PPPoE-SID Origin Fwding State
Subscriber
-------------------------------------------------------------------------------
[x/x/x/x:x]
x.x.x.x
xx:xx:xx:xx:xx:xx N/A DHCP Fwding
xxxxxxxxx
-------------------------------------------------------------------------------
Subscriber-interface : xxxx
Group-interface : xxxx
Sub Profile : xxxx
SLA Profile : xxxx
App Profile : N/A
Egress Q-Group : N/A
Egress Vport : N/A
Acct-Session-Id : xxxxxx
Acct-Q-Inst-Session-Id: xxxxxx
Address Origin : AAA
OT HTTP Rdr IP-FltrId : N/A
OT HTTP Rdr Status : N/A
OT HTTP Rdr Fltr Src : N/A
HTTP Rdr URL Override : N/A
GTP local break-out : No
DIAMETER session ID Gx: N/A
-------------------------------------------------------------------------------
Number of subscriber hosts : 1
===============================================================================
A:admin@g1-pe4# show service id "401" ipoe session ip-address x.x.x.x detail
===============================================================================
IPoE sessions for service 401
===============================================================================
SAP : [x/x/x/x:x]
Mac Address : xx:xx:xx:xx:xx:xx
Circuit-Id : xxxxxxx
Remote-Id : xxxxxxx
Session Key : sap-mac
MC-Standby : No
Subscriber-interface : xxxxxx
Group-interface : xxxxxx
Termination Type : local
Up Time : 0d 04:04:32
Session Time Left : N/A
Last Auth Time : 03/17/2026 17:25:16
Min Auth Intvl (left) : 0d 00:05:00 (0d 00:00:29)
Persistence Key : N/A
Subscriber : "xxxxx"
Sub-Profile-String : "xxxxxx"
SLA-Profile-String : "xxxxx"
SPI group ID : (Not Specified)
ANCP-String : "xx:xx:xx:xx:xx:xx"
Int-Dest-Id : ""
App-Profile-String : ""
Category-Map-Name : ""
Acct-Session-Id : "xxxxxxxxxxxx"
Sap-Session-Index : x
IP Address : x.x.x.x
IP Origin : Radius
Address-Pool : N/A
(...)
A:admin@g1-pe4# show service id 401 pppoe session ip-address x.x.x.x detail
===============================================================================
PPPoE sessions for svc-id 401
===============================================================================
Sap Id Mac Address Sid Up Time Type
IP/L2TP-Id/Interface-Id MC-Stdby
-------------------------------------------------------------------------------
[x/x/x/x:x] xx:xx:xx:xx:xx:xx x 0d 04:34:03 local
x.x.x.x
xx:xx:xx:xx:xx:xx:xx:xx
LCP State : Opened
IPCP State : Opened
IPv6CP State : Opened
PPP MTU : 1492
PPP Auth-Protocol : CHAP
PPP User-Name : xxxxxxx
Subscriber-interface : xxxxx
Group-interface : xxxxx
IP Origin : radius
DNS Origin : none
NBNS Origin : none
(...)
Tip
To get a list of all subscriber-hosts IP addresses you can use show service id "401" subscriber-hosts or show service active-subscribers hierarchy. And then explore a few by using one of the above commands.
3.2 Analyze RADIUS Access-Accept messages#
Inspect the contents of the Access-Accept messages for one of the relevant subscriber sessions.
Configure a new log (with a new log-id) to monitor the debug stream. Then enable RADIUS debugging and monitor the output.
If you need assistance
Note
This should be already pre-configured in PE4.
[gl:/configure log log-id "21"]
A:admin@g1-pe4# info
admin-state enable
description "debug log"
source {
debug true
}
destination {
cli {
}
}
To subscribe/unsubscribe that log-id on your current terminal session, use the following commands respectively:
Tip
To restart the subscriber session associated with a particular MAC-address, use the following command in your hackathon instance:
The session-idX (decimal) maps to the host MAC address least significant bits. For example session-id 4 corresponds to the host with MAC-address 02:00:00:00:00:04. The session-id can also be consulted in the remote-id identifier, which is displayed in the show service id 401 ipoe session detail or show service id 401 ppp session detail output.A:admin@g3-pe4# show service id 401 ipoe session mac 02:00:00:00:00:04 detail
===============================================================================
IPoE sessions for service 401
===============================================================================
SAP : [1/1/c5/1:100]
Mac Address : 02:00:00:00:00:04
Circuit-Id : agg1-e1/1:100
Remote-Id : session4
Session Key : sap-mac
(...)
Alternatively, you can force-clear a particular session on the BNG. When using this method, PPP clients will quickly attempt reestablishment, but IPoE (DHCP) clients will only do it after the DHCP lease-time expires:
On session reconnect, some RADIUS debug messages are expected and session Up Time should reset:
51 2026/04/06 16:40:12.524 UTC minor: DEBUG #2001 Base RADIUS
RADIUS: Transmit
Access-Request(1) 10.64.13.0:1812 id 189 len 139 vrid 1 pol RadPolicy1
USER NAME [1] 17 02:00:00:00:00:04
PASSWORD [2] 16 yAAo.bVJ7OmQSy3s6aleQ.
NAS IP ADDRESS [4] 4 10.46.3.24
VSA [26] 25 DSL(3561)
AGENT CIRCUIT ID [1] 13 agg1-e1/1:100
AGENT REMOTE ID [2] 8 session4
NAS PORT TYPE [61] 4 Ethernet(15)
NAS PORT ID [87] 12 1/1/c5/1:100
VSA [26] 19 Nokia(6527)
CHADDR [27] 17 02:00:00:00:00:04
A:admin@g3-pe4# show service id 401 ipoe session
===============================================================================
IPoE sessions for svc-id 401
===============================================================================
Sap Id Mac Address Up Time MC-Stdby
Subscriber-Id
[CircuitID] | [RemoteID]
-------------------------------------------------------------------------------
[1/1/c5/1:10] 02:00:00:00:00:01 0d 00:33:15
cafe
[1/1/c5/1:12] 02:00:00:00:00:03 4d 07:49:27
babe
[1/1/c5/1:100] 02:00:00:00:00:04 0d 00:00:07
1/1/c5/1:100
[1/1/c5/1:101] 02:00:00:00:00:06 4d 07:49:26
1/1/c5/1:101
-------------------------------------------------------------------------------
CID | RID displayed when included in session-key
Number of sessions : 4
===============================================================================
Examine the Access-Accept message
Write down your answer to the following questions, you may need them later:
- Which attribute needs to be inspected by python script to evaluate if the subscriber matches the target category?
- Which attributes are relevant for the subscriber address assignment? How those interact with the current BNG configuration?
3.3 Apply a python-policy for RADIUS Access-Accept messages.#
By now you should have a mental plan on how to accomplish the goal. It's time to start implementation.
Configure a python-policy/python-script so that inbound Access-Accept RADIUS messages are intercepted and passed transparently without modification (you will change the script behavior in later tasks).
- Create a python script file inside
cf3:/that contains at least one line of code. - Define a
python-scriptunder/configure python python-script. - Define a
python-policyunder/configure python python-policy. - Apply the
python-policyunder the relevant/configure aaa radius server-policythat is being used to authenticate the subscribers.
Tip
Enable debug for your python-script execution. Note this debug has not yet migrated to MD-CLI, so it needs to be enabled from Classic CLI context. You can quickly switch between those modes using //
[/]
A:admin@g1-pe4# //
INFO: CLI #2051: Switching to the classic CLI engine
INFO: CLI #2050: Classic CLI modification of the configuration is not allowed - 'model-driven' management interface configuration mode active
*A:g1-pe4# debug python python-script xxxxx script-all-info
no debug Don't forget to use // to switch back to the model-driven CLI.
Test the python-script execution by forcing a single subscriber to re-authenticate.
How to force re-authentication?
One way to do it is to restart the subscriber session on the end-device
If all goes well, a sequence of 3 debug messages should be logged, indicating that python-script intercepted the Access-Accept message successfully:
192 2026/04/06 17:37:04.752 UTC minor: DEBUG #2001 Base Python Output
Python Output: xxxxx
193 2026/04/06 17:37:04.752 UTC minor: DEBUG #2001 Base Python Result
Python Result: xxxxx
194 2026/04/06 17:37:04.752 UTC minor: DEBUG #2001 Base RADIUS
RADIUS: Script
Access-Accept(2) id 252 len 338 from 10.64.13.0:1812 policy xxxxx status success
Note
Python-script file modifications do not take effect automatically. To apply your updates, reload the script using:
To verifypython-script in-service status and last-update time, use: Help
- Inspect the vprn configuration and find the first reference point to the radius authentication policy
- In MD-CLI configuration context, you can use
info flat | match radiusto search for configured lines that include the keywordradius. - You can create/edit PE4
cf3:/files using the CLI built-infile edittool, directly from the hackathon instance by accessing/home/nokia/SReXperts/clab/clab-srexperts/pe4/A/config/cf3, or by uploading them to the node using SFTP
configuration
/configure python python-script "my_script" admin-state enable
/configure python python-script "my_script" action-on-fail passthrough
/configure python python-script "my_script" urls ["cf3:/radius.py"]
/configure python python-script "my_script" version python3
/configure python python-policy "rpol" radius access-accept direction ingress script "my_script"
/configure aaa radius server-policy "RadPolicy1" python-policy "rpol"
python script
#The pass statement can be used as a placeholder when code is to be included in the future.
pass
Access-Accept messages are passed through unaltered to the BNG RADIUS client application. On the next tasks you will develop this script in order to inspect and conditionally modify the contents of RADIUS messages. 3.4 Develop the python-script logic to identify the target subscribers#
Note
For this and next tasks, refer to RADIUS SR BNG TPSDA Python 3 API for how to inspect or modify attributes in a RADIUS message.
Modify the python-script to evaluate if a given subscriber matches the target category.
Tip
Have the script print a message if the condition matches, so you can visualize in debug log that evaluation is successful for the intended subscriber only.
Hint
Make use of python3 standard lib module ipaddress to simplify operations over IP addresses.
3.5 Finalize the changes to achieve the objective#
Modify the python-script (and BNG configuration, if you think it is needed) to make sure that IPv6 hosts are not created for the subscribers that match the target category.
3.6 Test functionality#
Restart all subscriber sessions and verify that IPv6 hosts are blocked ONLY for the target category of subscribers.
A:admin@g1-pe4# show service active-subscribers hierarchy
===============================================================================
Active Subscribers Hierarchy
===============================================================================
-- 1/1/c5/1:100
(SUB_PROF1)
|
+-- sap:[1/1/c5/1:100] - sla:SLA_PROF1
|
+-- IPOE-session - mac:02:00:00:00:00:04 - svc:401
|
|-- 10.24.1.129 - DHCP
|
|-- 2010:4:a:c::1/128 - DHCP6
|
+-- 2010:4:d:2c::/64 - DHCP6-PD
-- 1/1/c5/1:101
(SUB_PROF1)
|
+-- sap:[1/1/c5/1:101] - sla:SLA_PROF1
|
|-- PPP-session - mac:02:00:00:00:00:05 - sid:1 - svc:401
| | circuit-id:agg1-e1/2:101
| | remote-id:session5
| |
| |-- 10.24.1.127 - IPCP
| |
| +-- 2010:4:d:2a::/64 - DHCP6-PD
|
+-- IPOE-session - mac:02:00:00:00:00:06 - svc:401
|
|-- 10.24.1.130 - DHCP
|
|-- 2010:4:a:d::1/128 - DHCP6
|
+-- 2010:4:d:2d::/64 - DHCP6-PD
-- 1/1/c5/1:102
(SUB_PROF1)
|
+-- sap:[1/1/c5/1:102] - sla:SLA_PROF1
|
+-- PPP-session - mac:02:00:00:00:00:07 - sid:1 - svc:401
| circuit-id:agg1-e1/2:102
| remote-id:session7
|
|-- 10.24.1.128 - IPCP
|
+-- 2010:4:d:2b::/64 - DHCP6-PD
-- babe
(SUB_PROF1)
|
+-- sap:[1/1/c5/1:12] - sla:SLA_PROF1
|
+-- IPOE-session - mac:02:00:00:00:00:03 - svc:401
|
+-- 10.24.1.14 - DHCP
-- beef
(SUB_PROF1)
|
+-- sap:[1/1/c5/1:11] - sla:SLA_PROF1
|
+-- PPP-session - mac:02:00:00:00:00:02 - sid:1 - svc:401
| circuit-id:agg1-e1/2:11
| remote-id:session2
|
+-- 10.24.1.13 - IPCP
-- cafe
(SUB_PROF1)
|
+-- sap:[1/1/c5/1:10] - sla:SLA_PROF1
|
+-- IPOE-session - mac:02:00:00:00:00:01 - svc:401
|
|-- 10.24.1.20 - DHCP
|
|-- 2010:4:a:cafe::/128 - DHCP6
|
+-- 2010:4:d:cafe::/64 - DHCP6-PD
-------------------------------------------------------------------------------
Number of active subscribers : 6
Flags: (N) = the host or the managed route is in non-forwarding state
===============================================================================
Solution
from alc import radius
import ipaddress
start_address = ipaddress.IPv4Address('10.24.1.10')
end_address = ipaddress.IPv4Address('10.24.1.19')
framedip_bytes = radius.attributes.get((8,))
if framedip_bytes:
framedip = ipaddress.IPv4Address(framedip_bytes)
if framedip >= start_address and framedip <= end_address:
radius.attributes.clear((100,)) #clear Framed-IPv6-Pool VSA
radius.attributes.clear((26,6527,131)) #clear Alc-Delegated-IPv6-Pool VSA
radius.attributes.clear((123,)) # clear Delegated-IPv6-Prefix VSA
radius.attributes.clear((97,)) # clear Framed-IPv6-Prefix VSA
Did you arrive to similar solution?
There is (at least) one alternative way to solve it.
4. Summary#
Congratulations! If you have got this far you have tackled the complex task of integrating Python code into the RADIUS authentication data-path to modify RADIUS messages on the fly, adjusting their attributes and solving the objective of restricting IPv6 for specific user groups.
In this exercise you have:
- Used the
python-policyfeature to inspect RADIUS messages - Written code in Python
- Worked with debug and other troubleshooting tools
- Manipulated RADIUS attributes
- Used customization with code to troubleshoot and provide workaround to limitations of RADIUS servers