Published on

CentryLink Fiber PPPoE on Linux Router

Authors

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:

  1. Connecting to CenturyLink using PPPoE and systemd-networkd
  2. Network Architecture and VLAN configuration
  3. 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.

Fiber Installation

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.

VLAN Configuration

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. enp2s0.network).

[Match]
Name=enp2s0

[Network]
VLAN=enp2s0.201 

Create corresponding .network and .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

Now run 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 Connection

Install the 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
myusername1234@centurylink.net  *  password
EOF

Finally, you can test the connection using possibly one of the silliest sounding commands named pon.

$ pon centurylink
$ ping 1.1
PING 1.1 (1.0.0.1) 56(84) bytes of data.
64 bytes from 1.0.0.1: icmp_seq=1 ttl=59 time=3.50 ms
64 bytes from 1.0.0.1: 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/ppp@centurylink.service/usr/lib/systemd/system/ppp@.service.

⚠️ 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!