Ubiquity EdgeRouter X and IPv6 Support


EdgeRouter X and IPv6

The year is 2020, IPv6 has been a standard for over 22 years. And amazingly enough, there are still networking products which aimed solidly at the IPv4 customer, such Ubiquity.

I bought the Ubiquity EdgeRouter X, thinking it would be a nice addition to my IPv6 Test network. Basically it is a five (5) port GigE router (with eth0-eth4). It had a wonderful specifications list, supporting many features I recognized, and some I even planned on using, like RIPng.

Basic Specs of the EdgerRouter X

The Ubiquity Spec sheet is impressive, including five GigE ports, and a 4 core MIPS CPU with 256 MB of RAM. Here’s some of the following of what the EdgeRouter X supports right out of the box.

Feature Protocol
Interface/Encapsulation 802.1q VLAN
IP in IP
Routing Static Routes
BGP (with IPv6 Support)
Services DHCP/DHCPv6 Server
Dynamic DNS
DNS Forwarding
Web Caching
PPPoE Server
Management Web UI
CLI (SSH, Telnet)

Lots of protocols to keep an old Bay Networks person, like myself, busy for some time.

EdgeRouter X and IPv6 Support

The EdgeRouter X is the bottom of the product line for Ubiquity. After all, it only costs $60 USD on Amazon. And it does have impressive IPv6 support. But the catch is that one must use the CLI to configure IPv6. The web interface is nearly totally devoid of IPv6 configuration and operational status.

Having worked in product development, including software development, and CLI design, I can see many of the challenges the designers had with creating a cohesive interface. For example, do you add a router protocol (such as RIPng or OSPFv3) to a port, or do you add ports to the routing protocol? Ubiquity decided to split the difference, and add some config to the ports and other parts of the config to the routing protocol.

Little IPv6 seen in the GUI

Unfortunately, the Web Interface is lacking in IPv6 support. For example, here is the Routing tab. And this router has RIPng running (configured via CLI) with plenty of IPv6 routes.

All routes GUI

To be fair to the Web GUI, there is a Configuration Tree in the GUI, that basically maps the CLI into a tree, where IPv6 protocols can be configured:

Config Tree GUI


Although the CLI looks like it will support DHCPv6-PD, I was unable to find success attempting to configure a /60. I repeatedly got an unhelpful error “64 + 4 + 64 prefix too long” (which of course exceeds 128 bits of IPv6).

OpenWrt to the rescue

Although the dazzling list of supported protocols was enough for me to purchase the EdgeRouter X, the really nice part, is that the little capable router is also supported by OpenWrt, which does have excellent IPv6 support.

Typically the steps to upgrade a OpenWrt supported router is:

  1. Download the “factory” install image from the OpenWrt website to your laptop
  2. Log into the router, and find the software upgrade section (different for every router manufacturer)
  3. Upload/Upgrade the router with the OpenWrt software
  4. Log into the router, and enjoy OpenWrt

Upgrading the EdgeRouter X to OpenWrt was not quite as simple as other routers. Unfortunately Step 3 fails. The EdgeOS upgrade screen will not accept the latest OpenWrt “factory” install image.

Upgrade Image failed

Fortunately, the open source community has not only created steps, but an OpenWrt image which will be accepted by EdgeOS.

The Steps to upgrade the EdgeRouter X becomes:

  1. Download the interim tar file image from open source community to your laptop.
  2. Log into the router, and find the software upgrade section (Under System->Upgrade System Image)
  3. Upload/Upgrade the router with the interim OpenWrt software

Half way there

The router will reboot, and have a default address of with no password (the default for OpenWrt), and no GUI. There is also a default ULA address, if you only have IPv6. The router will send an RA with a ULA* prefix, such as fd45:1373:e6bd::/48 The router will have the ::1 address. In my example, router address was fd45:1373:e6bd::1, which you can ssh to.

But that only gets a minimal OpenWrt snapshot running on the EdgeRouter X. In order to finish the upgrade, one has to download the v19.07 Upgrade image from OpenWrt to your laptop, then connect to one of the ethernet LAN ports (eth1-4), and scp it over to the router’s /tmp directory.

scp openwrt-19.07.2-ramips-mt7621-ubnt-erx-squashfs-sysupgrade.bin 'root@[fd45:1373:e6bd::1]/tmp/'

Log into the router via ssh using the IPv4 or IPv6 default address.

ssh root@fd45:1373:e6bd::1  #use your own ULA prefix here
cd /tmp
sysupgrade openwrt-19.07.2-ramips-mt7621-ubnt-erx-squashfs-sysupgrade.bin

As part of the sysupgrade, the ssh session will disconnect, and the router will reboot.

Log into the OpenWrt Web GUI

After the reboot, you should be able to log into the OpenWrt Web Interface. In my case, I put the IPv6 ULA into the location bar in the browser (yes, the square brackets are required for a raw IPv6 address).


And you will see that OpenWrt reports that the hardware is a UBNT-ERX (short for Ubiquity EdgeRouter X)

Config Tree GUI

Tthe first port of the router is the WAN port (eth0), and if connected to an upstream Dual-Stack network, you will see that the EdgeRouter X has picked up an IPv6 GUA, and automatically requested DHCPv6-PD, and allocated a /64 to the downstream LAN ports (four right-hand ports eth1-4).


