rtr7 / router7
- понедельник, 16 июля 2018 г. в 13:10:02
Go
pure-Go small home internet router
router7 is a pure-Go implementation of a small home internet router. It comes with all the services required to make a fiber7 internet connection work (DHCPv4, DHCPv6, DNS, etc.).
Note that this project should be considered a (working!) tech demo. Feature requests will likely not be implemented, and see CONTRIBUTING.md for details about which contributions are welcome.
Before starting router7, I was using the Turris Omnia router running OpenWrt. That worked fine up until May 2018, when an automated update pulled in a new version of odhcp6c, OpenWrt’s DHCPv6 client. That version is incompatible with fiber7’s DHCP server setup (I think there are shortcomings on both sides).
It was not only quicker to develop my own router than to wait for either side to resolve the issue, but it was also a lot of fun and allowed me to really tailor my router to my needs, experimenting with a bunch of interesting ideas I had.
/perm
partition and can be modified.The reference hardware platform is the PC Engines™ apu2c4 system board. It features a 1 GHz quad core amd64 CPU, 4 GB of RAM, 3 Ethernet ports and a DB9 serial port. It conveniently supports PXE boot, the schematics and bootloader sources are available. I recommend the msata16g SSD module for reliable persistent storage and the usbcom1a serial adapter if you don’t have one already.
Other hardware might work, too, but is not tested.
The cheap and widely-available Teensy++ USB development board comes with a firmware called rebootor, which is used by the teensy_loader_cli
program to perform hard resets.
This setup can be used to programmatically reset the apu2c4 (from rtr7-recover
) by connecting the Teensy++ to the apu2c4’s reset pins:
GND
pin to the apu2c4 J2’s pin 4 (GND
)B7
pin to the apu2c4 J2’s pin 5 (3.3V
, resets when pulled to GND
)You can find a working rebootor firmware .hex file at https://github.com/PaulStoffregen/teensy_loader_cli/issues/38
router7 is based on gokrazy: it is an appliance which gets packed into a hard disk image, containing a FAT partition with the kernel, a read-only SquashFS partition for the root file system and an ext4 partition for permanent data.
The individual services can be found in github.com/rtr7/router7/cmd.
cmd/dhcp4
writes /perm/dhcp4/wire/lease.json
.SIGUSR1
.File | Consumer(s) | Purpose |
---|---|---|
/perm/interfaces.json |
netconfigd |
Set IP/MAC addresses of uplink0 and lan0 |
/perm/portforwardings.json |
netconfigd |
Configure nftables port forwarding rules |
/perm/dhcp6/duid |
dhcp6 |
Set DHCP Unique Identifier (DUID) for obtaining static leases |
File | Producer | Consumer(s) | Purpose |
---|---|---|---|
/perm/dhcp4/wire/ack |
dhcp4 |
dhcp4 |
last DHCPACK packet for renewals across restarts |
/perm/dhcp4/wire/lease.json |
dhcp4 |
netconfigd |
Obtained DHCPv4 lease |
/perm/dhcp6/wire/lease.json |
dhcp6 |
netconfigd |
Obtained DHCPv6 lease |
/perm/dhcp4d/leases.json |
dhcp4d |
dhcp4d , dnsd |
DHCPv4 leases handed out (including hostnames) |
Port | Purpose |
---|---|
<public>:8053 |
dnsd metrics (forwarded requests) |
<public>:8066 |
netconfigd metrics (nftables counters) |
<private>:80 |
gokrazy web interface |
<private>:67 |
dhcp4d |
<private>:58 |
radvd |
<private>:53 |
dnsd |
<private>:8077 |
backupd (serve backup.tar.gz) |
<private>:7733 |
diagd (perform diagnostics) |
<private>:5022 |
captured (serve captured packets) |
Here’s an example of the diagd output:
Here’s an example of the metrics when scraped with Prometheus and displayed in Grafana:
Connect your serial adapter (usbcom1a works well if you don’t have one already) to the apu2c4 and start a program to use it, e.g. screen /dev/ttyUSB0 115200
. Then, power on the apu2c4 and configure it to do PXE boot:
F10
to enter the boot menu3
to enter setupn
to enable network bootc
to move mSATA to the top of the boot ordere
to move iPXE to the top of the boot orders
to save configuration and exitConnect a network cable on net0
, the port closest to the serial console port:
Next, build a router7 image:
go get -u github.com/gokrazy/tools/cmd/gokr-packer
go get -u -d github.com/rtr7/router7
mkdir /tmp/recovery
GOARCH=amd64 gokr-packer \
-hostname=router7 \
-overwrite_boot=/tmp/recovery/boot.img \
-overwrite_mbr=/tmp/recovery/mbr.img \
-overwrite_root=/tmp/recovery/root.img \
-kernel_package=github.com/rtr7/kernel \
-firmware_package=github.com/rtr7/kernel \
-gokrazy_pkgs=github.com/gokrazy/gokrazy/cmd/ntp \
-serial_console=ttyS0,115200n8 \
github.com/rtr7/router7/cmd/...
Run rtr7-recover -boot=/tmp/recovery/boot.img -mbr=/tmp/recovery/mbr.img -root=/tmp/recovery/root.img
to:
Run e.g. rtr7-safe-update -updates_dir=$HOME/router7/updates
to:
/perm
rtr7-recover
otherwiseThe update step uses kexec to reduce the downtime to approximately 15 seconds.
Given rtr7-safe-update
’s safeguards, manual recovery should rarely be required.
To manually roll back to an older image, invoke rtr7-safe-update
via the
recover.bash
script in the image directory underneath -updates_dir
, e.g.:
% cd ~/router7/updates/2018-07-03T17:33:52+02:00
% ./recover.bash