where the flamingcow roams

WiFi client router setup


I’ve still got two devices in my home that can’t do WiFi natively, but that I don’t have a good wiring solution for (one is an RPi that has a strange device on the USB bus that panics if anything else is on the USB bus, and the other is a FireTV with issues). This is a great opportunity to use another Raspberry Pi as a WiFi client <-> wired connection, providing a wired drop wherever I want it.

If you search for this on the Internets, you discover a problem. While 802.11 looks like Ethernet, there’s a critical difference in this case. Most access points won’t let clients speak with anything other than their own MAC address. If you’re two or more devices (the client and the devices wired to it), you have a problem, with a few ugly solutions:

If you’ve got a router at the front of your network that supports static routes, though, you’ve got a conceptually simpler option: build a wireless client router. This is still a lot of moving parts and things to go wrong, but those things are going to be more debuggable when they do.

Shopping list

Install and configure Raspbian Lite. Get your device connected via WiFi. (Side note: the ArchLinux wiki is really great).

Assign a static IPv4 address

Your wired side is going to need static addresses. These should be a different subnet than your existing private network. Strangely, in the new world, we configure static IPv4 addresses in /etc/dhcpcd.conf. Add a stanza that looks like:

interface eth0
 static ip_address=10.167.0.1/16
 nolink
 noipv6rs

Assign a static IPv6 address

You’ll need IPv6 addresses. These are going to be hard to keep in sync with IPv6 addresses on your main network; multi-level prefix delegation does not seem to be a thing yet, though that’s likely the future. In the meantime, set up unique local addresses so you can at least talk within your network. Go generate a unique local address block to start with. Take the first address from that network (network::1) and configure it, this time in /etc/network/interfaces:

auto eth0
iface eth0 inet6 static
  address fd28:ec48:8874:bd68::1
  netmask 64
  accept_ra 0
  autoconf 0
  privext 0

Really, don’t just use the address from this page; generate your own.

Enable router advertisements

sudo apt-get -y install radvd

Add a stanza to /etc/radvd.conf that looks like:

interface eth0
{
  AdvSendAdvert on;
  prefix fd28:ec48:8874:bd68::/64
  {
  };
  RDNSS 2001:4860:4860::8888 2001:4860:4860::8844
  {
  };
};

Enable IP forwarding

Edit /etc/sysctl.conf and uncomment the lines:

net.ipv4.ip_forward=1

net.ipv6.conf.all.forwarding=1

Set up a DHCP server

sudo apt-get -y install isc-dhcp-server

Edit /etc/default/isc-dhcp-server and set:

INTERFACES=”eth0"

Edit /etc/dhcp/dhcpd.conf, comment out the example junk, and add:

option domain-name-servers 8.8.8.8, 8.8.4.4;

subnet 10.167.0.0 netmask 255.255.0.0 {
  range 10.167.0.2 10.167.255.254;
  option routers 10.167.0.1;
}

Static IP and route

Now you need to assign a static IPv4 address to the wireless interface of the machine, and create static routes for both IPv4 and IPv6. You should do both of these in your primary router; Google for instructions. The examples below are for Cisco IOS, which is likely not very useful to you.

ip dhcp pool bridge2
 host 10.66.0.3 255.255.0.0
 client-identifier 0194.103e.7eba.f2

ip route 10.167.0.0 255.255.0.0 10.66.0.3

ipv6 route FD8B:CF21:31AC:69DF::/64 FD8B:CF21:31AC:A8CD:AD7F:4B19:EBD9:34CB

Reboot

Reboot your RPi to pick up all these changes.

Caveats

Because of the lack of multi-level prefix delegation, hosts behind your new router won’t have IPv6 connectivity to the world. Fingers crossed to fix this soon.

Linux doesn’t activate IPv6 addresses on interfaces until those interfaces come up and it can do duplicate address detection. This means that you won’t be able to ping the IPv6 addresses on eth0 until it’s plugged into something.