The EdgeRouter X has NAT forwarding hardware acceleration. This is an IPv4-only feature, but certainly useful in Dual-Stack networks. Using OpenWrt and HW NAT Acceleration enabled, it has been measured to have a blazing forwarding capacity of 846 Mbit/sec average, faster than the original Ubiquity software.

The software-only throughput is a respectable 643 Mbit/sec with all four cores pulling hard.

If you have a high speed Internet connection, this little high performance router is for you.


OpenWrt has excellent IPv6 support in its Web GUI, with reasonable defaults for obtaining an IPv6 address, delegating a Prefix, and IPv6 firewall rules.

The EdgeRouter X is a high performance home router for a low price. And fortunately, there is a choice to have excellent IPv6 support via OpenWrt.

* ULA (IPv6 Unique Local Addresses) begins with ‘FD’ followed by randomized 40 bits. OpenWrt follows RFC 4193 and automatically creates a ULA at install time.


Article originally appeared on Makiki.ca

Jitsi: The IPv6 friendly Video Conferencing Tool


Jitsi: IPv6 Enabled

In these times of Social Distancing, or more correctly physical distancing, the use of Video Conferencing has taken a big upturn. Unfortunately most of the commonly known solutions are still stuck in the past century by only supporting IPv4. Some apps like Zoom, don’t even work on an IPv6-only network.

But fortunately, there is a nice IPv6 enabled alternative called Jitsi. Some of the advantages are:

  • Service is free with no time limit (unlike Zoom)
  • No software download required, runs in a browser like Chrome/Chromium without plugins
  • iOS & Android apps are available
  • No login/account is required
  • Works on IPv6 & IPv4
  • Encrypted Streams using DTLS-SRTP
  • Dial-in number available (NOT toll-free)
  • Runs on Open Source Software (install on your own server if you like)

Jitsi also works quite well on an IPv6-only network, when using NAT64 to talk to an IPv4-only peer.

Meeting on Jitsi
Jitsi Meeting in Tile-mode *

IPv6 Done Right

This is the way all applications should operate. The use of IPv6 or IPv4 is transparent to the users. If one user is on IPv4-only, then a peer-to-peer conversation will happen over IPv4.

Jitsi is also NAT64-friendly, still working when one peer is IPv4-only and the other IPv6-only. Unlike Zoom, which breaks NAT64 with hidden IPv4 addresses hardcoded built into the application.


The video streams are encrypted using DTLS-SRTP. Jitsi operates in peer-to-peer mode when there are only two participants and automatically switches to using the Video Bridge when there are more than two.

In peer-to-peer, the entire video/audio stream is end-to-end encrypted. When using more than two, the streams are encrypted to the video bridge, decrypted and mixed, and then sent out encrypted (again) to the individual participants. And a new feature is in the works to use end-to-end encryption, even when going through the video bridge.

And unlike Zoom, Jitsi does not collect your personal data, or suffer the many other security issues of Zoom.

Securing the Video Conference

Of course, it is also possible to password protect the conference.

The Moderator (generally the person who starts the Conference) also has options to mute all, and even kick out unwanted participants.

participant action menu

Good Geeky Stats

And if you are interested in Statistics on how each participant is doing, there’s a handy cell-phone-strength meter in the upper left corner of each persons video window.

Geeky Stats

The information includes simple colour coding (green = good, red = bad), but also the bandwidth each peer is using, and frame loss. Pretty cool stuff.

Go Forth and Video Conference over IPv6

Jitsi is a full featured Video Conferencing Tool which has excellent support for IPv6 (and IPv4). Go forth and Video Conference using the free, IPv6-enabled, with no time limits, solution.


* Video Conferencing Photo and dialogues: from Jitsi Blog

*  Originally appeared  on www.makiki.ca

IPv6 Adoption: Over a Billion Users


Google IPv6 Stats

Like many of us IPv6 advocates, I regularly visit Google IPv6 Statistics Page. Some have noted that over time, the increase of IPv6 users have tapered off, and others have predicted that IPv6 usage will not increase beyond 30%.

One can attempt to infer much from Google’s statistics, not always correctly. When I look at the graph, I see a little bump around the Christmas Holiday period. I’d like to think that is because people are at home more (taking time off the during holidays), and using their home IPv6-enabled connection, rather than their work/enterprise-ipv4-only connection to access Google. But even if my reason for the bump is wrong, it is clearly there, and one can see it for each of the years going back as far as 2013.

Size of the Internet is still growing

But just looking at Google’s stats doesn’t tell the entire story. It doesn’t show how the internet is continuing to grow. Another statistics site, Statistica.com, estimates the number of world wide users, where it can be seen that the size of the internet continues to increase.

Global Internet Users

Looking at the graph above, one can see a rather linear growth to the number of internet users in the world.

What is 30% of 4 Billion?

Because IPv4 Address space is limited to 4 bilion (2^32=4 billion), the growth in the internet will have to use IPv6 address space.

So what does the growth of IPv6 enabled users look like? What if we combine the data, looking at the Google Data for % of IPv6 Users, with number of Internet users.

Is IPv6 running out of steam (reaching an asymptotic line), or does it continue to grow?

Year G-Data in % Millions of Internet Users % Ipv6 Users
2019 30.48 4150* 1264.92
2018 26.75 3896 1042.18
2017 22.27 3650 812.855
2016 16.79 3417 573.7143

Number of IPv6 Users

As you can see from my simple graphing abilities (thanks to LibreOffice) that although the Google data appears to show the rate of IPv6 adoption is decreasing, the combined data shows that the number of people using IPv6 in the last 4 years have doubled!

