Upto: Table of Contents of full book "Internet of Things - a techie's viewpoint"

OpenWrt on a Raspberry Pi

This chapter was meant to be the second part of a three part series on Homenet for the Linux Journal. Very sadly, the journal closed down in August 2019 and so this was never published.

Resources

The OpenWrt site at https://openwrt.org is the entry point to all OpenWrt activities. The main alternative open source router system is DD-WRT at https://dd-wrt.com. It often includes routers not supported by OpenWrt, but is generally a bit harder to use. Several other alternatives are listed by AlternativeTo... and also by Wikipedia's List of router firmware projects

Introduction

In the first part of this series I looked at enabling a typical home router for IPv6, what that looks like, and how to find out things like the IPv6 hosts on my network. This was the start of my journey to Homenet.

The consumer level routers I have at my disposal are locked down to support an assumed user level. I know the routers have the capability of acting as full computing devices, but the vendors have chosen to remove those capabilities from me. I saw this with IPv6, and to go beyond that will be harder still.

For example, a simple thing: one of the things that I can't seem to find is what IPv6 prefix is being given to my Linksys EA6900 router. On the LAN side the router hands out a /64 prefix via router adverts and each node creates one or more IPv6 global addresses from that. But to do subnetting properly I'm going to need a bigger address space than that. A /56 would be good, and then I can have upto 28 subnets, which will keep me going for a while. By email, my ISP informed me that they have given me a /56, so they are doing the right thing.

But since I can't find this information from my standard router, I either have to make it non-standard, or replace it with one I can control.

The OpenWrt project (which forked to the LEDE project but has since merged) can turn my router into an open source Linux router that I can control through an ssh or web interface. Cool, but I want a more failsafe method than just flashing the firmware on my only internet gateway and trusting it works. Paranoia may be justified sometimes!

The Raspberry Pi (RPi) is the obvious solution to building a custom router and so I will go that way. Once I have it stable, I can maybe look at re-flashing my Linksys router.

OpenWrt

OpenWrt supports an enormous number of routers and has pre-prepared images for many of them. The first task is to sort out which image you need to download. From the home page, select "Supported Devices" from the menu on the left. This will show a list of tables, and select from that "Where can I download OpenWrt firmware for my router?" This will bring up an extensive list. Search this list for your router. In my case, for the Raspberry Pi 3 B+. The 8th column will say the principal Target, here brcm2708 and in the 9th column the Subtarget, here brcm2710. The 10th column takes you to a download directory, and select the ext4 image. Download this, gunzip it and copy it to an SD card for the RPi using dd (or any other favourite method).

Choosing an OpenWrt image
Choosing an OpenWrt image

I adopted the approach of getting the new router to work as a secondary router to my main one. Once that is done, swap them over so that the new router is connected to my ISP. Then the old router is a secondary router to the new one. That way, I get much of the configuration done while the old router is in place and unaffected. Then by swapping them over, I leave all my old devices connected to the old router. I can gradually move them around with minimal upsets to the rest of my household!

Setting up the new router behind the old router

When OpenWrt is booted up on the RPi, it assigns the IPv4 address 192.168.1.1 to the RPi's ethernet card as a static address. If you don't have anything else in your network using that address and are on the same 192.168.1.0/24 network, then plug it into your network using the ethernet port and ignore these next steps. If you do, then it gets a bit more tricky. I did have something on 192.168.1.1, so I attached a keyboard and screen to the RPi (easy to do with the RPi, not so easy with general routers!).

Then either directly or via ssh, log in as user 'admin' and password '1234' and edit the file /etc/config/network. Assuming your current router is handing out addresses locally using DHCP, change the 'lan' interface from the default configuration


config interface 'lan'
    option type 'bridge'
    option ifname 'eth0'
    option proto 'static'
    option ipaddr '192.168.1.1'
    option netmask '255.255.255.0'
    option ip6assign '60'
      
to get values picked up from the current router using DHCP

config interface 'lan'
    option ifname 'eth0'
    option proto 'dhcp'
      
