Setup Ubuntu IPv4/IPv6 router for VLAN-tagged PPPoE internet connection

My ISP, XS4ALL, delivers IPv4/IPv6 over fiber via VLAN-tagged PPPoE. Normally, you would use the (excellent) WiFi-router they lend you, but if you want a little more control you can install your own computer as router. In this post I will explain how to do this with Ubuntu 15.04. Some steps are specific to my ISP, but most of it will also apply to any other provider using PPPoE.

Rename interfaces
The router should have at least two interfaces: one to connect to the fiber-modem and the other for the LAN. It is convenient to rename the interfaces. Create a file /etc/udev/rules.d/10-persistent-network-names.rules containing

SUBSYSTEM=="net", ACTION=="add", KERNEL=="em1", ATTRS{address}=="12:34:45:67:89:0a", NAME="modem"
SUBSYSTEM=="net", ACTION=="add", KERNEL=="eth0", ATTRS{address}=="12:34:45:67:89:0a", NAME="modem"
SUBSYSTEM=="net", ACTION=="add", ATTRS{address}=="0a:89:67:45:23:12", NAME="lan"

Replace the MAC addresses by the corresponding MAC addresses of your interfaces (you can find them using ifconfig | grep HWaddr) and em1 by the current name of the interface connected to the modem. Note that we have two rules for the modem interface: this is to prevent udev form renaming the VLAN interface. If you know a nicer way, please let me know. Reboot and test whether this worked.

Configure interfaces
Add the following to /etc/network/interfaces

auto modem
iface modem inet manual
    mtu 1508

auto modem.6
iface modem.6 inet manual
    vlan-raw-device modem
    mtu 1508

auto lan
iface lan inet static

auto wan
iface wan inet ppp
    pre-up /bin/ip link set modem.6 up
    provider xs4all

iface wan inet6 auto

The block for modem is only used to set its MTU to 1508. We need this if we want to set the MTU of the PPPoE connection to the normal 1500 (and compensate for the 8 bytes PPPoE uses). If you run into trouble, you can leave all MTU declarations out.

The block modem.6 configures an interface for packets on modem tagged with VLAN ID 6. XS4ALL uses VLAN tagging such that it can deliver different services (internet on 6, TV on 4, …) via the same modem.

The block lan sets up the interface for a LAN on 10.0.0.x.

Finally, the wan block tells the system to set-up a PPP-interface using the configuration named xs4all. We will set that up in a moment.

Set-up PPPoE
Install the package pppoe and create /etc/ppp/peers/xs4all with the contents

ifname wan
+ipv6 ipv6cp-use-ipaddr
connect /bin/true
mtu 1500
mru 1500
plugin modem.6
user ""

Also create /etc/ppp/chap-secrets with

"" * "somepassword"

My ISP requires the authentication step, but (intentionally) does not check the username and password — you can fill in anything you like.

Reboot. You should have IPv4 on the router. (The rest: DNS, IPv6, IPv4 on the LAN shouldn’t work.)

We’re ready to set up the LAN. We will use dnsmasq as it will act as (caching) DNS server, DHCP server and RA (IPv6’s alternative to DHCP) server. Install dnsmasq and write the following to /etc/dnsmasq.conf


In /etc/resolv.conf, put:


You might want to remove the package resolvconf as it might interfere. Now, in /etc/resolv.conf-dnsmasq, put the actual DNS server you would like to use. For Google’s public DNS, write:


We’re almost done with the IPv4 LAN. To /etc/sysctl.conf append


This will allow the kernel to forward packages between all interfaces. If you have more interfaces, you might want to restrict the forwarding to lan and wan, but to configure this requires running a script at the creation of the interfaces.

And finally, install iptables-persistent and write to /etc/iptables/rules.v4, the following for the IPv4 NAT:


Note that this will allow any connections from outside to the router on any port. Also, without configuration ip6tables, no connection is blocked form the outside. If you like a firewall (that is: whitelist which connections are allowed), you want to add some rules here.

Reboot. You should have IPv4 & DNS on the router and LAN.

My ISP assigns a /48 via DHCPv6. Install wide-dhcpv6-client. Change /etc/wide-dhcpv6/dhcp6c.conf to

profile default
  script "/etc/wide-dhcpv6/dhcp6c-script";