IPv6 Users exceed the entire 2007 Internet

As John Curran, CEO of ARIN, said back in 2017, IPv6 will not take over overnight, in fact, there will be a “long tail” of IPv4 usage. But as you can see from the combined data, the millions of IPv6 users continues to grow, as the Internet grows. In fact, the number of IPv6-enabled users today exceeds the entire Internet population in 2007.

IPv4-only means slower delivery of data/services

If you are IPv4-only today, you will have to rely on someone else’s translation mechanism (NAT64/DNS64, XLAT464, etc) for those millions of IPv6-enabled users to reach your website. Translations services you have no control over. This means it will take longer for your pages to load, when compared to your IPv6-enabled competitors. Google, Amazon, and CDNs have shown that longer load time translates directly to reduced revenue (how long will your customers wait for your page to load?).

IPv6 is the future, it is 2020, the future is now

It is 2020, the beginning of the IPv6 decade. It is not too late. But it is time to get connected to the IPv6 Internet and reach those 1.2 Billion users out there who are already using IPv6 today!


Originally published on www.makiki.ca

IPv6 Christmas Tree

Christmas has come and gone, but the Christmas tree in the corner still has a few days left before we take it down.

On the IPv6 Internet (the “other” internet that the IPv4-only folks can’t see) there is an IPv6 Christmas Tree that can be decorated with your IPv6 pings.

By assigning 16 million IPv6 addresses to a single Christmas Tree, one can adjust the colours of the lights on the tree. According to the website:

2a05:9b81:2020::AA:BB:CC for HTML Color #AABBCC

There are many resources to convert colours to hex, but to light the lights red, one would ping:

ping -6 2a05:9b81:2020::FF:00:00

Because the tree doesn’t really have 16 million addresses assigned to the IPv6 stack, it will not reply, but you can watch a video of the tree and see the results of your pings.

So enjoy the last few days of 2019, and light the IPv6 Christmas Tree in your favourite colour.

Using IPv6 Link-Local to rescue your embedded device


IPv6 to the Rescue

Your embedded device has been running great for the past few weeks, and now all the sudden, it can’t be found on the network. You can’t ssh into see what the problem is, it has just disappeared.

Lots of reasons why this may have happened, perhaps the program hit a bug and crashed, or more likely, it has forgotten its IPv4 address. Sure you can just “turn it off and on again” and that may fix the problem, or it could make it worse, if it was writing out to the SD Card at the time you pulled power.

The real answer is to log in and find out what is really going on, but as I said, for some reason your Pi, router, or device isn’t responding. So what do you do?

IPv6 to the Rescue

But if you setup your network as a dual-stack network, then your device already has not only an IPv4 address, but also an IPv6 address as well. And if you put the IPv6 address into your local DNS, then you can just ssh to the hostname, and see what is going on with your device.

But what if you do have a dual-stack network (your ISP is providing IPv6) but you haven’t really done anything with IPv6. How can you use it to rescue your device?

ssh to the IPv6 address of the device, and Bob’s your uncle.

Finding the IPv6 Address of your device

Unlike IPv4 network scanners, scanning IPv6 networks is much more challenging. After all, instead of looking at 254 addresses, you are now looking to scan 18,446,744,073,709,551,616 or 18 quintillion addresses. Assuming that you use the fastest scanner zmap which claims to be able to scan the entire IPv4 internet (all 4 billion addresses) in 45 minutes. With 18 quintillion possible addresses, it is still going to take 367,719 years! (2^32 *45 min / 60 min/ 24 hours/ 365 days). And zmap doesn’t support IPv6 (and you can see why)

Fortunately, there are non-brute-force solutions to the problem.

IPv6 Basics, the all-nodes address

Although there is no broadcast in IPv6, there is a specific multicast address that all nodes must listen to. This is called the all-nodes address, or ff02::1. It is possible to send a ping to the all-nodes address, and get multiple responses back, similar to pinging the IPv4 broadcast address will (used to) return multiple responses.

$ ping6 -c 2 -I wlan0 ff02::1
PING ff02::1(ff02::1) from fe80::f203:8cff:fe3f:f041%wlan0 wlan0: 56 data bytes
64 bytes from fe80::f203:8cff:fe3f:f041%wlan0: icmp_seq=1 ttl=64 time=0.140 ms
64 bytes from fe80::2ac6:8eff:fe16:19d7%wlan0: icmp_seq=1 ttl=64 time=7.32 ms (DUP!)
64 bytes from fe80::21e:6ff:fe33:e990%wlan0: icmp_seq=1 ttl=64 time=7.66 ms (DUP!)
64 bytes from fe80::216:3eff:fea2:94e8%wlan0: icmp_seq=1 ttl=64 time=8.67 ms (DUP!)
64 bytes from fe80::ba27:ebff:fe89:bc51%wlan0: icmp_seq=1 ttl=64 time=9.60 ms (DUP!)
64 bytes from fe80::4aa2:12ff:fec2:16df%wlan0: icmp_seq=1 ttl=64 time=9.73 ms (DUP!)
64 bytes from fe80::216:3eff:feff:2f9d%wlan0: icmp_seq=1 ttl=64 time=10.6 ms (DUP!)
64 bytes from fe80::f203:8cff:fe3f:f041%wlan0: icmp_seq=2 ttl=64 time=0.686 ms

--- ff02::1 ping statistics ---
2 packets transmitted, 2 received, +6 duplicates, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.140/6.814/10.696/3.840 ms