and reboot with a wired connection from eth0 to the current router. Then you should be on your existing network using a wired connection. The new router then appears as a new device on the existing network, with a DHCP IPv4 address of 192.168.1.48 (in my case). The network looks like Figure 2.
RPi added to existing network
RPi added to existing network

Really, the interface should have been changed from 'lan' to 'wan'. But that would put internal services inside of the RPi's new firewall and then you can't ssh into or get web access to the router from outside on the existing network without changing firewall rules. So leave it as 'lan' for now.

Don't try setting up wireless yet, because later I will be configuring this as a wireless access point to a different wireless network.

Setting up another network on the new router

The RPi only has one ethernet port and we are using that already. Eventually, that will be the WAN port. Most home routers have several ethernet ports on the LAN side. To extend the RPi, I decided to add a USB to ethernet adaptor (shields are also available). I bought an ASIX Electronics Corp AX88772B, sold under the brand name Astrotek. I plugged it in, attached a live ethernet cable and saw ... nothing. The command ifconfig -a could not see it. So I needed to find out what USB devices I have, but lsusb is missing from the standard OpenWrt image.

To fix that use the OpenWrt package manager opkg which behaves like other managers such as dpkg,


      opkg update
      opkg install usbutils
      
Then I can run lsusb to see the adapter. But there is no appropriate ethernet driver loaded. Hmmm, what is it? Plug it into a normal Raspbian system and see what lsmod tells me is needed. Actually, a web site told me I needed kmod-usb-net-asix. So

	  opkg install kmod-usb-net-asix
      
and then the adapter shows up as eth1. Finally! I can use one side as the WAN connection, plug upto four USB-ethernet adapters and use WiFi for other devices.

Actually, rather than many USB adapters, it is cheaper to buy a 5-port unmanaged layer 2 switch and plug that into the new ASIX ethernet port. I'm part way towards the RPi as router! It looks like Figure 3

RPi with a subnet
RPi with a subnet

