In my ongoing adventures of playing with the Chromebox as a firewall, I eventually found a reason to use stock Ubuntu 16.04 instead of VyOS.
For the most part, devices just work as you’d expect under Ubuntu. Even my USB ethernet network interface (NIC) devices work fine. But I eventually noticed a problem.
By default USB NICs under Ubuntu 16.04 (which uses systemd & udev) are named “enxABCDEF123456” where ABCDEF123456 is the full MAC address of the device.
This is fine for basic usage, but problems occur when you want to use device aliasing or VLAN tagging.
As an example, a standard USB interface definition would look like this in /etc/network/interfaces:
iface enxABCDEF123456 inet static address 192.168.1.20 netmask 255.255.255.0
Linux interface aliasing lets you add another IP to the same device like by adding another entry with a colon plus integer (eg, :1 or :10). The aliased device can be treated as a unique device for ifup/ifdown, etc. It looks like this:
iface enxABCDEF123456:1 inet static address 192.168.1.35 netmask 255.255.255.0
You can add VLAN tagging to an interface very simply in a similar way. It’s done by adding a dot/period plus integer (eg, :100 or :201) and referencing the parent “raw” device. The aliased device can be treated as a unique device for ifup/ifdown, etc. It looks like this:
iface enxABCDEF123456.201 inet static vlan-raw-device enxABCDEF123456 address 192.168.2.20 netmask 255.255.255.0
Looks good, right? Nope! Guess what, this isn’t going to work as is!
If you actually try to bring up one of these devices, you’ll see this.
$ sudo ifup enxABCDEF123456.201 RTNETLINK answers: Numerical result out of range Failed to bring up enxABCDEF123456.201.
Turns out this is due to the (very long) length of the device name. Actually, someone already filed a bug for this with Ubuntu: https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1567744
So, what to do? There’s a reasonably simple solution, but it took some searching to figure it out.
First, if you just read docs about systemd you’ll see a seemingly “obvious” way to name devices by mapping the MAC address. This creates a file which should rename the device enxABCDEF123456 to enx0.
cat > /etc/systemd/network/10-enx0.link << EOF [Match] MACAddress=AB:CD:EF:12:34:56 [Link] Name=enx0 EOF
It seems good, but doesn’t work by itself.. the trick is that udev is also at work tweaking the NIC device names.
Per the systemd man page: https://www.freedesktop.org/software/systemd/man/systemd.link.html
All link files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority, files in /run take precedence over files with the same name in /usr/lib. This can be used to override a system-supplied link file with a local file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to /dev/null disables the configuration file entirely (it is “masked”).
This gave me the idea that masked files may also be at play with udev…. the file which directs udev to name USB devices with full MAC address is /lib/udev/rules.d/73-usb-net-by-mac.rules so I’ll attempt to mask it in in /etc.
ln -s /dev/null /etc/udev/rules.d/73-usb-net-by-mac.rules update-initramfs -u reboot
Note that udev and systemd rules, need to be in the initfamfs, so that has to be updated before rebooting for the changes to take effect.
Oh, of course, now if I was depending on that USB NIC, I just lost networking because my /etc/network/interfaces is invalid. So based on the examples above, here’s a snapshot of what the that file should now look like:
iface enx0 inet static address 192.168.1.20 netmask 255.255.255.0 iface enx0:1 inet static address 192.168.1.35 netmask 255.255.255.0 iface enx0.201 inet static vlan-raw-device enx0 address 192.168.2.20 netmask 255.255.255.0
Now, the base USB interface, the alias interface, and the VLAN interface should all work!