about summary refs log tree commit diff homepage
path: root/blog/route.md
blob: 3f6d0cbc9c2e1bc16bda608bfce8e156116f77a7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
+++
rss = "How to set up an Ubuntu system as a router"
date = Date(2024, 8, 3)
tags = ["fun", "recipe", "net"]
+++

# GNU as a Router, the Canonical Way

A while ago I noticed that my ISP leases IPv4 addresses out indefinitely.
It was everything I'd ever wanted and I gotta seize it to truly _self_-host.
As an experiment, I started on something cheaper, like a single-board compooter.
In 2024, support for general-purpose RISC-V chips began to ripen, so naturally
due to FOMO, I bought a board with JH-7110.  Boy, was that a mistake!
While the bootloaders' support had been well [upstreamed],
certain essential features like PCIe (for NVMe) has yet to reached
a mainline Linux release, even worse so on the BSDs.  I ended up flashing
the _only_ distribution with official support [at the time][goatse], Ubuntu.

Funny enough, after over a decade of daily driving GNU, twas the first time
I installed Ubuntu on a machine of my own.  At the time of writing,
the reason for the was more apparent than ever: Canonical had been
forcing Snap[^snap] down the users' throat, even on the _server_ edition.
Thankfully Snap was still managed by APT and twas easy enough to remove
prevent it from coming back.  Another annoyance was the lack of manual pages
in the minimized installation _and_ that the official way to enable them
is through a script that also install other bloats SMFH (the script
is quite short and the actually necessary commands can be trivially found,
I'd rather they're documented instead).