(I won't show the switch in later figures for simplicity.).

Now we can configure the new ethernet interface and wireless to act in a new network. I chose 192.168.3.0/24 for my new network as my original network was a 192.168.1.0/24 network and I was already playing with another router on a 192.168.2.0/24 network. So I need to configure eth1 as a DHCP server, set up a wireless SSID, and bridge the new wired and wireless networks together.

A lot of this can be done using the GUI interface (called Luci) to OpenWrt, or by directly editing the configuration files. ~tore at Making a Homenet router out of OpenWrt shows how to do this using the GUI. If you want to edit the files directly, vi (vim) is there, or you can download a simpler editor such as nano or several others (not emacs though!). Whichever way is used, you should end up with configuration files similar to these with changes highlighted in red:

/etc/config/network:


config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config interface 'wan'
	option ifname 'eth0'
	option proto 'dhcp'

config interface 'lan'
	option proto 'static'
	option ifname 'eth1'
	option ipaddr '192.168.3.254'
	option netmask '255.255.255.0'
        option gateway '192.168.1.254' # this is the internet g/w
        option type 'bridge'

    
/etc/config/dhcp: Much of this can be set up for you by using the GUI interface. You really only need to specify parts like using DHCP on the new eth1 interface, and what is your wireless SSID password.

config dnsmasq
        # no changes in this (long) section
        # so not included

config dhcp 'lan'
        # no changes

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'

config odhcpd 'odhcpd'
        # no changes


config dhcp 'eth1'
	option start '100'
	option leasetime '12h'
	option limit '150'
        option interface 'eth1'

    
/etc/config/wireless:

config wifi-device 'radio0'
	option type 'mac80211'
	option channel '11'
	option hwmode '11g'
	option path 'platform/soc/3f300000.mmc/mmc_host/mmc1/mmc1:0001/mmc1:0001:1'
	option htmode 'HT20'
	option country '00'
	option legacy_rates '1'


config wifi-iface 'default_radio0'
	option device 'radio0'
	option mode 'ap'
        option ssid 'OpenWrt'
	option network 'lan eth1'
	option encryption 'psk2'
	option key 'my-SSID-secret-key'

    

At the end of all this, I had a working IPv4 network 192.168.3.0/24 with both wireless (ssid is 'OpenWrt') and wired access, connected as a subnet to the original 192.168.1.0/24 network. IPv4 NAT is turned on by default, so hosts connected to the new network should be able to access the internet firstly through the RPi gateway 192.168.3.254 and then through the original router gateway 192.168.1.254. However, you won't be able to access hosts on the new network from any external network (including the rest of the home), since the firewall on the RPi will be blocking inward access.

Debugging

Playing with networking configurations isn't always fun. Debugging is often necessary, but it isn't a matter of stepping through code, setting breakpoints, etc as in debugging an application. You want to see what is going in the network itself, that is, what packets are being sent around. Two standard tools for this are tcpdump which gives a command line interface to network traffic, and wireshark which has a GUI interface.

You can install tcpdump on the RPi router by


	  opkg install tcpdump
      
I prefer to use wireshark, but that isn't available on OpenWrt. Never mind, install it on a more capable laptop or PC that is on one of the new router's networks. Then you can run tcpdump using ssh on the RPi router, wireshark on the other monitoring machine, and connect them together by a pipeline. I run this from a PC connected 'downstream' (i.e. on its eth1 interface) from the RPi:

	  ssh root@192.168.3.254 tcpdump -i eth0 -U -s0 -w - | sudo  wireshark -k -i -
	
      
This captures packets sent and received on the new router's eth0 interface and sends them to wireshark on my monitoring computer. I will use variations on this later.

There is a little hiccup in the last command: ssh by default wants a password, and so does sudo and they both ask at the same time. Who gets which one? The suggestion from OpenWrt is to set up ssh keys so that it doesn't ask for a password. This involves extra work, so my solution is to first run an innocuous command on my monitoring host like


	  sudo ls
      
which asks for the sudo password on my monitoring host, and then gives a little time when I can execute more commands without asking again. Then I only get asked for the ssh password for the RPi router.

Wireshark is a powerful and complex tool. It takes a little while to get your head around it. Little issues like the difference in syntax between capture filters and display filters can cause headaches. It is worth spending time on tutorials such as Wireshark Tutorial for Beginners - YouTube by Anson Alexander, and other more complex ones.

There is another little wrinkle to this: the ssh command can only run when there is a network in place between the router and monitoring computer. On booting or resetting the network, any existing connection is dropped, and has to be re-established. So any network setup packets can't be seen using this.

To see all the packets, I setup a small 4-port hub between one of the router's ports and the network I am interested in. Then as well as the router and the network, I also plug in the monitoring computer and just run wireshark on that (no need for ssh, just listen on the ethernet port). All the packets to and from the router are duplicated on all the hub's interfaces, so I can see everything. The only drawback is that most hubs are limited to 10Mbps, so my network will run s-l-o-w-l-y. It can be done using a faster managed bridge, but that requires extra configuration to duplicate packets, and I am trying to reduce complexity!

For example, to see the conversation between the original router and the ISP's modem, I set it up as in Figure 4.

Debugging using a hub
Debugging using a hub

The hub can be set up between any pair of ethernet nodes.

Capturing wireless traffic is also possible but I haven't needed to do that yet. It's a lot more tricky if the wireless network uses encryption and is described at How to decrypt WPA traffic in Wireshark .

Setting up the new router in front of the old router

Now it's time to swap the roles of the old and new routers. To do this, we must find out how the old router connects to the ISP. Mine uses a PPPoE ethernet connection to a modem supplied by my ISP. The configuration settings can be found by digging through the menus on the old router's web page. For me, they are


      IPv4:
      Connection type: PPPoE
      username: xyz@abc.com
      passwd:   whatever
      MTU: auto

      IPv6:
      IPv6 automatic: enabled
      DUID: 00:02:03:09:05:05:C0:56:27:6F:9C:C5
      6rd tunnel: disabled
      prefix etc: empty
      MTU: auto
      

I now swap around the wiring so that my new RPi router is connected on its WAN interface (the normal RPi ethernet interface, eth0) to the ISP's modem, while the old router's WAN interface is now connected to the RPi eth1 interface. The configurations now have to be changed.

Swapping the two routers
Swapping the two routers

For my old router, the WAN interface has to be set to dhcp because that is what the RPi's eth1 interface will deliver. I do that from a browser in my old home network, as nothing has been changed on the LAN side of that old network.

For my new router, in my case it has to be set to a PPoE connection. Copying the values from the old router and resetting some of the interface names gives me in /etc/config/network on the RPi:


config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config interface 'wan'
	option ifname 'eth0'
	option proto 'pppoe'
	option username 'xyz.abc.com'
	option password 'whatever'

config interface 'lan'
	option proto 'static'
	option ifname 'eth1'
	option ipaddr '192.168.3.254'
	option netmask '255.255.255.0'
	option type 'bridge'
      

Assuming nothing has gone wrong, the RPi should now be the principal router connecting to the ISP's modem, with the old router on the subnet 192.168.3.0/24. I know mine worked fine, because I did the changeover while my partner was out for an hour, and when she returned had no complaints about "Is the network down again?". Success is demonstrated by lack of screams from the rest of the household :-)

At the end of this, I have an IPv4 network working exactly as before, but now with an RPi as principal router. Instead of a black box where I am constrained by the GUI interface offered by the router, I now have a connection to my ISP where I can run tools like tcpdump to see who is doing what on my network and generally have a standard Linux box to play with.

Gotcha: mislocated server

Actually, it's only me screaming: I run a web server out of my home, and that is now buried down below my old router. It was accessible by NAT port forwarding, but now it is in the wrong place. I need double-NAT from my new router to the old router. Except the old router has gone into a sulk and exposes no open ports to the new router ("all ports are filtered"). This is a problem with no obvious solution, so the simplest thing is to move the web server to the new network. It's a wired device, an HP Proliant Microserver which is still going great guns after several years. The simplest solution was to move the server from the old router's network to the new router's network by swapping the ethernet cable from the old router to the new one.

It's an IPv4 network at present. To make the server visible externally, I need to use port forwarding. Port forwarding is done using the router's firewall configuration file /etc/config/firewall. I added the following lines to this file, to forward HTTP and HTTPS traffic:


config redirect
	option target DNAT
	option src wan
	option dest lan
	option proto
	option src_dport 80
	option dest_dport 80
	option dest_ip 192.168.3.216
	option enabled

config redirect
	option target DNAT
	option src wan
	option dest lan
	option proto
	option src_dport 443
	option dest_dport 443
	option dest_ip 192.168.3.216
	option enabled
      
Then apply these by /etc/init.d/firewall restart. This can all be done from the OpenWrt web GUI, but I prefer to dig around at the command line level.

Gotcha: no PPPoE connection

This was a serious problem, in that sometimes the PPPoE connection to my ISP from the RPi wouldn't get set up. With the above OpenWrt configuration files, I should see the interfaces

lo
The loopback address, 127.0.0.1
eth0
The physical WAN device
pppoe-wan
The PPPoE virtual WAN device connected to eth0
eth1
The LAN ethernet device
wlan0
The wireless LAN device
br-lan
The virtual bridge linking eth1 and wlan0 into my LAN

Sometimes the pppoe-wan interface never showed up, and I had no internet connection. This almost always happened when trying to set up IPv6 and so looked like an OpenWrt configuration issue. But after much investigation and assistance in the OpenWrt forum IP breaks using @wan instead of eth0 , it seems to be either a hardware issue with the ethernet card or perhaps an issue with the ethernet driver.

When the pppoe-wan interface doesn't show, running /etc/init.d/network restart would fix it - but sometimes up to 10 restarts needed! I don't have a solution as yet, but I have a workaround: swap the two ethernet cards. That is, make eth0 the LAN side and eth1 the WAN side. It's a quick edit on the different configuration files. Different hardware and driver now on the WAN side, and the problem disappeared. Yes, it's a hack, but well, it works so far.

Router speeds

The RPi isn't designed as a router, so you can't expect it to behave like one dedicated to that purpose. The standard ethernet device is actually a USB device, so it shares the USB bus with any other USB devices. Nevertheless, it should be able to achieve upto 100Mbps. Let's see what it does.

I installed speedtest-cli. This is a Python script, so you may need to go through


	  opkg install python
	  opkg install python-pip
	  pip install speedtest-cli
      
Then when you run speedtest-cli you may get the error

$ speedtest-cli
Retrieving speedtest.net configuration...
Cannot retrieve speedtest configuration
ERROR: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] unknown error: unable to get local issuer certificate (_ssl.c:1051)
      