In IPv6, multicast addresses are associated with multiple interfaces (there is an all-nodes address on each interface), therefore it is necessary to specify an interface -I to ping.

OK, but how to we find the IPv6 address in my dual-stack network?

Using an open source utility, v6disc.sh, which uses the all-nodes technique discovers the nodes on your IPv6 network in a matter of seconds, rather than years.

$ ./v6disc.sh 
WARN: avahi utis not found, skipping mDNS check 
-- Searching for interface(s) 
-- Found interface(s):  eth0 
-- INT:eth0 prefixs: 2001:470:db8:101 
-- Detecting hosts on eth0 link 

-- Discovered hosts for prefix: 2001:470:db8:101 on eth0 
2001:470:db8:101::1                      00:24:a5:f1:07:ca    Buffalo
2001:470:db8:101:203:93ff:fe67:4362      00:03:93:67:43:62    Apple
2001:470:db8:101:211:24ff:fece:f1a       00:11:24:ce:0f:1a    Apple
2001:470:db8:101:211:24ff:fee1:dbc8      00:11:24:e1:db:c8    Apple
2001:470:db8:101:226:bbff:fe1e:7e15      00:26:bb:1e:7e:15    Apple
2001:470:db8:101::303                    d4:9a:20:01:e0:a4    Apple
2001:470:db8:101:3e2a:f4ff:fe37:dac4     3c:2a:f4:37:da:c4    BrotherI
2001:470:db8:101:6a1:51ff:fea0:9339      04:a1:51:a0:93:38    Netgear
2001:470:db8:101:b41f:18a3:a97c:4a0c     10:9a:dd:54:b6:34    Apple
2001:470:db8:101::9c5                    b8:27:eb:89:bc:51    Raspberr

The utility looks up the Ethernet MAC address manufacturer and prints it in the third column.

As you can see it is easy to spot the Raspberry Pi on this network.

But wait, I don’t have a dual-stack network, now what?

So you have Shaw for an ISP, and they can’t spell IPv6, now what? Another IPv6 fact is that every device which has an IPv6 stack, must have a link-local address. The link-local address is used for all sorts of things, including Neighbour Discovery Protocol (NDP), the IPv6 equivalent of ARP. Therefore, even if your network doesn’t have an IPv6 connection to the internet, your IPv6-enabled device will have a link-local address.

Fortunately, v6disc.sh also can detect link-local addresses as fast as it detects IPv6 global addresses (in mere seconds).

$ ./v6disc.sh -i wlan0 -L
WARN: avahi utis not found, skipping mDNS check 
-- INT:wlan0    prefixs:  
-- Detecting hosts on wlan0 link 
-- Discovered hosts for prefix: fe80: on wlan0 
fe80::216:3eff:fea2:94e8                 00:16:3e:a2:94:e8    Xensourc
fe80::216:3eff:feff:2f9d                 00:16:3e:ff:2f:9d    Xensourc
fe80::21e:6ff:fe33:e990                  00:1e:06:33:e9:90    Wibrain
fe80::2ac6:8eff:fe16:19d7                28:c6:8e:16:19:d7    Netgear
fe80::4aa2:12ff:fec2:16df                48:a2:12:c2:16:df    
fe80::ba27:ebff:fe89:bc51                b8:27:eb:89:bc:51    Raspberr
fe80::f203:8cff:fe3f:f041                f0:03:8c:3f:f0:41    Azurewav
-- Pau 

Link-local addresses are not globally unique, and therefore an interface must be specified with the -i, and the -L tells v6disc.sh to only detect link-local addresses.

Again, as you can see, it is easy to pick out the Raspberry Pi link-local address on this network.

Now I have the IPv6 address, how do I use it?

With the Global or link-local IPv6 address, all one need to do it ssh into the lost device and find out what is going on.

If using the link-local address, the interface must also be specified with the %intf notation (e.g. <link-local_addr>%wlan0) :

$ ssh cvmiller@fe80::ba27:ebff:fe79:bc51%wlan0
cvmiller@fe80::ba27:ebff:fe79:bc51%wlan0's password: 
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1030-raspi2 armv7l)

Last login: Mon Sep 30 19:57:11 2019 from fe80::2ac6:8eff:fe16:19d7%br0

Log in and fix it

And now you are logged into your wayward device, and you can troubleshoot to figure out what went wrong.

IPv6 Summer Fun


IPv6 Fun

Everyone knows (by now) that IPv6 is an 128 bit address. And most know that the least significant 64 bits is the Interface ID (IID). That is 2^64 or 18,446,744,073,709,551,616 hosts per /64 prefix (think: subnet). But no one expects we will fill networks with that many hosts per prefix. IPv6 prefixes are part of the mind-change from IPv4, where subnets are tightly packed with hosts, to sparsely populated prefixes.

Consuming IPv6 Address space

But what if a host occupied all of the addresses in a /64 prefix? We all know that IPv6 hosts typically have more than one IPv6 address per interface. But can an interface have 2^64 addresses?

Well, probably your OS won’t allow anywhere near that number of addresses. But with a relatively simple Python program, a lowly Raspberry Pi can listen on all of those addresses simultaneously.

Fun with 2^64 Addresses

This summer I discovered ipv6board, a project run out of Sweden running on a Raspberry Pi streaming a short SMS style message that anyone can write to. You can view the Raspberry Pi display at ipv6board.best-practice.se (unfortunately, the author is having a problem the streaming video part, and may be off-line)