That being said, not everything Ubuntu includes due to NIH is bad.
Unity (not the game engine that's proprietary like Snap server)
was loved by many; and this article is basically an appreciation post
for some others: [Netplan] and [ufw].  Before diving in,
lemme finish the story to give you the full context of this setup.
The SBC is the VisionFive 2 which is blessed with plenty of IO:

* 8 GB of memory
* 4 USB 3.0 type-A ports
* 2 RJ45 ports (1 Gb and 100/10 Mb)
* 1 M.2 slot (I used this as an excuse to buy a larger SSD
  and put the old 256 GB one here)
* 1 eMMC slot[^mmc] (eMMC are cheap, got one also with 256 GB)
* 1 TF slot
* 40 pin GP(and predefined-purpose)IO
* Other stuff for interfacing with humen like HDMI, audio jack, etc.

Initially, my plan for the SBC was to host services unlisted
on the [loang network].  Official services were not considered
because my home network has no IPv6 and sometimes I'll like
to have most of the bandwidth for meself.  Shortly afterwards,
I also purchased a somewhat beefy desktop compooter with even more I/O,
especially a bunch of SATA, which are a lot more attractive
than connecting hard di\*ks via USB.  On the other hand, the SBC barely
consume any electricity, well under 10 W with the NVMe drive, a Wi-Fi dongle
and a fan connected.  Since it cost virtually nothing to keep it up 24/7,
I decided to hand it the following two tasks:

* Reverse proxying services running on more powerful machines
  in the local network.
* Acting as a virtual router between nodes I manage.
  This is particularly useful for tunneling to my work network
  and accessing the servers, allowing me to work remotely with low latency.

Setting up the VPN with Wireguard was relatively easy, so I assumed swapping
the SBC for the home router couldn't be too hard.  Once again, I [chose poorly],
this little project'd costed me so many sleepless nights so I figured
I should note down what I learned here in case it can save someone else
from the same pain.  **Do not take inspiration from this!**

\toc

## Connecting to the Internet

My landlord handles the contract with the ISP so I don't know the details
of the subscription, but there's certainly no IPv6 nor any static IPv4 address.
Bandwidth to datacenters in the region is approximately 100 Mb/s
and the wall socket connects to a Cat 5e cable.  I know about the latter
because whatever dumb ass did the last maintenance wired that to another
short one dangling from the wall socket[^futa], and after getting stabbed
in the eyes for months I finally to open it up and made the socket
a proper socket.

It would not make the slightest of a difference but I connect
the SBC's 1 Gb port (identified in Ubuntu as end0) to the Internet
and the slower one (end1) to my desktop on the local network.
Thankfully no [special setup][router freedom] was needed
and here is the entire Netplan configuration to connect to the outside world:

```yaml
network:
  ethernets:
    end0:
      dhcp4: true
  renderer: networkd
  version: 2
```

## Local Networking

For simplicity's sake, I decided to use the same subnet for both Ethernet
and Wi-Fi under a bridge br0, where addressing and routing is configured:

```yaml
network:
  bridges:
    br0:
      addresses:
        - 192.168.147.254/25
      interfaces:
        - end1
      routes:
        - from: 192.168.147.128/25
          on-link: true
          to: 0.0.0.0/0
          type: nat
          via: 192.168.147.254
  ethernets:
    end1:
      dhcp4: false
```

As Netplan doesn't configure any DHCP server,
that's done separately by udhcpd from busybox:

```plaintext
interface br0
start 192.168.147.128
end 192.168.147.253
max_leases 126
option subnet 255.255.255.128
option router 192.168.147.254
```

I couldn't seem to get a concrete information on the ports used by DHCP
so I open the firewall for UDP on both 67 and 68 (I swear
this isn't an engagement bait to test out the new mailing list):

```plaintext
ufw allow in on br0 to any port 67 proto udp
ufw allow in on br0 to any port 68 proto udp
```

## Wireless Access Point

Thanks to systemd, the Wi-Fi dongle is recognized as wlx600dd0g8b33f.
Yes, that abomination of a name includes the chip's full MAC address.
That being said, I'd like to stick to the basis of a systemd/Linux distro.
Even though Netplan doesn't support Wi-Fi hotspot with systemd-networkd
but NetworkManager, so the interface had thus to be declared as Ethernet:

```yaml
network:
  bridges:
    br0:
      interfaces:
        - wlx600dd0g8b33f
  ethernets:
    wlx600dd0g8b33f:
      dhcp4: false
```

Actual wireless connectivity is handled by hostapd:

```ini
interface=wlx600dd0g8b33f
bridge=br0

ssid=
utf8_ssid=1
country_code=KR
channel=6
ieee80211d=1
ieee80211h=1
ieee80211n=1
hw_mode=g
wmm_enabled=1

wpa=2
wpa_pairwise=TKIP
wpa_passphrase=just enter random characters
```

## Name Resolution

My ISP is [known to be evil][KT malware] so I'd rather rely on more reputable
resolvers like [OpenNIC] (plus free-of-charge domain names!).  Most of their
[tier 2] are located on the other side of the globe (200 to 300 ms RTT),
so a local cache is almost required.  SmartDNS seems to be the best fit
for this purpose, as it queries upstream servers simultaneously
and also check for the IP with the lowest RTT among the results.
Since I don't trust my ISP, connections to the upstream servers are encrypted:

```plaintext
bind :53@br0
server-tls 51.254.162.59 -host-name ns1-dot.iriseden.fr
server-tls 202.61.197.122 -host-name dns.furrydns.de
server-tls 80.152.203.134 -host-name dot.kekew.info
server-tls 178.201.248.159 -host-name dot.kekew.info
server-tls 178.201.248.160 -host-name dot.kekew.info
server-tls 95.216.99.249 -host-name dns.froth.zone
```

For the router itself, the nameserver is set in /etc/resolv.conf
and Netplan is told not to change it:

```yaml
network:
  ethernets:
    end0:
      dhcp4-use-dns: false
```

After ufw is configured to allow UDP traffic in port 53 on br0,
udhcpd is instructed to advertise this local DNS server:

```plaintext
option dns 192.168.147.254
```

I might consider blocking ads at the domain-name level someday, but for now
uBlock Origin is working well enough on my systems and I rarely have
people over, especially not for looking at _their_ electronic devices.

[^snap]: Not [the good one][snap].
[^mmc]: Innovation's gone full circle, _eMMC_ is short for _embedded MMC_.
[^futa]: Basically a futanari of the RJ45 world.

[upstreamed]: https://rvspace.org/en/project/JH7110_Upstream_Plan
[goatse]: https://loa.loang.net/chung/D16T24MXDP3T.3BR1X04I90CGT@guix/t
[Netplan]: https://netplan.io
[ufw]: https://launchpad.net/ufw
[loang network]: https://loang.net
[chose poorly]: https://antifandom.com/how-i-met-your-mother/wiki/Knight_Vision
[snap]: http://snap.berkeley.edu
[router freedom]: https://docs.fsfe.org/en/teams/router-freedom-tech-wiki
[KT malware]: https://www.tomshardware.com/tech-industry/cyber-security/south-korean-telecom-company-attacks-torrent-users-with-malware-over-600000-people-report-missing-files-strange-folders-and-disabled-pcs
[OpenNIC]: https://opennic.org
[tier 2]: https://servers.opennic.org
[SmartDNS]: https://pymumu.github.io/smartdns/en