How to replace Singtel provided 2Wire router with Linux?
I grew to dislike non auto updating computing gear. As much as possible, I'd like to be able to update software running on my computer. I also like to be able to upgrade the software running my wireless router, on my phone, as well as the software running my public internet facing router.
My home internet connectivity is provided by Singtel, the national telco in Singapore. The package I have includes Fibre Broadband and mio TV. For that, I was provided with three hardware items: a fibre network terminal, a wireless router from 2Wire and the mio TV receiver itself. You can find pictures of a similar setup on the Sharing is caring blog. The fibre network terminal has several ethenet ports, but only one is used. This specific port on the network terminal must be connected to the 2Wire wireless router. The wireless router will then seggregate broadband network traffic (i.e. the internet) and mio TV traffic; it is pre-configured to allow broadband network traffic on one ethernet port, and mio TV traffic on another ethernet port. All of this is installed and tested by a Singtel technician on-site.
My goal was to get rid of the provided 2Wire wireless router, and to replace it with a Linux router; this for several reasons:
By default, the 2Wire is my de-facto internet facing router; it owns my public internet IP address. I want to be able to control TCP ports redirections easily. The 2Wire router allows for some configuration on a web interface, but that web interface is very slow and requires a reboot of the router for most simple configuration changes.
I own a wireless router that I prefer to the 2Wire. My existing router is faster (especially to whitelist new guests laptops), and can be upgraded easily.
The 2Wire software never is upgraded. I have no way to trigger any such update.
The 2Wire router provides only one single gigabit Ethernet port for the internet. I have an handful of wired connections, so I would need to keep my existing wireless router to act as a gigabit switch anyway.
Ethernet tagging
To provide both for the internet broadband traffic and the mio TV traffic, Singtel has chosen to "tag" the Ethernet traffic going from the 2Wire wireless router to the fibre via the fibre network terminal that acts as a bridge and connection identifier. Ethernet tagging follows the IEEE 802.1Q networking standard: ethernet frames corresponding to internet broadband traffic are flagged vlan ID 10, and ethernet frames corresponding to mio TV traffic are flagged vlan ID 20. In the default Singtel setup, the ethernet tagging is done by the 2Wire wireless router: ethernet traffic on the mio TV ethernet port is routed to vlan 20, and ethernet traffic on the broadband ethernet port is routed to vlan 10. That is all very simple.
Linux comes with support for the IEEE 802.1Q networking standard. I used Arch Linux, the configuration I described is targetted for that specific distribution.
I chose to rename my network interfaces as described on Arch Linux wiki
# cat /etc/udev/rules.d/10-network.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="[REDATED MAC]", NAME="singtel"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="[REDATED MAC]", NAME="lan"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="[REDATED MAC]", NAME="miolan"
The singtel network interface is connected to the fibre network terminal. The lan network interface is my internal LAN connecting various computers and a wireless router. The miolan network interface is connected to the mio TV receiver.
I then can configure my Linux network.
# cat /etc/network.d/broadband
INTERFACE="singtel.10"
VLAN_PHYS_DEV="singtel"
VLAN_ID="10"
CONNECTION="vlan"
IP="dhcp"
We told Arch Linux to configure a virtual network interface with the name singtel.10 that contains the singtel network interface traffic that belongs to vlan ID 10.
# systemctl enable netcfg@broadband
# systemctl start netcfg@broadband
We should now have internet traffic and a public IP address on the interface singtel.10. That was the very easy part.
Ethernet priority
Back to the IEEE 802.1Q networking standard. The 802.1Q Header contains 32-bit of information. We saw how to add a VLAN id to the ethernet packets we send, and to extract the packets marked to a specific VLAN id. Now we would like to modify another field of the 802.1Q Header: the priority code point (PCP). The content of the field is defined as part of IEEE 802.1p.
Singtel has chosen to have an additional configuration twist for mio TV traffic: it must be flagged with the ethernet priority 4 (acronym VI for video). That specific ethernet header modification is difficult to do on anything but Linux.
# cat /etc/network.d/miotv
INTERFACE="singtel.20"
VLAN_PHYS_DEV="singtel"
VLAN_ID="20"
DESCRIPTION="mioTV vlan"
CONNECTION="vlan"
IP="static"
IPCFG=("link set dev singtel.20 type vlan egress-qos-map 0:4 1:4 2:4 3:4 5:4 6:4 7:4")
# systemctl enable netcfg@miotv
# systemctl start netcfg@miotv
The IPCFG configuration line tells Linux to rewrite all outgoing ethernet packets with the QoS priority set to value 4.
This interface will be used as part of a bridge, so it does not need any IP address.
Masquerading
Now that we have the Singtel facing interfaces in place, we can start to build our internal network. In my setup, I have a lan interface for my local computer network that is masqueraded by iptables to the singtel.10 broadband interface.
# cat /etc/network.d/lan
CONNECTION='ethernet'
DESCRIPTION='My private intranet'
INTERFACE='lan'
IP='static'
ADDR='192.168.100.1'
NETMASK='255.255.255.0'
BROADCAST='192.168.100.255'
DNS=('127.0.0.1')
# systemctl enable netcfg@lan
# systemctl start netcfg@lan
The minimal iptables setup would be something like:
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i lan -j ACCEPT
# iptables -A FORWARD -j REJECT --reject-with icmp-host-unreachable
# iptables -P FORWARD DROP
# iptables -A POSTROUTING -s 192.168.100.0/24 -o singtel.10 -j MASQUERADE
# sysctl -w net.ipv4.ip_forward=1
# sysctl -w net.ipv6.conf.all.forwarding=1
The sysctl flags should be persisted in the file /etc/sysctl.conf.
The setup isn't fully complete. You'd need to configure a DHCP server to provide an IP address in the 192.168.100.* network to local computers and set the route to our gateway 192.168.100.1. You may also need to run a DNS server, or just forward to your internet provider DNS servers.
Bridging
The mio TV receiver will setup its connection automatically. The
Linux router needs to act as a simple network switch between the
internal interface miolan and the external interface singtel.20.
# cat /etc/network.d/miolan
INTERFACE="miolan"
CONNECTION="ethernet"
IP="static"
DESCRIPTION='mioTV LAN'
# cat /etc/network.d/miobridge
INTERFACE="miobridge"
CONNECTION="bridge"
DESCRIPTION="Bridge"
BRIDGE_INTERFACES="singtel.20 miolan"
IP="static"
ADDR="192.168.1.254"
# systemctl enable netcfg@miolan
# systemctl enable netcfg@miobridge
# systemctl start netcfg@miolan
# systemctl start netcfg@miobridge
# iptables -I FORWARD 1 -i miotv -j ACCEPT
# sysctl -w net.bridge.bridge-nf-call-ip6tables=0
# sysctl -w net.bridge.bridge-nf-call-iptables=0
I am setting an IP address on the bridge itself 192.168.1.254. I did not test if that is strictly required, the mio TV receiver will set its IP address to 192.168.1.1 immediately after boot and ping 192.168.1.254.
The sysctl flags are required to avoid setting up rules for the bridge with iptables. Beware: persisting these flags in /etc/sysctl.conf does not work; you will need manually to setup a script to disable them after boot.
My mio TV is able to acquire an IP address on its own. The Singtel
DHCP server in VLAN 20 will only answer to requests that are marqued
with a QoS priority of 4. I also had to take special care of the mio TV
traffic when hardening my firewall with rules on the INPUT chain in iptables.
The configuration allowed me to get rid of the 2Wire wireless router. It certainly is somewhat sophisticated, but it allows a good level of control on my home network setup, which is the goal I had set for this project.