From the ipv6board website, one encodes ASCII into the last 8 bytes (the IID) of an addresses, and pings the ipv6board. The ASCII encoded message will show up on the Raspberry Pi’s 8×3 display. Pinging 2001:6b0:1001:105:4177:6573:6f6d:6521 will print “Awesome!” to the board.


Encoding ASCII

This is all fun, but converting text to ASCII by hand becomes tiresome fairly quickly. I thought, why not have a computer do the ASCII conversion, and pop those 8 bytes into an IPv6 address and send it off to the IPv6Board.

I decided to write a conversion program in shell script, because I wanted it to run everywhere (even on my OpenWrt router). The script takes a message argument, converts it to ASCII, and then pings the ipv6board.

$ ./ipv6board.sh "IPv6 Bd"
PING 2001:6b0:1001:105:4950:7636:2042:6420(2001:6b0:1001:105:4950:7636:2042:6420) 56 data bytes

--- 2001:6b0:1001:105:4950:7636:2042:6420 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms


Run it multiple times (with different messages) to fill the screen of IPv6board. ipv6board.sh is open source and hosted on github.com/cvmiller/ipv6board.sh.

How much address space do we need?

Clearly, 8 bytes is too small to write tweets. Perhaps the version of IP after IPv6 will have even more bytes so we can write a haiku poem. But for now, enjoy the Summer Fun with IPv6 today.

*Fun, Createive Commons


IPvFoo helping you create IPv6-only websites


Firefox & Chrome Extension

The transition to IPv6 will be a long one. Even with Google measuring 25% utilization world-wideon the IPv6 internet, many services will be running dual-stack for some time to come.


But there are those who have already moved to IPv6-only networks, most notably Facebook, and T-Mobile. They run a variety of transition mechanisms to help external IPv4-only services connect or traverse their IPv6-only networks.

But what if you just wanted to check your own servers to ensure they are ready for IPv6-only? Modern applications pull in javascript from many sources, and those external sources may not be available on IPv6, thus breaking your IPv6-only deployment.

There is an excellent extension to Chrome and Firefox which not only displays if the website is over IPv6, but also all the web page elements referred to on a given web page.

IPvFoo Screenshot

Looking for the Green 6

IPvFoo will put a green 6 or red 4 in the upper right corner of the browser indicating which network transport (IPv6 or IPv4 respectively) was used. In addition, a smaller 4 and/or 6 will be displayed to the right of the large 4/6 indicating referenced sites by the webpage.

Clicking on the 6 or 4, will display a list of referred sites and what addresses were used will pop up.

Looking up who owns that address

By right-clicking an address on the right side of the pop-up list, an option of Look up on bgp.he.net. Click that, and Hurricane electric will not only display the AS (autonomous system) that announced that IP block, but clicking on the whois tab will show you who is registered for that IP block.

IPvFoo Screenshot

Creating a IPv6-only site

When creating an IPv6-only site, IPvFoo can quickly tell you if not only your server is running IPv6, but also the references that your web application might be using. In a IPv6-only network, the IPv4 references will not connect (unless you are using a transition mechanism like NAT64)

But why should you create an IPv6-only site. Frankly it is easier and faster, with only one protocol and firewall/ACLs to manage, and no transition mechanisms to traverse. If you believe the projections, the IPv6 Internet will be at 80% by 2025, that is only a little more than five years from now.

Be Ready for the Future Now

IPvFoo not only displays if you are IPv6-only ready, but is interesting to see how the rest of the world is building web sites as well.

Originally posted at www.makikiweb.com

Free (ISP) IPv6 Deployment in France with 6rd

Some distance from Hawaii, but I thought you might enjoy seeing how other ISPs are deploying IPv6. Free.fr is an ISP in France that has been supplying IPv6 to its customers since 2007. Whether it is xDSL or Fibre, the legacy deployment is via 6rd (or Rapid Deployment) which is an IPv6-in-IPv4 encapsulation method.

What’s interesting about Free’s deployment, is that they use the customer’s globally routable IPv4 address and encode the 32 bits in the IPv6 prefix bits 28-60, leaving the customer with a /60. Typically the 0 network is used for the WAN tunnel (6rd tunnel) and the remaining 15 networks are for the customer to use at their house/small office. There is no DHCPv6-PD.

Free supplies a CPE, but if you want to have more control over your routing, and features, you can use an OpenWrt router. Here’s a how-to on configuring your OpenWrt router for Free.

Bon Appetit!


Wireguard IPv6 VPN

Bringing the IPv6 Internet to the IPv4-only land of NAT

WireGuard bringing IPv6 to NATland

The evil of NAT (Net Address Translation) has become institutionalized. And because NAT munges the network header, it causes all sorts of problems, including preventing simple IPv6 tunneling (6in4).

But go to any Starbucks, McDonald’s, the airport or even the Library, and you will find yourself on a NATted network. How to get on the IPv6 Internet when stuck behind NAT? Enter the VPN (Virtual Private Network).

VPN tunneling IPv6

Most people use VPNs make it appear they are in a different location, or are looking for the extra security. But most (99%) VPN providers only support IPv4, and in fact, either disable IPv6, or ask you to do so to prevent IPv6 leakage.

But what if you could use a VPN to transport IPv6 traffic to the IPv6 Internet (now over 25% utilization). I looked at OpenVPN, for this purpose, but found all the moving parts (Certs, pushing routes, lack of IPv6 examples) daunting. If you have a working OpenVPN setup, you may find it easier to tunnel IPv6 through it.