interface wan {
    send ia-pd 0;

id-assoc pd 0 {
   prefix-interface lan {
       sla-len 16;
       sla-id 0;
       ifid 1;

This will request a subnet and assign it to the lan interface. The IP of the router will be thesubnet::1 due to the ifid setting.

That’s it: reboot and enjoy your IPv4 & IPv6 connection.

8 thoughts on “Setup Ubuntu IPv4/IPv6 router for VLAN-tagged PPPoE internet connection”

  1. I’m not sure. At the moment my router is working fine with the MTU of both the physical interface (modem) and its derived VLAN interface (modem.6) set to 1508. Does it break for you?

  2. Hi – when we try this we get in syslog:

    pppd[1614]: Plugin loaded.
    ifup[1361]: Plugin loaded.
    pppd[1615]: pppd 2.4.7 started by root, uid 0
    ifup[1361]: Cannot find device “wan”
    ifup[1361]: Failed to bring up wan.
    pppd[1615]: Timeout waiting for PADO packets
    pppd[1615]: Unable to complete PPPoE Discovery
    pppd[1615]: Terminating on signal 15
    pppd[1615]: Exit.

    This is on ubuntu 16.x

    Isn’t pppd supposed to create an interface called “wan” as specified at the top line of /etc/ppp/peers/xs4all:

    ifname wan

    or “wan” is supposed to be already existing in the output of ifconfig -a or somewhere else defined?

    It’s hard to tell at the moment if the problem is with our config and with pppd finding a device to listen on, or whether the subsequent “Timeout waiting for PADO packets” represents something physical on the wire…

    Any pointers would be much appreciated!

  3. Hi Liam. The line plugin modem.6 should direct pppd to make the connection on the iface modem.6 and from it create a new interface called wan. Does exist?

  4. Hi Bas! Thanks for the great guide! This got me 90% of the way there. Ubuntu 18.04 throws a few curve balls (see below)

    I can verify this works w/ CenturyLink FTTH in Seattle. Specific notes specific to CenturyLink (hopefully helpful to others):

    a) CenturyLink does not (yet?) support IPv6, so I disabled those blocks and the wide-client

    b) I ran into “Timeout waiting for PADO packets” once I got everything almost working. Symptom, I would get about 10 seconds of connectivity, then that error. The issue was the MTU setting. I removed all the MTU statements in interfaces AND in /peers/your_client_name (I eventually added mtu/mru to 1492 just for completeness).

    c) I got a CHAP auth error (due to a type), then for some reason a SAP auth error (so I copied my credentials over there), and that seemed to resolve it. However, I’m certain my connection is using CHAP (never figured this out).

    d) FYI: vlan for centurylink is 201

    Specific notes for Ubuntu 18.04 (I’m using Ubuntu Server LTS):

    1) This setup requires ifupdown AND (I would recommend) removing netplan and disabling networkd management (Follow this:

    2) I did not end up renaming my interfaces. Ubuntu now a-days provides consistent naming. It’s not as readable, but I had udev issues…

    3) In interfaces file, “auto wan” with the pre-up line caused me trouble, with the interface coming up, but then for some reason udev was shutting it down just as it was getting going (causing a “term requested by signal 15” in the /var/log/syslog). This is apparently a known issue … for the last decade?! udev+interfaces have always been super confusing to me. So, I followed this advice: comment #14. My modifications to interfaces look like (adapted to be a diff from above):
    auto modem.6
    iface modem.6 inet manual
    vlan-raw-device modem
    # New:
    post-up ifup wan
    pre-down ifdown wan

    # Comment out or remove:
    # auto wan
    iface wan inet ppp
    # pre-up /bin/ip link set modem.201 up
    provider xs4all

    4) I added the loopback (lo) interface. For some reason it was missing in ifconfig after everything was said and done. Simply:
    auto lo
    iface lo inet loopback

    5) I have a router that sits behind this box, and is the only client of my dnsmasqd. As such, I added a DHCP reservation for that host so it basically has a static IP. Lets assume that address is (required for 6 to make sense)

    6) I added some NAT rules to forward all traffic destined for my public/WAN IP to be forwarded onto my router (IP is known in advance from (5). This requires knowing your WAN ip address… which only happens AFTER the pppoe connection succeeds. So, I added these lines to the end of /etc/ppp/ip-up (file already exists):
    WAN_IP=”`ifconfig wan | sed -n -e ‘s/.*inet \([0-9]\+.[0-9]\+.[0-9]\+.[0-9]\+\).*/\1/p’`”
    iptables -t nat -A PREROUTING -d $WAN_IP -p tcp -j DNAT –to-destination $DMZ_IP
    iptables -t nat -A POSTROUTING -s -d ${DMZ_IP}/32 -p tcp -j MASQUERADE

    7) Since this is a somewhat public facing machine, I would highly recommend installing unattended-upgrades

    I hope this helps the next person in some way or fashion!!!

  5. One last piece required to make my setup complete. Some sites/games do not work correctly. A example: works great! But does not. This turned out to be a MTU issue. All the clients by default assume mtu 1500. Since the pppoe is 1492, there are several mechanism to let all the LAN clients know to down-size to 1492. However _NONE_ of them are “enabled” by default. Read here for details:

    I went with the “7.15.2. Clamping the MSS via IPTABLES” approach. Very simply, edit your /etc/iptables/rules.v4 and update the main *filter section:

    :INPUT ACCEPT [1:373]
    :OUTPUT ACCEPT [0:0]
    # Add this line! Important
    -A FORWARD -p tcp -m tcp –tcp-flags SYN,RST SYN -j TCPMSS –clamp-mss-to-pmtu

  6. I’ve been nearly a year on this setup with rock solid performance! Only one minor addition/followup:
    – Every time my router renewed it’s DHCP lease to the dnsmasq-dns, it seemed to cause a multi-minute period of downtime. I fixed this by giving my router a static IP and that cleared up the issue. I also played with expiry, but nothing seemed to do the trick.

Leave a Reply

Your email address will not be published. Required fields are marked *