diff options
author | Himbeer <himbeerserverde@gmail.com> | 2024-02-17 17:20:11 +0100 |
---|---|---|
committer | Himbeer <himbeerserverde@gmail.com> | 2024-02-17 17:20:11 +0100 |
commit | 3a8bafb03a656dad9b782fcd7025f0da6e4aba99 (patch) | |
tree | a02975bb363130b6da6454f3b11a03d43aeac55f | |
parent | df78abfe26be621a19a9b716b7246f9fb90b84d4 (diff) |
update rsdsl article
-rw-r--r-- | static/md/rsdsl.md | 148 |
1 files changed, 111 insertions, 37 deletions
diff --git a/static/md/rsdsl.md b/static/md/rsdsl.md index 3afd12c..f2cf41e 100644 --- a/static/md/rsdsl.md +++ b/static/md/rsdsl.md @@ -63,14 +63,14 @@ Here's the core concept of how the components work together. | | | ^ V | V ip6 prefix | +--------+ ip4 +----------+ ip4 conf | -| pppoe2 | ----> | netlinkd |<------------+ +| pppoe3 | ----> | netlinkd |<------------+ +--------+ conf +----------+ | ^ | V ip4 addr | | +------+ | | -| 6in4 | ----------+ | ip6 conf -+------+ | - ^ | +| 6in4 | ----------+ | ip6 conf +----------+ ++------+ | | netdumpd | + ^ | +----------+ | V +-----+ +-------+ +------------+ | ntp | | radvd | | netfilterd | @@ -85,12 +85,13 @@ These are either background services or oneshot setup commands. Some of them are optional depending on the environment the router is used in and personal preference. -pppoe2 +pppoe3 ------ This is the second most important program running on the system. It is what connects to the outside world. -To do so it utilizes the PPPoE standard, only implementing a bare minimum. +To do so it utilizes the PPPoE standard, implementing most parts of the +main specification. PPP has a wide variety of authentication protocols to choose from, out of which this implementation supports CHAP-MD5 and PAP. With this ISP only CHAP is used in practice. @@ -102,15 +103,27 @@ A link-local native IPv6 connection is established using IPv6CP. Once connected the service creates a virtual network interface called `ppp0`. It lets the kernel handle the PPPoE encapsulation which surprisingly doesn't provide a significant performance boost compared to the old unoptimized -userspace implementation. It caps out at about 90 megabits per second -with an average of 80. This is acceptable for a 100/40 plan. +userspace implementation. It is capable of saturating a 100/40 Mbps plan. The client does not configure the interface or even bring it up on its own. -This is the responsibility of netlinkd. It does however write +This is the responsibility of [netlinkd](#netlinkd). It does however write the IP(v6)CP results to `/tmp/pppoe.ip_config` in a JSON format. -This includes the assigned address as well as the primary -and secondary DNS servers. The IPv6 information also contains -the link-local address of the ISP peer. Both sections are optional. +For IPv4, this includes the assigned address as well as the primary +and secondary DNS servers (which aren't used). +The IPv6 information contains the link-local addresses of the local and remote +peers. Both sections are optional: While dual-stack connections are preferred, +IPv4-only or IPv6-only connectivity is also supported (the software is going to +attempt to configure a tunnel for the other protocol, +either [DS-Lite](#dslite) or [6in4](#6in4)). + +The secondary `/data/pppoe.last` file holds the last results +and isn't cleared when one or both protocols get disconnected. +Its purpose is to re-request the same IPv4 address and IPv6 link-local address +every time. For IPv6 this is almost guaranteed to succeed whereas IPv4 +is highly dynamic which is likely a measure against address scarcity +or quick reassignment. Since the IPv6 address is link-local it's never going to +be rejected unless it collides with the ISP's link-local address +which only requires a single change due to the persistence file. To establish the connection the client uses a JSON configuration file located at `/data/pppoe.conf` containing the username and password @@ -133,11 +146,11 @@ link-local IPv6 address `fe80::1/64`. The kernel can potentially configure an additional EUI-64 based link-local address. It then waits for the WAN config to become available in the aforementioned `/tmp/pppoe.ip_config` file. It also monitors the file for changes -in case `pppoe2` reconnects. The public IPv4 address usually changes +in case [pppoe3](#pppoe3) reconnects. The public IPv4 address usually changes when reconnecting but it's somewhat inconsistent. -The local IPv6 link-local address of the WAN connection is always random -for the sake of simplicity, but making it static wouldn't provide any benefits -anyway. +The local IPv6 link-local address of the WAN connection is pseudo-static, +meaning it only changes if it collides with the ISP's link-local address +which is also static. The WAN interface is then configured with the public IPv4 address as a /32, assuming there is native IPv4 connectivity. @@ -147,17 +160,18 @@ In recent versions the routing has become much simpler. A single default route sends all traffic down the `ppp0` interface without a gateway. This is a point-to-point link after all. -If native IPv6 is available the link-local address if configured +If native IPv6 is available the link-local address is configured as a /64. A default route is also created. Just like the IPv4 route the IPv6 route doesn't use a gateway and instead relies on the interface alone. -Once `dhcp6` provides or updates its lease `netlinkd` picks it up -and subnets the prefix to as many /64s as it needs. +Once [dhcp6](#dhcp6) provides or updates its lease [netlinkd](#netlinkd) +picks it up and subnets the prefix to as many /64s as it needs. This is done sequentially rather than using the VLAN ID (or zero) as the subnet ID, allowing small prefixes (e.g. /61) to work -but I'd like to switch `6in4` and IPv4 to the same layout for consistency. +but I'd like to switch [6in4](#6in4) and IPv4 to the same layout +for consistency. The subnets are then assigned to the interfaces, reserving the first one -for the WAN side (instead of respecting a PD exclude hint if present). +for the WAN side (not respecting a PD exclude hint if present). The router has no other way to get clean IPv6 connectivity for itself since neither SLAAC nor DHCPv6 can be used to obtain a single WAN address. @@ -189,9 +203,9 @@ for the exact ruleset. Notably ICMP and ICMPv6 are always allowed for debugging purposes. IPv4 NAT is done on outbound traffic as normal. This does not apply to DS-Lite traffic since the AFTR is perfectly capable of -handling NAT for us as per RFC 6333. Avoiding double NAT helps reduce -the overhead introduced by such a carrier-grade NAT solution -and is comparable to IPv6 privacy wise. +handling NAT for us as per [RFC 6333](https://rfc-editor.org/rfc/rfc6333). +Avoiding double NAT helps reduce the overhead introduced by such a +carrier-grade NAT solution and is comparable to IPv6 privacy wise. This alone does make the IPv4 internet reachable but some services still won't work. @@ -214,7 +228,7 @@ interface the packet came from and the one it is routed to. Now all services should be reachable. This MSS clamping is applied to other WAN interfaces as well -so DS-Lite and 6in4 should work flawlessly too. +so [DS-Lite](#dslite) and [6in4](#6in4) should work flawlessly too. dhcp4d ------ @@ -236,6 +250,12 @@ the same client will usually end up with the same address every time even if it expired. Collisions are handled by generating a new address until no collisions are left. +Some IoT devices don't include a client ID in their requests +(for DHCPv4 this is RFC compliant). +To stay compatible with such clients `dhcp4d` uses `01:MAC_ADDRESS` +as the client ID if the option is missing. It uses the mandatory `chaddr` +field of the DHCP packets for this so no raw sockets are required. + The only gateway and DNS server advertised is the router itself. dhcp6 @@ -247,13 +267,23 @@ discovering a DS-Lite AFTR. This is where DHCPv6 comes into play. If a native IPv6 connection has been established this service requests a prefix delegation of size /56, the DNS servers and the AFTR name. -The result is written to `/tmp/dhcp6.lease` in a simple JSON format +The result is written to `/data/dhcp6.lease` in a simple JSON format but only two DNS servers are included in the file. +The DNS servers only get used for AFTR hostname queries +as those sometimes aren't available to public resolvers. The valid and preferred lifetimes are stored as well but not used as of now. The AFTR is optional. -The client automatically renews the lease after the time sent by the server -has passed. If this fails it starts over. +The client automatically renews and rebinds the lease after the timers +sent by the server has passed. If this fails it starts over. + +If the PPPoE session reconnects for any reason and the lease is still valid, +the client attempts to rebind the lease to get it routable again. +Usually the server replies with a force expiration (all timers set to 0) +but a resolicitation with a prefix hint for the last lease usually manages +to obtain the same prefix again (even if the lease has been expired +for a short amount of time). The IPv6 prefix is generally a lot more stable +than the IPv4 address. dnsd ---- @@ -266,15 +296,23 @@ for the hostname. If it finds a lease it reports it back to the client without ever forwarding the request to the hardcoded upstream server. The ISP provided nameservers are ignored for simplicity reasons. This program is fully capable of resolving AAAA records -and accepting IPv6 packets. The network design makes it impossible -to resolve local AAAA records though. +and accepting and forwarding IPv6 packets. +The network design makes it impossible to resolve local AAAA records though. ~~It also results in NXDOMAIN errors below the IPv4 address in nslookups -if no IPv6 addresses exist for a given hostname.~~ -Amazingly it doesn't add any measurable latency. +if no IPv6 addresses exist for a given hostname~~ (fixed). If a local hostname is present on multiple interfaces, the interface the request originated from is prioritised when choosing the response. +Amazingly it doesn't add any measurable latency. + +The DNS resolver uses two Do53 upstream resolvers. +They can be configured in the +[source code](https://git.himbeerserver.de/rsdsl/dnsd.git/tree/src/main.rs) +and are currently set to Quad9 IPv6 and IPv4. +The timeout for failed queries or fallback to the secondary upstream resolver +is 1 second. + dslite ------ @@ -325,13 +363,24 @@ would likely be possible too. ntp --- -Some services on the router (namely `6in4`) require a somewhat accurate -system clock in order to establish encrypted connections. +Some services on the router (namely [dhcp6](#dhcp6), [6in4](#6in4) +or external HTTPS clients like [dyndns-rs](https://git.himbeerserver.de/dyndns-rs.git/about/)) +require a somewhat accurate system clock in order to establish +encrypted connections. This simple NTP client waits for the PPPoE connection to come up and makes up to 3 attempts to get the time from a basic NTP server (no support for NTPv4 or SNTP). The fractional part is ignored for simplicity. If the unix epoch and the actual time are mixed in your logs this is why. +Since the Raspberry Pi 3B doesn't have a hardware clock +the current time is saved to `/data/ntp.last_unix` after (re)synchronization +or before system shutdown (SIGTERM). +The system clock is immediately set from disk (if available) on startup. + +This persistent storage (along with build timestamps as the default value) +also makes it possible to detect NTP era rollovers and keep working +after 2036. + 6in4 ---- @@ -370,6 +419,13 @@ This program also takes care of calling the update URL to inform HE of our current IPv4 address. It needs DNS resolution (see code) and NTP to work. +This program is no longer receiving true maintenance (though this may change +again) because it's only a workaround for ISPs that don't support native IPv6. +Transition technologies like this shouldn't be supported by default +to drive adoption of the new protocol. This is not to be confused +with backwards compatibility like [DS-Lite](#dslite) which is acceptable +(though it does come with major drawbacks for the end user). + radvd ----- @@ -377,8 +433,25 @@ Just like with IPv4 our client hosts need a way to get the IPv6 configuration. The most compatible and convenient way of achieving this is through SLAAC. This service periodically multicasts Router Advertisements (RA) to the local networks, advertising itself as the gateway and DNS server. -It also sends a multicast if it receives a Router Solicitation (RS) -from a connecting host. Unicast is not used here out of laziness. +It also sends a unicast if it receives a Router Solicitation (RS) +from a connecting host. + +netdumpd +-------- + +Sometimes a quick packet capture is invaluable for debugging +connectivity issues. This service captures important configuration protocols +on all interfaces, including ARP, DHCPv4, DHCPv6, SIP, ICMPv4, ICMPv6, +PPPoED (discovery stage) and PPP control protocols (LCP, authentication +and NCPs, but no data packets) and stores up to 256000 packets in a ring buffer. +You can connect to this service via SSH on port 22 +(only exposed to trusted networks) using the password stored in +`/data/admind.passwd`. You're going to get the entire contents +of the ring buffer (which covers about 2 days depending on the +number of clients) first, followed by real-time traffic. +The packet capture includes absolute timestamps and working time offsets +between packets, though the exact values of the time column in Wireshark +are somewhat unpredictable (which shouldn't be a problem). Interesting observations ======================== @@ -395,7 +468,8 @@ only the last octet is changed. ~~I don't know about IPv6 yet.~~ -The IPv6 prefix is similarly dynamic. +The IPv6 prefix is similarly dynamic by default, though [pppoe3](#pppoe3) +and [dhcp6](#dhcp6) manage to work around this quite well. IPv6 support ------------ |