Wireguard, the easy VPN

Wireguard is getting a lot of buzz these days, as it is much easier to setup than OpenVPN. It works similar to ssh keys. Create public/private key pair, for each node in the VPN, tell the each nodes the remote node IPv4 address, and connect! Wireguard is very good at making a complex VPN thing into a simple setup.

But the typical Wireguard VPN only has a roaming laptop at the far end. I wanted to share the IPv6 goodness with my friends, which meant that I wanted to have an entire IPv6 subnet available in IPv4-only NAT-Land.

Using OpenWrt to share IPv6 in NAT-Land

OpenWrt to the rescue. OpenWrt is an open source router software than runs on hundreds of different types of routers. And Wireguard is a package that is prebuilt for each of those routers. There’s even a friendly web GUI frontend to configure Wireguard! What’s not to like.

extending your IPv6 network

The network (above) shows the highlevel design. Allow IPv4 traffic to follow the usual NAT-Land path to the IPv4 Internet (via the Evil NAT Router). But push the IPv6 traffic through the Wireguard Tunnel, where there is another router which will forward it onto the IPv6 Internet. This is called split tunnel in VPN parlance.

The advantages of this topology are:

  • IPv4 traffic follows the usual NATted path, no change there
  • End stations (to the left of R1) require no special software configuration to use it
  • Rather than just keeping the IPv6 to yourself, you can share the IPv6 goodness with anyone connecting to R1 router

The last point means you can bring IPv6 networking into the unfriendly IPv4 NAT-Land world, and show people there is a better way (like a 4K TV). Training is the obvious application, but there are other applications such as transitional networks, and better security.

Address Planning

Before we get too far, you will need an address plan. Since IPv6 will need a network for each link (almost, we’ll use link-local for the point-to-point link), we need a plan so that packets can be routed down to R1 at the far end of the WireGuard VPN from the internet.

Since I am routing the VPN tunneled IPv6 packets through my house, I will need more than a /64 from my ISP. Fortunately, I have a /48. The address plan should look something like this:

  • ::/0 The Internet
  • 2001:db8:ebbd::/48 My House Network
  • 2001:db8:ebbd:9900::/56 my DMZ Network
  • 2001:db8:ebbd:9908::/62 the LAN ports of R2, which are unused, but DHCPv6 allocates them automagically
  • 2001:db8:ebbd:990a::/64 the LAN ports of R1, which is out in NATland

Assuming you are running a DMZ, and an internal LAN, you are going to need at least 3 /64 networks. Therefore if your ISP provides a /60 you have enough, and if they give you a /56, you have plenty to do other IPv6 projects as well.

Installing Wireguard on OpenWrt

The easiest method is to use the Web GUI to install software on the router. But it can also be done via the CLI, after ssh-ing to the router.

opkg update
opkg install luci-app-wireguard

The luci-app-wireguard is for the web GUI, but it also pulls in the kernel module which does most of the work kmod-wireguard, and wireguard-tools which contains the CLI interface.

After installing wireguard, use the CLI tool wg to create a private/public key pair. This command does both in one easy line

wg genkey | tee privatekey | wg pubkey > publickey  

Just like when using ssh private/public keys, the private key is private. It never leaves the system it was created on. Whereas the public key can go anywhere, including publishing it on the internet!

Configuring Wireguard on OpenWrt

  • Add a new interface called WGNET. This is quite easy using the OpenWrt LuCI Web GUI. Under Network->Interfaces, scroll to the bottom and click on the Add New Interface button.
  • Add Private Key and Listening Port to WGNET
  • Add a Peer, including the Peer’s public key and IPv6 Address. I used a Link-local address
  • Click Save & Apply
  • Click Connect WGNET

With any luck, WGNET will connect to the peer.

On the router using the wg show command to show the state of the connection. It should look something like this:

root@makiki:~# wg show
interface: WGNET
  public key: E/2sXvSeg8cggZhJvDOn22z5HqV+eSDduOw46BwBzww=
  private key: (hidden)
  listening port: 29998

peer: cqrT9TuDN3yAjRXprLVWYiH0tAgPxr8Np/HDIQ21+AM=
  allowed ips: ::/0, fe80::/64
  latest handshake: 1 minute, 46 seconds ago
  transfer: 1.05 MiB received, 1.03 MiB sent
  persistent keepalive: every 25 seconds

The key info is the latest handshake. If that isn’t there, then the VPN isn’t up, and you will need to go back and re-check your configuration.

The OpenWrt GUI also has this information under Status->WireGuard Status. (if it is blank, the VPN link isn’t connected)

Setting up DHCPv6-PD

But getting the WireGuard VPN link up is only half the fun. You will quickly discover that you can’t ping6 from a host connected to the R1 LAN ports (and wireless) for two reasons:

  1. the hosts on that LAN don’t have GUA (Global Unique Address) yet
  2. There is no return route down to the R1 LAN (see address plan above)

Advertising RAs on the LAN and creating a DHCPv6 Client

The WireGuard interface is just an interface. We must use a stacked interface to run a DHCPv6 client on top of the WGNET interface. Create yet another interface on Router R1, called LAN6.

Select DHCPv6 Client as the interface type, and WGNET as the underlying interface. Then select Request IPv6-prefix length of 64 Click save and apply. Once the DHCPv6 client gets a Prefix Delegation from R2, the R1 LAN hosts will receive GUAs.