This needs to be fixed by setting a bash environment variable (https://github.com/sivel/speedtest-cli/issues/568)

	  export PYTHONHTTPSVERIFY=0
      

My ISP connection is 75/75Mbps up and down, and I usually get close to that. From the new router, I get 73.50/70.43Mbps, so the ethernet interface is performing okay. From a PC connected to the new router by wireless, it isn't so good: 42.59/27.99Mbps. From a PC connected to the new router by ethernet cable, 79.56/65.90Mbps. So within the constraints of my home connection to an ISP, that is okay. If you have a faster connection, then you will clearly want a faster router. Also, the wireless on the RPi is not particularly powerful, so if your home is large you might lose connections or speed. Most commercial home routers seem to lose the plot if there are more than 30 wireless nodes connected. I don't have 30 to play with in my home (yet), but doubt if the RPi could handle that many.

Note: my speeds are achieved by using a wireless ISP provider, Lightning Broadband. The much touted Australian NBN (National Broadband Network) has proved to be a disappointing waste of money from a Government that destroyed the original idea of fibre to the home, and even quite recently claimed that 25Mbps was good enough for everybody. I see no value in going backwards but wish I could go forwards to the Gigabit speeds seen in even our nearest neighbour, New Zealand!

But where is IPv6?

I've left IPv6 out of this so far as just replicating the original environment is complex enough. But from here, setting up IPv6 isn't hard at all. I'll make it simple IPv6 - what happens for Homenet will be discussed in the next article in this series.

First, let's look at the IPv6 network information given by the ISP. To remove most of the irrelevant packets, start wireshark from a PC looking at packets from the hub between the router and the ISP modem, with a display filter set to icmpv6 || dhcpv6.

A global IPv6 prefix is given out by router adverts from the ISP to the multicast address ff02::1. See Figure 6,

ISP router advertisement
ISP router advertisement

with details in Figure 7.
Router advertisement packet details
Router advertisement packet details

The source of the advert is the ISPs router (using its link local address). It also includes a /64 prefix of 2400:3740:100:d9::/64, which is used by recipients such as my edge router to allocate themselves a GUA on the ISP side.

A prefix request is made by a DHCPv6 Request from my router to the ISP (actually, to anyone who is listening to the multicast address ff02::1:2). See Figure 8,

Prefix request
Prefix request

with details in Figure 9.
Prefix request packet details
Prefix request packet details

The response from the ISP is the packet shown in Figure 10.
Prefix reply
Prefix reply

The details of this packet are shown in Figure 11
Prefix reply details
Prefix reply details

This offers from the ISP a /56 prefix 2400:3740:200:d900::/56. Our router can then use this to offer addresses within this range to its own LAN clients.

Please note that the /64 offered by the ISPs Router Advert and the /56 from the DHCPv6 reply to the prefix request are disjoint: 2400:3740:100:d9::/64 versus 2400:3740:200:d900::/56. This is good practice by my ISP: if my router took an address from within the /56 range, it would in effect have "stolen" one of the addresses from use in my router's LAN, and that would be against the idea that my router has complete use of the /56 on the LAN side>.

The ICMPv6 router adverts and the DHCPv6 requests and responses for multiple routers overall are given in Figure 12

Overview of requests and responses
Overview of requests and responses

(There are actually earlier steps of the client sending a Solicit message and the router replying with an Advert, omitted for simplicity.)

We need to configure the new router to handle these messages and also to pass on relevant information to its own clients. Clients will assign themselves a link local address anyway. With the prefix information passed to them from the ISP via the new router they will be able to generate a GUA. But it would also be good for the router to send to clients a ULA prefix so all nodes can communicate with each other in the home network.

The principal change is to the OpenWrt file /etc/config/network on the new RPi router. This now needs a wan6 section to handle the messages from the ISP. The change is easy: just add these lines to the file:


config interface wan6
    option ifname '@wan'
    option proto dhcpv6
      
Now there is a little explanation required here. The OpenWrt documentation suggests the interface name could be interchangeably eth0 (or whatever the interface is) or @wan. Not so, at least not when we are using PPPoE. If we use eth0 then DHCPv6 packets go out over the eth0 interface. But they need to go out over the pppoe-wan interface. So the wan6 interface needs to be mapped to whatever the wan interface is, by using @wan.

We also add the line


	  option ipv6 '1'
      
to the wan section, and

	  option ip6assign 59
      
to the lan section. This ensures that proper router adverts get passed to the clients, in particular to the old router and its clients. I've changed the earlier value of 60 to 59 because the behaviour of odhcpd seems to be different to the documentation. From an OpenWrt forum discussion odhcpd gets wrong prefix from DHCPv6 SOLICIT messages 'jow' says
The odhcpd server will never hand out the entire downstream prefix on client requests but will always try to partition it into at least two halves.
so if we want a /60 prefix handed out, we need to set ip6assign to 59.

We can add in the ULA addresses by also adding to this file a random ULA prefix


config globals 'globals'
    option ula_prefix 'fd87:5070:a96b::/48'
      
Then nodes will also assign themselves a ULA based on this prefix.

The /etc/config/network file finally looks like


config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix 'fd87:5070:a96b::/48'

config interface 'wan'
	option ifname 'eth1'
	option proto 'pppoe'
	option username 'uer name'
	option password 'password'
	option ipv6 '1'

config interface 'lan'
	option proto 'static'
	option ifname 'eth0'
	option ipaddr '192.168.3.254'
	option netmask '255.255.255.0'
	option type 'bridge'
	option ip6assign 59

config interface wan6
	option ifname '@wan'
	option proto dhcpv6
      

You may also need to add an entry to the /etc/config/firewall file, unless it is already there:


config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option src_ip 'fc00::/6'
	option dest_ip 'fc00::/6'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'
      

At the end of all this, the new router gets an IPv6 address of 2400:3740:100:d9:3d04:ccc0:5160:2c6d/64 on the WAN side, 2400:3740:200:d900::1/60 on the LAN side, and broadcasts router adverts to its clients shown in Figure 13

RPi adverts to its clients
RPi adverts to its clients

with /64 prefixes for the GUA and ULA of each node. Each node can then use these for SLAAC or DHCPv6 assignment of their addresses. The message also includes a /56 for GUA subnetting and a /48 for ULA subnetting.

At the end of all this, one node on the new router's network sees IPv6 addresses


    inet6 2400:3740:200:d900::858/128 scope global
    inet6 fd87:5070:a96b:0:2150:6480:8d6a:7565/64 scope global temporary dynamic
    inet6 fd87:5070:a96b:0:224:21ff:fe43:4aed/64 scope global dynamic
    inet6 2400:3740:200:d900:2150:6480:8d6a:7565/64 scope global temporary dynamic
    inet6 2400:3740:200:d900:224:21ff:fe43:4aed/64 scope global dynamic
    inet6 fe80::224:21ff:fe43:4aed/64 scope link
      
a mix of permanent and temporary GUAs and ULAs and a link local address.

On the old router, which is now on a subnet of the new router, we see on its client side


    inet6 2400:3740:200:d904:224:21ff:fe43:4aed/64 scope global deprecated dynamic
    inet6 fd87:5070:a96b:4:2150:6480:8d6a:7565/64 scope global temporary dynamic
    inet6 fd87:5070:a96b:4:224:21ff:fe43:4aed/64 scope global dynamic
    inet6 fe80::224:21ff:fe43:4aed/64 scope link
      
The Linksys router is picking up the GUA and ULA prefixes okay.

Firewall rule

My web server is on my home network and should be visible externally. The mechanisms to do this are different for IPv4 and IPv6. Earlier, I showed how to this for IPv4 using port forwarding. Now I have to set up an IPv6 firewall rule to allow external hosts to connect to the server.

OpenWrt uses iptables by default. This can be immensely complicated, but we don't need to go into the horrors. Simply ACCEPT suitable packets for my server with GUA 2400:3740:200:d900::26:


config rule
	option src wan
	option proto tcp
	option dest lan
	option dest_ip 2400:3740:200:d900::260
	option dest_port 80
	option family ipv6
	option target ACCEPT
                                               
config rule                                     
        option src wan                          
        option proto tcp                        
        option dest lan                         
        option dest_ip 2400:3740:200:d900::260
        option dest_port 443
        option family ipv6                      
        option target ACCEPT  
      

There is a significant difference between IPv4 port forwarding and IPv6 firewalling. Under IPv4, you could have many services on many hosts inside your network, all with a single external IPv4 address using NAT. Under IPv6, each host has (at least) one distinct IPv6 GUA. So to access services on different internal hosts from external hosts, you will need to go to different IPv6 addresses.

I use an external DNS provider Zoneedit for my domain jan.newmarch.name. In the last article I talked about making these visible on the global DNS. There are no changes to the process described there.

Static IP addresses

For services runing inside your network to be visible outside, they will generally need to have static IP addresses. For IPv4 services, the static IP is the WAN address of your gateway router as it uses NAT to map external requests to internal hosts. But for IPv6, you need the GUA of the host with the service to stay static.

You may be changing routers, so you don't really want the router to be in charge of the internal hosts IPv6 addresses. The page IPv6 addressing, dynamic prefix static local part describes how to do this using the Linux NetworkManager, but I couldn't get it to work. That is, I got it to add a fixed suffix to the prefix, but only as a /64 and it needed to be a /128.

I did get fixed IPv6 addressing by the OpenWrt router working by setting DHCPv6 parameters in /etc/config/dhcp:


config host
	option name 'server'
	option dns '1'
	option mac '44:1E:A1:3B:75:31'
	option hostid '260'
	option ip '10.208.0.2'
	option leasetime '12h'
        option duid '0004d946de693def512ab5f4ee58409f88d1'
      
This gives a fixed IPV4 address of 10.208.0.2, and a suffix of 260 to be added to the advertised prefix to make a /128 IPv6 address on the host 'server'. I had to use the Luci GUI interface to do this - I couldn't have figured it out from the documentation. It didn't work immediately - I had to wait some time, probably for the DHCP lease to expire.

DNS

External hosts

DNS (domain name server) allows us to use names like www.google.com instead of the IP addresses. For IPv4 it is working fine. For IPv6 it is also. dig is the tool of preference for doing command line DNS queries. Its output is a bit messy, and you usually want to look for the ANSWER section. For example, a simple (IPv4 lookup) of www.google.com is


$dig www.google.com

; <<>>; DiG 9.11.3-1ubuntu1.5-Ubuntu <<>> www.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43656
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;www.google.com.			IN	A

;; ANSWER SECTION:
www.google.com.		193	IN	A	172.217.167.68

;; Query time: 2 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Mar 13 16:49:36 AEDT 2019
;; MSG SIZE  rcvd: 59
      
with the answer highlighted in red. The Google IPv4 address is 172.217.167.68 (it may be different in your location).

We can ask for an IPv6 address by specifying that we want an AAAA ('quad-A') record by


	  dig AAAA www.google.com
      
with answer

;; ANSWER SECTION:
www.google.com.		243	IN	AAAA	2404:6800:4006:802::2004
      
to get address 2404:6800:4006:802::2004.

Now we actually made that DNS query using IPv4 to get an IPv6 address. To make the same query using IPv6, we need to specify the -6 flag


	  dig -6 AAAA www.google.com
      
which gives the same answer but obtained over IPv6 instead of IPv4.

Internal hosts

The situation isn't quite so simple with internal hosts. For starters, look at what the RPi router's Luci interface gives you when you go to the router's web page, shown in Figure 14

DHCP leases
DHCP leases

OpenWrt sets up the local DNS to have the domain .lan, and any hostname with no domain given belongs to that domain. Using dig these all return valid IPv4 addresses in the .lan domain

The router itself also has an address for its DNS name OpenWrt.

I've set up DHCPv4 fixed address entries for only two of these: server and desktop. The other host names are presumably coming from the hostname parameter in the DHCP requests and responses between clients and servers, as given in RFC2132.

For DHCPv6, no fixed IP addresses are assigned by me. So the only two entries are presumably coming from the DHCPv6 requests for the host name as per the IETF draft Options for DHCPv6 . The other nodes are not supplying anything.

dig AAAA ... works on the two hosts Desktop and newmarch-Latitude-E6520 but not on any others.

Not so good, eh! But to the rescue comes ip6neigh which uses IPv6 neighbour discovery to populate a host file which it hands to the DNS server dnsmasq. It classifies the addresses it discovers into LL, MAN, GUA and TMP.GUA addresses.

After it is run, you can see the addresses it creates by ip6neigh list all which gives something like


newmarch-Latitude-E6520.LL.lan fe80::8d6:8384:320e:ec12
newmarch-Latitude-E6520.TMP.GUA.lan 2400:3740:200:d900:55b6:57a2:be8e:4739
newmarch-Latitude-E6520.TMP.lan fd87:5070:a96b::55b6:57a2:be8e:4739
Linksys11654                   fd87:5070:a96b::c256:27ff:fe6f:9cc5
Linksys11654.GUA.lan           2400:3740:200:d900:c256:27ff:fe6f:9cc5
Linksys11654.LL.lan            fe80::c256:27ff:fe6f:9cc5
Linksys11654.MAN.lan           fd87:5070:a96b::10a
...
      
It isn't perfect nor complete, but a lot better than nothing! These can all be used by lookups such as

	  dig AAAA newmarch-Latitude-E6520.LL.lan
	  dig AAAA newmarch-Latitude-E6520.TMP.GUA.lan
	  dig AAAA newmarch-Latitude-E6520.TMP.lan
      

I started up a web server on the newmarch-Latitude-E6520 machine, and using the url http://newmarch-latitude-e6520.tmp.gua.lan/ was able to connect to it from other internal hosts. I've installed an extension IPvFoo to the Chromium browser which gives me an indication as to whether it has connected via IPv4 or IPv6 (a '4' or '6' in the extensions bar) and it confirms I have connected by IPv6.

Routing

One of the keys to IPv6 addressing is how it allows (or not) routing from one network to another. For LL (link local) addresses, routing to another segment is not allowed. For ULA (unique local addresses), routing within the organisational boundaries (here the home) is allowed. For GUA (global unique addresses) routing to and from any IPv6 address is allowed - all this subject to firewalls of course!

At the moment we have an RPi as edge router to the internet with the Linksys home router still with its original firmware as a subnet. Not much to do routing with yet!

The Linksys doesn't want to play ULAs at all. It won't allow ping6's to ULA addresses either way across its segment boundary. It will allow ping6's from its own clients to any GUAs on the internet, so it's not totally bad :-). It's just not set up to handle multiple IPv6 networks.

So I set up another RPi as client router to my RPi edge router, just as I did originally with the RPi to the Linksys router. The only change I made was to the SSID for this second RPi to avoid confusion with the first RPi's wireless network.

With clients on the two RPi OpenWrt networks, everything was fine: I could ping6 ULAs between any two nodes on the networks. Of course, this isn't a large network requiring heavy duty routing algorithms - but that is where Homenet expects home networking to go, and will develop user-friendly routing algorithms.

Conclusion

This article has discussed installing the OpenWrt system onto an RPi. While I have mainly used command line tools, the Luci web interface allows most of the configuration to be done using a web GUI. What you get is an open Linux system rather than a locked-down proprietary router and that to me is always a good thing - with more and more devices coming onto my network, I have become progressively more uneasy as to what they are all doing, and this gives me the means to find out.

The next article will talk about the Homenet system, and how this gives you even more visiblity - but also control - over increasingly more complex home networks.