Removing the Internet Box
If you have your own router, there’s no reason to use Proximus’s CPE (the Internet Box, which was called BBox in the past). Indeed, the fiber comes with two devices: the ONT, which has a fiber “in” and an ethernet port “out” (trying to speak to a large audience here), and the router itself. The router takes care of WiFi and VoIP (fix phone).
A lot of people had their modem in “bridge” mode already in the past, so they’d use their own router and WiFi access point. With fiber, using the bridge mode if you don’t have telephony doesn’t make any sense, you can just get rid of the Internet Box.
It will be the subject of another post, but the gains are substantial in term of electricity consumption. The ONT only consumes around 2.5 Watts. The Internet Box consumes an additional 6.5 Watts that can be removed. So that’s 56kWh, or around 20euros of electricity per year. It also slows the down the latency by something around 1.5ms, which, knowing the latency with fiber is around 6.7ms without the box is quite consequent.
WAN Connectivity
The following explains how to get connectivity when directly connecting your router to the ONT. This tutorial assumes Ubuntu 22.04. I use ifupdown, like old people instead of the novel netplan, on 22.04 it must be installed:
sudo apt update
sudo apt install ifupdown net-tools
The traffic towards the internet must be tagged on the VLAN 20. IP address is given via DHCP. There is no more PPPoE.
My interface connected to the ONT is enx00e04c680a48
/etc/network/interfaces
auto enx00e04c680a48
iface enx00e04c680a48 inet manual
post-up /etc/network/enable_vlan.sh
iface enx00e04c680a48 inet6 manual
allow-hotplug internet0
iface internet0 inet dhcp
iface internet0 inet6 auto
dhcp 1
request_prefix 1
accept_ra 2
/etc/network/enable_vlan.sh
#/bin/bash
ip link add link enx00e04c680a48 name internet0 type vlan id 20
exit 0
The exit 0 part is an awful trick to avoid failing if the vlan is already created (for instance if you do sudo service networking restart).
That’s it. If you restart the networking service, you’ll get both an IPv4 address and an IPv6 /64 range. Interestingly, you get the /64 prefix through RA, but for your local network, you may use DHCPv6 to get a /56 range. It’s quite practical because you don’t have to subdivide the /56 range yourself.
internet0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 91.178.XX.XX netmask 255.255.240.0 broadcast 91.178.207.255
inet6 2a02:a03f:XXXX:XXXX:cd9e:7208:f4b:2751 prefixlen 64 scopeid 0x0<global>
inet6 2a02:a03f:XXXX:XXXX:2e0:4cff:fe68:a48 prefixlen 64 scopeid 0x0<global>
inet6 2a02:a03f:XXXX:XXXX:ff8d:359a:c3c6:86d3 prefixlen 64 scopeid 0x0<global>
inet6 2a02:a03f:XXXX:XXXX:f308:aacb:a438:6322 prefixlen 64 scopeid 0x0<global>
inet6 2a02:a03f:XXXX:XXXX:d800:106e:5a53:6d86 prefixlen 64 scopeid 0x0<global>
inet6 fe80::2e0:4cff:fe68:a48 prefixlen 64 scopeid 0x20<link>
inet6 2a02:a03f:XXXX:XXXX:8c4e:b44b:2fa8:ec27 prefixlen 64 scopeid 0x0<global>
inet6 2a02:a03f:XXXX:XXXX:fc26:be7c:b9fd:dc0 prefixlen 64 scopeid 0x0<global>
inet6 2a02:a03f:XXXX:XXXX:45b3:1bcb:7aef:5adf prefixlen 64 scopeid 0x0<global>
ether 00:e0:4c:XX:XX:XX txqueuelen 1000 (Ethernet)
RX packets 27423813 bytes 32859906931 (32.8 GB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 21693717 bytes 7316444742 (7.3 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
LAN Connectivity
For IPv4, it’s just standard NAT. For IPv6 you must enable IPv6 prefix delegation.
First, enable IP forwarding. If you have a firewall, remember to allow the FORWARDING traffic.
/etc/sysctl.conf
#Uncomment the following lines
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
To enable the NAT, either you directly add an IPTables rules somewhere:
sudo iptables -A POSTROUTING -s 192.168.1.0/24 -o internet0 -j MASQUERADE
Or, you add the following line for the UFW firewall, in /etc/ufw/before.rules:
-A POSTROUTING -s 192.168.1.0/24 -o internet0 -j MASQUERADE
In both cases, change your local network range according to your setup.
IPv6 Prefix Delegation
You have to add the following script found at https://wiki.debian.org/IPv6PrefixDelegation in /etc/dhcp/dhclient-exit-hooks.d/prefix_delegation:
# This script assigns a delegated IPv6 prefix obtained via DHCPv6 to another interface
#
# Usage: This scrips is designed to be called from dhclient-script (isc-dhcp-client).
#
# LOCATION: /etc/dhcp/dhclient-exit-hooks.d/prefix_delegation
# RECOMMENDED PACKAGES: ipv6calc
# CONFIGURATION OPTIONS
# Define the interface to which a delegated prefix will be assigned
# This must not be the same interface on which the prefix is learned!
IA_PD_IFACE="br0"
# Provide a space separated list of services that need to be restarted or reloaded after a prefix change
# Services must be controllable via systemd's systemctl, the default action is restart
# Service names may be followed by a colon and action name, to override the default action
# Supported actions are: restart and reload
# Example: IA_PD_SERVICES="shorewall6:reload dnsmasq"
IA_PD_SERVICES=""
# Define the location of the ipv6calc executable, if installed
# If this is empty or no executable file, no EUI-64 based IPv6 address will be calculated for the interface set in IA_PD_IFACE; instead, a static interface identifier (::1) will be appended to the prefix
# Example: IA_PD_IPV6CALC="/usr/bin/ipv6calc"
IA_PD_IPV6CALC=""
# Set to yes to make logging more verbose
IA_PD_DEBUG="yes"
# END OF CONFIGURATION OPTIONS
logger -t "dhcpv6-pd" -p daemon.info "DHCPv6-PD is running"
fn_calc_ip6addr() {
[ -z "$1" ] && return
local ia_pd_mac
local ia_pd_addr
[ -e "/sys/class/net/${IA_PD_IFACE}/address" ] && ia_pd_mac="$(cat /sys/class/net/${IA_PD_IFACE}/address)"
if [ -n "$ia_pd_mac" ] && [ -n "$IA_PD_IPV6CALC" ] && [ -x "$IA_PD_IPV6CALC" ]; then
[ "$IA_PD_DEBUG" = "yes" ] && logger -t "dhcpv6-pd" -p daemon.debug "Debug: Determined MAC address $ia_pd_mac for interface $IA_PD_IFACE."
ia_pd_addr="$("$IA_PD_IPV6CALC" -I prefix+mac -A prefixmac2ipv6 -O ipv6addr "$1" "$ia_pd_mac")"
fi
if [ -z "$ia_pd_addr" ]; then
[ "$IA_PD_DEBUG" = "yes" ] && logger -t "dhcpv6-pd" -p daemon.debug "Debug: Failed to calculate EUI-64 based IPv6 address, using static client suffix ::1 instead."
echo "$1" | sed 's#::/#::1/#'
else
echo "$ia_pd_addr"
fi
}
fn_restart_services() {
if [ -n "$IA_PD_SERVICES" ]; then
local pair
local action
local daemon
for pair in $IA_PD_SERVICES ; do
action="$(echo "$pair" | cut -d':' -f2)"
daemon="$(echo "$pair" | cut -d':' -f1)"
# Check if a valid action was provided or default to 'restart'
case $action in
reload) action="reload";;
*) action="restart";;
esac
# Check if daemon is active before trying to restart or reload it (avoids non-zero exit code)
if ! systemctl -q is-active "${daemon}.service" > /dev/null ; then
logger -t "dhcpv6-pd" -p daemon.info "Info: $daemon is inactive. No $action required."
continue
fi
if systemctl -q "$action" "${daemon}.service" > /dev/null ; then
logger -t "dhcpv6-pd" -p daemon.info "Info: Performed $action of $daemon due to change of IPv6 prefix."
else
logger -t "dhcpv6-pd" -p daemon.err "Error: Failed to perform $action of $daemon after change of IPv6 prefix."
fi
done
elif [ "$IA_PD_DEBUG" = "yes" ]; then
logger -t "dhcpv6-pd" -p daemon.debug "Debug: No list of services to restart or reload defined."
fi
}
fn_remove_prefix() {
[ -z "$1" ] && return
[ "$IA_PD_DEBUG" = "yes" ] && logger -t "dhcpv6-pd" -p daemon.debug "Debug: Old prefix $1 expired."
if [ "$(ip -6 addr show dev "$IA_PD_IFACE" scope global | wc -l)" -gt 0 ]; then
logger -t "dhcpv6-pd" -p daemon.info "Info: Flushing global IPv6 addresses from interface $IA_PD_IFACE."
if ! ip -6 addr flush dev "$IA_PD_IFACE" scope global ; then
logger -t "dhcpv6-pd" -p daemon.err "Error: Failed to flush global IPv6 addresses from interface $IA_PD_IFACE."
return
fi
# Restart services in case there is no new prefix to assign
[ -z "$new_ip6_prefix" ] && fn_restart_services
elif [ "$IA_PD_DEBUG" = "yes" ]; then
logger -t "dhcpv6-pd" -p daemon.debug "Debug: No global IPv6 addresses assigned to interface $IA_PD_IFACE."
fi
}
fn_assign_prefix() {
[ -z "$1" ] && return
local new_ia_pd_addr
new_ia_pd_addr="$(fn_calc_ip6addr "$1")"
if [ -z "$new_ia_pd_addr" ]; then
logger -t "dhcpv6-pd" -p daemon.err "Error: Failed to calculate address for interface $IA_PD_IFACE and prefix $1"
return
fi
[ "$IA_PD_DEBUG" = "yes" ] && logger -t "dhcpv6-pd" -p daemon.debug "Debug: Received new prefix $1."
# dhclient may return an old_ip6_prefix even after a reboot, so manually check if the address is already assigned to the interface
if [ "$(ip -6 addr show dev "$IA_PD_IFACE" | grep -c "$new_ia_pd_addr")" -lt 1 ]; then
logger -t "dhcpv6-pd" -p daemon.info "Info: Adding new address $new_ia_pd_addr to interface $IA_PD_IFACE."
if ! ip -6 addr add "$new_ia_pd_addr" dev "$IA_PD_IFACE" ; then
logger -t "dhcpv6-pd" -p daemon.err "Error: Failed to add new address $new_ia_pd_addr to interface $IA_PD_IFACE."
return
fi
fn_restart_services
elif [ "$IA_PD_DEBUG" = "yes" ]; then
logger -t "dhcpv6-pd" -p daemon.debug "Debug: Address $new_ia_pd_addr already assigned to interface $IA_PD_IFACE."
fi
}
# Only execute on specific occasions
case $reason in
BOUND6|EXPIRE6|REBIND6|REBOOT6|RENEW6)
# Only execute if either an old or a new prefix is defined
if [ -n "$old_ip6_prefix" ] || [ -n "$new_ip6_prefix" ]; then
# Check if interface is defined and exits
if [ -z "$IA_PD_IFACE" ] || [ ! -e "/sys/class/net/${IA_PD_IFACE}" ]; then
logger -t "dhcpv6-pd" -p daemon.err "Error: Interface ${IA_PD_IFACE:-<undefined>} not found. Cannot assign delegated prefix!"
ls -al /sys/class/net/
else
# Remove old prefix if it differs from new prefix
[ -n "$old_ip6_prefix" ] && [ "$old_ip6_prefix" != "$new_ip6_prefix" ] && fn_remove_prefix "$old_ip6_prefix"
# Assign new prefix
[ -n "$new_ip6_prefix" ] && fn_assign_prefix "$new_ip6_prefix"
fi
fi
;;
esac
Don’t forget to change the few first configuration lines. My LAN network is “br0” because I use a bridge over multiple interfaces.
That script will get the DHCP-assigned range and add it to the LAN interface. We still need to enable RADVD to advertise the prefix on the lan:
sudo apt-get install radvd
sudo update-rc.d radvd enable
/etc/radvd.conf
interface br0 # LAN interface
{
AdvManagedFlag off; # no DHCPv6 server here.
AdvOtherConfigFlag off; # not even for options.
AdvSendAdvert on;
AdvDefaultPreference high;
AdvLinkMTU 1280;
prefix ::/64
{
AdvOnLink on;
AdvAutonomous on;
};
};
And that’s all. Note we don’t need wide-dhcp-client anymore, which anyway has a blocking bug and seems to be unmaintained. dhclient is able to do everything we need, given the script for prefix delegation.