Setting up a DHCPv6-PD server on the upstream router

By configuring a DHCPv6-PD server on R2, not only will a PD be sent down to R1, but a route will be automagically installed on R2 pointing down to the Hosts attached to R1.

Configuring a DHCPv6-PD server on R2 is similar to the procedure on R1, In the web interface, Network -> Interfaces -> Add New Interface, create LAN_WG over the WGNET interface as a type Static Address. Then edit the following blanks:

  • IPv6 Assignment length: 63
  • IPv6 assignment hint: 990a, but you can try leaving this blank

Lower on the page, select the IPv6 Settings tab, and configure the following:

  • Router-Advertisment-service: server mode
  • DHCPv6-Service: server mode
  • NDP-Proxy: disabled
  • DHCPv6-Mode: stateless + stateful

Click save and apply.

Advantages of DHCPv6-PD

The advantage of using DHCPv6-PD is that it will automagically update the addressing if your ISP changes your prefix. All your hosts will automatically pick up the new prefix, and will still have connectivity to the IPv6 Internet.

Road Warrior

What if your remote location is not static? What if the Evil NATland router changes your port? How can you fill in the Peer IP address and port if you have unpredictable NAT changing things on your?

I am still working on it. The real solution would be to leave the Peer IP and Port info blank, and let WireGuard figure it out. But alas with OpenWrt 18.06.1 that doesn’t work.

As a work-around, I have created a script for R2 which listens for the Peer, and reconfigures the R2 WireGuard IP and Port info dynamically. The script is on github.


Although WireGuard works quite well at tunneling IPv6 through multiple layers of NAT, it is not without its limitations.

  • Network blocks UDP. Wireguard uses UDP as transport, and therefore won’t connect (there is no TCP option)
  • Network Latency. Anytime you tunnel IPv6 inside of IPv4, the network latency of IPv6 will never be less than that of IPv4. Therefore the performance of IPv6 will not be shown at its best.

IPv6 Oasis in the desert sands of NAT-Land

A tunneled IPv6 connection is always less desirable than a native one, but using WireGuard does allow one to use IPv6 when stuck in the deserts of IPv4 NAT-Land. And by using it with OpenWrt, the Oasis just got roomy enough to share with your friends.

Article (with more detail) originally appeared on www.makikiweb.com

Linux Containers with OpenWrt

Linux Containers Part 2


Virtual Network in the Palm of your hand

Although you can turn your Pi into an OpenWrt router, it never appealed to me since the Pi has so few (2) interfaces. But playing with LXD, and a transparent bridge access for the containers, it made sense that it might be useful. But after creating a server farm on a Raspberry Pi, I can see where there are those who would want to have a firewall in front of the servers to reduce the threat surface.

Docker attempts this, by fronting the containers with the dockerd daemon, but the networking is klugy at best. If you choose to go it on your own, and use Docker’s routing, you will quickly find yourself in the 90s where everything must be manually configured (address range, gateway addresses, static routes to get into and out of the container network). The other option is to use NAT44 and NAT66, which is just wrong, and results in a losing true peer to peer connectivity, limited server access (since only 1 can be on port 80 or 443), and the other host of brokenness of NAT.

OpenWrt is, on the other hand, a widely used open-source router software project, running on hundreds of different routers. It includes excellent IPv6 support, including DHCPv6-PD (prefix delegation for automatic addressing of the container network, plus route insertion), an easy to use Firewall web interface, and full routing protocol support (such as RIPng or OSPF) if needed.

Going Virtual

The goal is to create a virtual environment which not only has excellent network management of LXC, but also an easy to use router/firewall via the OpenWrt web inteface (called LuCI), all running on the Raspberry Pi (or any Linux machine).

Virtual router Network


OpenWrt project does an excellent job of creating images for hundreds of routers. I wanted to take a generic existing image and make it work on LXD without recompiling, or building OpenWrt from source.

Additionally, I wanted it to run on a Raspberry Pi (ARM processor). Most implementations of OpenWrt in virtual environments run on x86 machines.

If you would rather build OpenWrt, please see the github project https://github.com/mikma/lxd-openwrt (x86 support only)

Installing LXD on the Raspberry Pi

Unfortunately the default Raspian image does not support name spaces or cgroups which are used to isolate the Linux Containers. Fortunately, there is a Ubuntu 18.04 image available for the Pi which does.

If you haven’t already installed LXD on your Raspberry Pi, please look at Linux Containers on the Pi blog post.

Creating a LXD Image

NOTE: Unless otherwise stated, all commands are run on the Raspberry Pi

Using lxc image import an image can pulled into LXD. The steps are:

  1. Download the OpenWrt rootfs tarball
  2. Create a metadata.yaml file, and place into a tar file
  3. Import the rootfs tarball and metadata tarball to create an image

Getting OpenWrt rootfs

The OpenWrt project not only provides squashfs and ext4 images, but also simple tar.gz files of the rootfs. The (almost) current release is 18.06.1, and I recommend starting with it.

The ARM-virt rootfs tarball can be found at OpenWrt

Download the OpenWrt 18.06.1 rootfs tarball for Arm.

Create a metadata.yaml file

Although the yaml file can contain quite a bit of information the minimum requirement is architecture and creation_date. Use your favourite editor to create a file named metadata.yaml

architecture: "armhf"
creation_date: 1544922658

The creation date is the current time (in seconds) since the unix epoch (1 Jan 1970). Easiest way to get this value it to find it on the web, such as the EpochConverter

