On one of my router7 installations, I’m using a bridge for uplink0
(so that I can use the built-in SFP interface, or fall back
to an external media converter in case of trouble without reconfig).
On that installation, I have observed the following bug:
1. System boots, netconfig creates uplink0.
2. The Linux kernel assigns a MAC address (e.g. ce:fa:ba:3c:66:84).
3. Netconfig cannot add the interfaces to the bridge yet,
presumably because they are not created yet.
4. The dhcp4 program starts and reads the MAC address.
5. Netconfig adds the interfaces to the bridge, the MAC changes.
6. dhcp4 still has the old (incorrect) MAC address.
7. dhcp4 never obtains a lease, the router never becomes healthy,
you’re stuck in this state.
This will be prevented by not letting the kernel assign a MAC address,
but instead determining the future MAC address (in our case:
we just use the first configured MAC address) and creating the bridge
interface correctly configured to begin with, thereby eliminating
the race condition entirely.
I suspect that Go’s net package reuses its buffers and these bytes don’t remain
valid forever (perhaps only if the network interfaces of the machine change?).
At least that would explain why my DHCP client sent requests with a wrong address.
The current behavior stomps on the rules that programs like
podman or tailscale set up for port forwarding.
With this change, we split port forwardings into a separate chain,
which allows us to create the ruleset once at startup and then only
update the port forwardings specifically (the only dynamic part
of router7’s nftables ruleset).
External ICMP does not necessarily work.
It typically does, but not always.
Last week, for a day or two, ICMP traffic was dropped by Google.
So now we use ICMP only for network equipment targets (default gateway),
and instead use TCP for external connectivity checks.
fixes#77
This has the advantage that it also works for static DHCP leases,
provided the device obtains a DHCP lease at all (and isn’t configured with a
static IP address, like the shelly motion sensors for example).
Thus far, we have only had forwarded bytes metrics.
Notably, forwarded bytes does not include bytes that were sent by the router
itself, e.g. by the webserver or rsync server running on the machine.
fixes https://github.com/rtr7/router7/issues/71
* internal/dhcp*: switch to github.com/mdlayher/packet
* internal/dhcp4d: update test constructor name to avoid packet conflict
Signed-off-by: Matt Layher <mdlayher@gmail.com>
Previously, a permanent error would not be persisted for future
invocations of ObtainOrRenew. In practice, the daemon immediately
exited, so this made no difference.
If upstreams were reordered between start of an upstream request and its
conclusion, the move-to-front operation would likely incorrectly reorder
upstreams: duplicate one and remove another. Instead, we abandon the
move-to-front operation if that was about to happen.
Previously SetHostname could operate on an expired lease, or even on a
lease for a different hwaddr, if the lease for the correct hwaddr
expired and the same lease ID was given away to someone else.
That's though mostly a theoretical concern, given the actual usage of
SetHostname and the time scales involved.
It is generally not a good idea to have multiple IP addresses on the same
interface unless managing their relative priorities via metrics etc.
During an outage, I noticed that with multiple IP addresses,
Linux was using the old obsolete one to send out packets,
which does not work with the ISP.
With this change,
we still hold on to IP addresses for as long as possible,
but no longer.
fixes issue #57