CentryLink Fiber PPPoE on Linux Router
This post is part of a series of posts about building your own Linux home router using systemd-networkd. The posts are organized as follows:
- Connecting to CenturyLink using PPPoE and systemd-networkd
- Network Architecture and VLAN configuration
- Firewalld policy-based access control between zones
This guide assumes you have a working knowledge of Linux, networking and routing concepts. This guide is built on Arch, but should be roughly translatable to other Linux distributions which have Systemd Networkd, Firewalld and pppd packaged at a relatively recent version.
In this post, we’ll cover how to get connected to CenturyLink Fiber (my ISP) using PPPoE to authenticate.
After the usual pain and chaos of the required scheduling of a contractor to come setup the cables, I was left with the must-rent all-in-one routerbox (which for the curious is a Zyxel EX3510-B0, which will go unused) and a good connection. I measured using the CenturyLink provided box and verified I was achieving near-line rate throughput for the gigabit fiber (a little over 900Mbps). But that wasn’t before I hit some issues with speedtesting websites on firefox, so I simply used
iperf because CLIs never let me down.
Finally I can install my new router! For the hardware, I used the same box as my former OpenBSD router for the Linux one, namely a Zotac ZBOX Nano which is small, has dual gigabit ports, and is passively cooled. The very first step to get connected is to figure out PPPoE which I haven’t used before.
For bring-your-own-router setups, CenturyLink requires the PPPoE username and password (which can be lifted from the provided router’s web config). It also requires authenticating that connection over VLAN 201 on the external/WAN interface, so we’ll start with that.
To setup a persistent VLAN using systemd-networkd (included with systemd on Arch, YMMV on other distributions), do the following:
First, enable the systemd-networkd unit:
systemctl enable systemd-networkd. Identify your WAN port (
enp2s0 in my setup, and hereafter referred to as that). Create a
.network file under
/etc/systemd/network for that interface, indicating the presence of a child-VLAN (e.g.
[Match] Name=enp2s0 [Network] VLAN=enp2s0.201
.netdev files for the child VLAN interface:
$ cat /etc/systemd/network/enp2s0.201.network [Match] Name=enp2s0 $ cat /etc/systemd/network/enp2s0.201.netdev [NetDev] Name=enp2s0.201 Kind=vlan [VLAN] Id=201
networkctl reload and you should see the corresponding interface created after a few moments (it’s not immediate/synchronous with the reload):
$ ip link ... stuff ... 9: enp2s0.201@enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 00:01:ef:78:fu:68 brd ff:ff:ff:ff:ff:ff
ppp package to get the utilities for configuring the point-to-point connection. Create the following file, replacing the interface with the one created from the above configuration, and the fake username with your username.
cat >/etc/ppp/peers/centurylink<<EOF plugin pppoe.so # network interface to use enp2s0.201 # login name name "[email protected]" # usepeerdns persist defaultroute hide-password noauth EOF
Then, add your user credentials to the
pap-secrets file. I lifted my own credentials from the non-optional SOHO router that came with the service by inspecting the HTML in the browser console 🏴☠️, but you can probably also call CenturyLink and spend hours on hold to get them too.
cat >/etc/ppp/pap-secrets<<EOF # Secrets for authentication using PAP # client server secret IP addresses [email protected] * password EOF
Finally, you can test the connection using possibly one of the silliest sounding commands named
$ pon centurylink $ ping 1.1 PING 1.1 (220.127.116.11) 56(84) bytes of data. 64 bytes from 18.104.22.168: icmp_seq=1 ttl=59 time=3.50 ms 64 bytes from 22.214.171.124: icmp_seq=2 ttl=59 time=3.30 ms
TADA! 🎉 That’s it! You can make the ppp connection start automatically at boot via:
$ systemctl enable ppp@centurylink Created symlink /etc/systemd/system/multi-user.target.wants/[email protected] → /usr/lib/systemd/system/[email protected].
⚠️ Updated Note (2022-06-09) ⚠️
I forgot to mention that I had to apply this little pmtu clamping hack on the interface to get good throughput. Without it, your connection may slow unexpectedly and some sites may just be totally unavailable.
iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu # test that rule on a site which has trouble, then save permanently (on Arch) with: iptables-save -f /etc/iptables/iptables.rules # Applies iptables rules automatically at boot systemctl enable iptables
Or using firewalld, assuming you have a policy called internet-access (more on this in the post on firewalld):
firewall-cmd --add-rich-rule='rule tcp-mss-clamp value=pmtu' --policy=internet-access
Don’t be like me and mix the two above commands, as you shouldn’t be mixing use of iptables and nftables apparently. 😂 I haven’t yet found proof of what goes wrong when you do mix them, but it would certainly be painful when debugging anyway.
Not too shabby
Overall, I’m quite pleased with Centurylink thus far. Speeds are fairly decent, wasn’t too much trouble to BYOR (bring your own router), and reasonably priced!
Also, I’m very pleased with systemd-networkd as the network supervisor daemon! It has clear and concise configuration, great documentation, and easy for people familiar with networking to learn quite quickly. I highly recommend considering using it for projects of your own.
Learn more about how I’ve configured systemd-networkd in the next post, and how it integrates with firewalld in the post following that!