summaryrefslogtreecommitdiff
path: root/src/wifi.thrust
diff options
context:
space:
mode:
authorEthel Morgan <eth@ethulhu.co.uk>2020-07-06 18:23:10 +0100
committerEthel Morgan <eth@ethulhu.co.uk>2020-07-06 18:23:10 +0100
commitb1e6491f77421ae4623391a7f53af7f3e6c13f34 (patch)
treeacc4ce7ae214b92dbf2c269c70e94b68dac1d640 /src/wifi.thrust
parent04be5845dbaa6f8dec45a80dbe199861608b96f2 (diff)
import website from previous repo
Diffstat (limited to '')
-rw-r--r--src/wifi.thrust350
1 files changed, 350 insertions, 0 deletions
diff --git a/src/wifi.thrust b/src/wifi.thrust
new file mode 100644
index 0000000..26cbdc7
--- /dev/null
+++ b/src/wifi.thrust
@@ -0,0 +1,350 @@
+---
+title: home WiFi setup
+configs:
+ router:
+ /etc/systemd/network/wan.network: |
+ [Match]
+ # enp1s0 is the name of my router's WAN interface.
+ Name=enp1s0
+
+ [Network]
+ # take a IP from my ISP's modem over DHCP.
+ DHCP=yes
+
+ # use Google's public DNS servers.
+ DNS=8.8.8.8
+ DNS=8.8.4.4
+
+ # prefer DNS-over-TLS if available.
+ DNSOverTLS=opportunistic
+
+ # forward packets from this interface to other interfaces.
+ IPForward=yes
+
+ [DHCP]
+ # some ISPs' DNS invent A records, so don't use them.
+ UseDNS=no
+
+ /etc/systemd/network/bridge.netdev: |
+ [NetDev]
+ Name=br0
+ Kind=bridge
+
+ /etc/systemd/network/lan.network: |
+ [Match]
+ Name=enp2s0 enp3s0
+
+ [Network]
+ Bridge=br0
+
+ /etc/systemd/network/bridge.network: |
+ [Match]
+ Name=br0
+
+ [Network]
+ # the router's LAN IP.
+ Address=192.168.16.1/24
+
+ # run a DHCP server.
+ DHCPServer=yes
+
+ # forward packets from this interface to other interfaces.
+ IPForward=yes
+
+ # make forwarded packets appear to come from this device,
+ # a.k.a. enable NAT.
+ IPMasquerade=yes
+
+ [DHCPServer]
+ DefaultLeaseTimeSec=600
+
+ # LAN DNS & Stubby DNS-over-TLS bridge.
+ DNS=192.168.16.1
+
+ # fallback DNS.
+ DNS=8.8.8.8
+ DNS=8.8.4.4
+
+ bouncer:
+ /etc/systemd/network/bridge.netdev: |
+ [NetDev]
+ Name=br0
+ Kind=bridge
+
+ /etc/systemd/network/wired.network: |
+ [Match]
+ Name=eth0
+
+ [Network]
+ Bridge=br0
+
+ /etc/systemd/network/bridge.network: |
+ [Match]
+ Name=br0
+
+ [Network]
+ DHCP=yes
+ DNSOverTLS=opportunistic
+
+ shared:
+ /etc/hostapd/hostapd.conf: |
+ bridge=br0
+ interface=wlan0
+ driver=nl80211
+ ssid=something-witty
+
+ # select a channel automatically
+ # using the ACS survey-based algorithm,
+ # instead of setting a channel manually.
+ channel=0
+ country_code=GB
+ ieee80211d=1
+
+ # hw_mode=g for 802.11n, hw_mode=a for 802.11ac.
+ hw_mode=g
+
+ # 802.11n support.
+ ieee80211n=1
+ wmm_enabled=1
+
+ # WPA2 encryption settings.
+ # note that wpa_key_mgmt also has FT-PSK for 802.11r.
+ wpa=2
+ wpa_passphrase=something-secret
+ wpa_key_mgmt=WPA-PSK FT-PSK
+ wpa_pairwise=TKIP
+ rsn_pairwise=CCMP
+
+ # 802.11i support.
+ rsn_preauth=1
+ rsn_preauth_interfaces=br0
+
+ # 802.11r support.
+ # mobility_domain must be shared across APs.
+ # nas_identifier must be different between APs.
+ mobility_domain=19fc
+ nas_identifier=8e71540f0467
+ ft_psk_generate_local=1
+diagram: |
+ <svg xmlns='http://www.w3.org/2000/svg'
+ viewBox='0.00 0.00 466.59 106.00'
+ width='467pt' height='106pt'
+ style='font-family: "Times New Roman", Times, serif; font-size: 12pt; font-weight: lighter;'>
+ <g id='graph0' class='graph' transform='scale(1 1) rotate(0) translate(4 102)'>
+ <title>home network diagram</title>
+ <g id='home-network-diagram/internet' class='node'>
+ <title>internet</title>
+ <polygon fill='none' points='43.19,-8.05 45.61,-8.15 48.01,-8.3 50.37,-8.49 52.69,-8.74 54.96,-9.03 57.16,-9.36 59.29,-9.75 61.34,-10.18 63.31,-10.65 65.18,-11.16 66.95,-11.71 68.61,-12.31 70.17,-12.94 71.6,-13.61 72.92,-14.31 74.11,-15.04 75.18,-15.8 76.11,-16.59 76.92,-17.41 77.6,-18.25 78.15,-19.11 78.57,-19.99 78.87,-20.89 79.04,-21.8 79.08,-22.72 79.01,-23.65 78.81,-24.59 78.51,-25.53 78.1,-26.47 77.58,-27.41 76.96,-28.35 76.25,-29.28 75.46,-30.2 74.57,-31.11 73.61,-32.01 72.58,-32.89 71.47,-33.75 70.31,-34.59 69.09,-35.41 67.81,-36.2 66.49,-36.96 65.13,-37.69 63.73,-38.39 62.29,-39.06 60.83,-39.69 59.33,-40.29 57.82,-40.84 56.28,-41.35 54.73,-41.82 53.16,-42.25 51.58,-42.64 49.99,-42.97 48.4,-43.26 46.79,-43.51 45.18,-43.7 43.57,-43.85 41.95,-43.95 40.34,-44 38.72,-44 37.1,-43.95 35.48,-43.85 33.87,-43.7 32.26,-43.51 30.66,-43.26 29.06,-42.97 27.47,-42.64 25.89,-42.25 24.32,-41.82 22.77,-41.35 21.24,-40.84 19.72,-40.29 18.23,-39.69 16.76,-39.06 15.33,-38.39 13.92,-37.69 12.56,-36.96 11.24,-36.2 9.97,-35.41 8.74,-34.59 7.58,-33.75 6.48,-32.89 5.44,-32.01 4.48,-31.11 3.6,-30.2 2.8,-29.28 2.09,-28.35 1.47,-27.41 0.96,-26.47 0.54,-25.53 0.24,-24.59 0.05,-23.65 -0.03,-22.72 0.02,-21.8 0.19,-20.89 0.48,-19.99 0.9,-19.11 1.45,-18.25 2.13,-17.41 2.94,-16.59 3.88,-15.8 4.94,-15.04 6.14,-14.31 7.45,-13.61 8.89,-12.94 10.44,-12.31 12.1,-11.71 13.88,-11.16 15.75,-10.65 17.71,-10.18 19.76,-9.75 21.89,-9.36 24.1,-9.03 26.36,-8.74 28.68,-8.49 31.05,-8.3 33.44,-8.15 35.87,-8.05 38.31,-8 40.75,-8 43.19,-8.05'/>
+ <text text-anchor='middle' x='39.53' y='-21.8'>internet</text>
+ </g>
+ <g id='home-network-diagram/router' class='node'>
+ <title>router</title>
+ <polygon fill='none' points='170.05,-44 116.05,-44 116.05,-8 170.05,-8 170.05,-44'/>
+ <text text-anchor='middle' x='143.05' y='-21.8'>router</text>
+ </g>
+ <g id='edge1' class='edge'>
+ <title>internet -- router</title>
+ <path fill='none' d='M78.33,-26C90.85,-26 104.49,-26 115.93,-26'/>
+ </g>
+ <g id='node3' class='node'>
+ <title>kitchen</title>
+ <polygon fill='none' points='327.91,-78 270.49,-78 270.49,-42 327.91,-42 327.91,-78'/>
+ <text text-anchor='middle' x='299.2' y='-55.8'>kitchen</text>
+ </g>
+ <g id='edge2' class='edge'>
+ <title>router -- kitchen</title>
+ <path d='M170.2,-31.77C198.03,-37.91 241.9,-47.58 270.36,-53.86'/>
+ <text text-anchor='middle' x='220.33' y='-51.8'>powerline</text>
+ </g>
+ <g id='node4' class='node'>
+ <title>laptop</title>
+ <text text-anchor='middle' x='425.31' y='-13.8'>laptop</text>
+ </g>
+ <g id='edge3' class='edge'>
+ <title>router -- laptop</title>
+ <path fill='none' stroke-dasharray='5,2' d='M170.21,-24.18C195.79,-22.49 235.85,-20.07 270.6,-19 315.41,-17.62 367.61,-17.62 398.19,-17.78'/>
+ <text text-anchor='middle' x='299.2' y='-21.8'>WiFi</text>
+ </g>
+ <g id='edge4' class='edge'>
+ <title>kitchen -- laptop</title>
+ <path stroke-dasharray='5,2' d='M328.05,-50.57C349.07,-43.46 377.69,-33.78 398.25,-26.82'/>
+ <text text-anchor='middle' x='359.92' y='-45.8'>WiFi</text>
+ </g>
+ <g id='node5' class='node'>
+ <title>bulb</title>
+ <text text-anchor='middle' x='425.31' y='-75.8'>lightbulb</text>
+ </g>
+ <g id='edge5' class='edge'>
+ <title>kitchen -- bulb</title>
+ <path stroke-dasharray='5,2' d='M328.05,-64.49C347.06,-67.55 372.3,-71.62 392.17,-74.82'/>
+ <text text-anchor='middle' x='359.92' y='-73.8'>WiFi</text>
+ </g>
+ </g>
+ </svg>
+---
+{% extends 'templates/base.html' %}
+{% block body %}
+ <nav>
+ <a href='/projects'>&gt; projects</a>
+ </nav>
+
+
+ <article>
+ <h1>{{ title }}</h1>
+
+{% macro file(d, path) %}
+<pre><code>$ cat {{ path }}
+{{ d[path] }}</code></pre>
+{% endmacro %}
+
+{% markdown %}
+<details markdown='1'>
+<summary>contents…</summary>
+<div markdown='block'>
+
+[TOC]
+
+</div>
+</details>
+
+There are two Access Points (APs) in my house: one in the living room, and one in the kitchen.
+They are connected via LAN-over-powerline, and have WiFi Roaming set up for a seamless connection throughout.
+
+{{ diagram | safe }}
+
+## Roaming
+
+WiFi Roaming allows a client device (e.g. a phone) to transparently switch from one AP to another.
+Unlike "repeaters" or "boosters", which create a second WiFi network that the client needs to disconnect from and reconnect to, Roaming is _the same network_ across APs and allows for a seamless experience.
+
+This is implemented with two extensions of the WiFi spec, _802.11i_ and _802.11r_:
+
+- _802.11i_ is pre-authentication, which allows clients to start associating to a new AP while still connected to the previous one.
+- _802.11r_ is Fast Transition (FT), where APs can share keys with each other.
+ On large networks (e.g. corporate ones) this is done properly where the APs communicate and use intermediate keys and the like, but for a home network with a Pre-Shared Key (PSK), the APs can derive all the keys themselves.
+
+<details markdown='1'>
+<summary>How does 802.11r actually work?</summary>
+<div markdown='block'>
+In a given roaming connection, there are 3 keys:
+
+- Master Session Key (MSK).
+- R0, a key derived from the MSK.
+- R1, a key derived from R0.
+
+There are 3 players:
+
+- The client.
+- R0KH, the R0 Key Handler, may or may not be an AP.
+- R1KH, the R1 Key Handler, an AP.
+
+In "pull mode":
+
+1. The client connects to the first AP.
+2. The client is given a key and an R0KH-ID (the _NAS Identifier_, named for [RADIUS'](https://en.wikipedia.org/wiki/RADIUS) [Network Access Server](https://en.wikipedia.org/wiki/Network_access_server)).
+3. The client connects to the second AP.
+4. The client gives R0KH-ID to the second AP.
+5. The second AP, now R1KH, contacts R0KH using the ID and its own R1KH-ID.
+6. R0KH sends R1KH a key R1 derived from R0 and R1KH-ID.
+7. R1KH, gives the client R1.
+
+In "push mode":
+
+1. R0KH knows all its APs.
+2. R0KH sends each AP a unique R1 derived from R0 and the AP's R1KH-ID.
+3. the client connects normally.
+
+For PSK mode, the MSK is the PSK, so any AP can generate R0 and R1 for any NAS Identifier.
+</div>
+</details>
+
+## Router configuration { #router }
+
+My router is a [PC Engines APU 1d4](https://www.pcengines.ch/apu1d4.htm), which has:
+
+- 3 ethernet ports.
+- 1 wifi card.
+
+One of the ethernet ports is for WAN, and the other two and wifi card are LAN.
+The LAN interfaces are joined with a bridge, `br0`.
+
+### WAN { #router/wan }
+
+This is a fairly normal [`systemd-networkd`](https://wiki.archlinux.org/index.php/Systemd-networkd) client config, with the addition of `IPForward=yes`:
+
+{{ file( configs.router, '/etc/systemd/network/wan.network' ) }}
+
+### LAN { #router/lan }
+
+The LAN is controlled with `systemd-networkd` where possible, and the wifi is managed by `hostapd`.
+There are three parts to the `networkd` configuration:
+
+- Create a bridge network device.
+- Connect the LAN ethernet ports to it.
+- Configure the bridge to be a DHCP server & NAT gateway.
+
+First, create a bridge `br0`:
+
+{{ file( configs.router, '/etc/systemd/network/bridge.netdev' ) }}
+
+Connect the LAN ethernet ports to the bridge:
+
+{{ file( configs.router, '/etc/systemd/network/lan.network' ) }}
+
+Finally, configure the local network on the bridge itself.
+
+- `systemd-networkd` includes a minimal DHCP server, so also enable that.
+- Note the addition of both `IPForward=yes` and `IPMasquerade=yes` to set up NAT.
+
+{{ file( configs.router, '/etc/systemd/network/bridge.network' ) }}
+
+### WiFi { #router/wifi }
+
+Because `hostapd` has its own bridge management, it isn't included in the `systemd-networkd` configuration.
+
+This configuration:
+
+- Uses our bridge `br0`.
+- Uses the standard Linux WiFi driver set (others exist for other chipsets).
+- Automatically selects a channel at start.
+- Enables 802.11n (`hostapd` also supports 802.11ac).
+- Enables WPA2 with a Pre-Shared Key (PSK).
+- Enables pre-authentication (802.11i) on our bridge `br0`.
+- Enables roaming (802.11r):
+ - `nas_identifier` must be 6 bytes, and different between APs. I use the interface MAC.
+ - `mobility_domain` must be 2 bytes, and is shared between APs.
+
+{{ file( configs.shared, '/etc/hostapd/hostapd.conf' ) }}
+
+## Kitchen
+
+The WiFi in the kitchen is provided by a [Raspberry Pi 2B](https://www.raspberrypi.org/products/raspberry-pi-2-model-b/) and a USB WiFi adapter that supports _host mode_.
+I chose this hardware because I already owned it.
+
+### LAN { #kitchen/lan }
+
+This is a simpler version of the [Router's LAN configuration](#router/lan), but with only two steps:
+
+- Create a bridge network device.
+- Connect the LAN ethernet ports to it.
+
+As before, create a bridge `br0`:
+
+{{ file( configs.bouncer, '/etc/systemd/network/bridge.netdev' ) }}
+
+Connect the ethernet port to the bridge:
+
+{{ file( configs.bouncer, '/etc/systemd/network/wired.network' ) }}
+
+Configure the local network on the bridge itself.
+Because this is not the primary router, it can be just another DHCP client:
+
+{{ file( configs.bouncer, '/etc/systemd/network/bridge.network' ) }}
+
+
+### WiFi { #kitchen/wifi }
+
+This is basically the same as the [Router's WiFi configuration](#router/wifi), although remember to change the `nas_identifier`!
+{% endmarkdown %}
+ </article>
+{% endblock %}