Once the metadata.yaml file is created, tar it up and name it anything that makes sense to you.

tar cvf openwrt-meta.tar metadata.yaml

Import the image into LXD

Place both tar files (metadata & rootfs) in the same directory on the Raspberry Pi. And use the following command to import the image:

lxc image import openwrt-meta.tar default-root.tar.gz  --alias openwrt_armhf

Starting up Virtual OpenWrt

Unfortunately, the OpenWrt image won’t boot with the imported image. So a helper script has been developed to create devices in /dev before OpenWrt will boot properly.

The steps to get your virtual OpenWrt up and running are:

  1. Create the container
  2. Adjust some of the parameters of the container
  3. Download init.sh script from github
  4. Copy the init.sh script to /root on the image
  5. Log into the OpenWrt container and execute sh init.sh
  6. Validate that OpenWrt has completed booting

I use router as the name of the OpenWrt container

lxc init local:openwrt_armhf router
lxc config set router security.privileged true

In order for init.sh to run the mknod command the container must run as privileged.

Download init.sh from the OpenWrt-LXD open source project

The init.sh script is open source and resides on github. To download it on your Pi, use curl (you may have to install curl)

curl https://raw.githubusercontent.com/cvmiller/openwrt-lxd/master/init.sh > init.sh

After copying the script to the container, Log into the router container using the lxc exec command, and run the init.sh script.

lxc exec router sh
# sh init.sh

Managing the Virtual OpenWrt router

The LuCI web interface by default is blocked on the WAN interface. In order to manage the router from the outside, a firewall rule allowing web access from the WAN must be inserted. It is possible to edit the /etc/config/firewall file within the OpenWrt container and open port 80 for external management.

lxc exec router sh

# vi /etc/config/firewall

config rule                      
        option target 'ACCEPT'   
        option src 'wan'         
        option proto 'tcp'       
        option dest_port '80'    
        option name 'ext_web'                                   

Save the file and then restart the firewall within the OpenWrt container.

/etc/init.d/firewall restart

Now you should be able to point your web browser to the WAN address and login, password is blank.

Step back and admire work

Type exit to return to the Raspberry Pi prompt. By looking at some lxc output, we can see the virtual network up and running.

$ lxc ls
|  NAME   |  STATE  |          IPV4          |                     IPV6                      |    TYPE    | SNAPSHOTS |
| docker1 | RUNNING | (eth0) | fd6a:c19d:b07:2080:216:3eff:fe58:1ac9 (eth0)  | PERSISTENT | 0         |
|         |         | (docker0)   | fd4b:7e4:111:0:216:3eff:fe58:1ac9 (eth0)      |            |           |
|         |         |                        | 2001:db8:ebbd:2080:216:3eff:fe58:1ac9 (eth0)  |            |           |
| router  | RUNNING | (eth1) | fd6a:c19d:b07:2084::1 (br-lan)                | PERSISTENT | 1         |
|         |         | (br-lan) | fd6a:c19d:b07:2080::8d1 (eth1)                |            |           |
|         |         |                        | fd6a:c19d:b07:2080:216:3eff:fe72:44b6 (eth1)  |            |           |
|         |         |                        | fd4b:7e4:111::1 (br-lan)                      |            |           |
|         |         |                        | fd4b:7e4:111:0:216:3eff:fe72:44b6 (eth1)      |            |           |
|         |         |                        | 2001:db8:ebbd:2084::1 (br-lan)                |            |           |
|         |         |                        | 2001:db8:ebbd:2080::8d1 (eth1)                |            |           |
|         |         |                        | 2001:db8:ebbd:2080:216:3eff:fe72:44b6 (eth1)  |            |           |
| www     | RUNNING | (eth0) | fd6a:c19d:b07:2084:216:3eff:fe01:e0a3 (eth0)  | PERSISTENT | 0         |
|         |         |                        | fd4b:7e4:111:0:216:3eff:fe01:e0a3 (eth0)      |            |           |
|         |         |                        | fd42:dc68:dae9:28e9:216:3eff:fe01:e0a3 (eth0) |            |           |
|         |         |                        | 2001:db8:ebbd:2084:216:3eff:fe01:e0a3 (eth0)  |            |           |

The docker1 container is still running from Part 1, and still connected to the outside network br0. You can see this by the addressing assigned (both v4 and v6).

The router container (which is running OpenWrt) has both eth1 (aka WAN) and br-lan (aka LAN) interfaces. The br-lan interface is connected to the inside lxdbr0 virtual network. And OpenWrt routes between the two networks.

Limitations of Virtual OpenWrt

There are some limitations of the virtual OpenWrt. Please see the github project for the most current list. Most notably, ssh although it works, needs improving.

Address Stability

Because all of this is running on LXC, there is address stability. Not matter how many times you reboot the Raspberry Pi, or restart containers in different order, the addresses remain the same. This means the addresses above can be entered into your DNS server with out churn. Something Docker doesn’t provide.

Running a Virtual Network

LXC is the best at container customization, and virtual networking (IPv4 and IPv6). With LXCs flexibility, it is easy to create templates to scale up multiple applications (e.g. a webserver farm running in the palm of your hand). OpenWrt is one of the best Open source router projects, and now it can be run virtually as well. Now you have a server farm in the palm of your hand, with excellent IPv6 support and a firewall! Perhaps the Docker folks will take note.

Article originally appeared (with more detail) on www.makikiweb.com