Files
ssmithxandClaude Opus 5.5 d968403d33 Hardening: key-only SSH, admin off TollGate's open SSID, sysctls
Both routers: sshd takes keys only (it is reachable from the open TollGate
SSID, and on the Pi from the WAN); shared %router-sysctls in router-base
(no ICMP redirects taken, loose rp_filter, kptr_restrict, BPF JIT hardened).

MT6000: the lab WAN SSH rule is gone; 99_zz-wired-private (a uci-defaults
script, after TollGate's setup) moves lan1-lan5 into TollGate's private
network (192.168.2.1), leaves br-lan to the open SSID, rejects SSH/telnet/
LuCI from it, trims nodogsplash's router ports, and turns on the private
network's DHCP, which TollGate's setup left disabled (PITFALLS #55).

The kernel has CONFIG_NFT_FLOW_OFFLOAD; fw4's offloading was measured and
is left off -- no gain at line rate, and it would let flows bypass
nodogsplash's session enforcement (PITFALLS #56).  Deployed as MT6000
generation 6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:25:38 -04:00

95 lines
3.6 KiB
Scheme

;;; Pieces both router systems (rpi4.scm, mt6000.scm) use.
(define-module (router-base)
#:use-module (gnu)
#:use-module (gnu services shepherd)
#:use-module (guix packages)
#:use-module (guix utils)
#:use-module ((gnu packages admin) #:select (shadow))
#:use-module ((gnu packages dns) #:select (dnsmasq))
#:use-module ((gnu packages ntp) #:select (chrony))
#:export (dnsmasq/cross-fixed
%chrony-accounts
%chrony-service
%router-root-account
%router-sysctls))
;; Guix 1.5.0's dnsmasq refers to `%output' in a phase, which is unbound in
;; cross builds (PITFALLS #23).
(define dnsmasq/cross-fixed
(package
(inherit dnsmasq)
(arguments
(substitute-keyword-arguments (package-arguments dnsmasq)
((#:phases phases)
`(modify-phases ,phases
(replace 'install-dbus
(lambda* (#:key outputs #:allow-other-keys)
(install-file "dbus/dnsmasq.conf"
(string-append (assoc-ref outputs "out")
"/etc/dbus-1/system.d"))))))))))
;; Time. No RTC: the clock starts at the last shutdown (sysfixtime) and the
;; WAN comes up later. chronyd's `makestep 1 -1' steps the clock whenever it
;; is off by > 1 s, at any time; ntpd/openntpd only step at startup and would
;; then slew. (ntp-service-type doesn't cross-build either, and 1.5.0 has no
;; chrony service: PITFALLS #29.)
(define %chrony.conf
(plain-file "chrony.conf" "\
pool pool.ntp.org iburst
makestep 1 -1
# No chronyc access (UDP command port, Unix socket); pid file in /run.
cmdport 0
bindcmdaddress /
pidfile /run/chronyd.pid
"))
(define %chrony-accounts
;; chronyd is built to drop root privileges to this user.
(simple-service 'chrony-accounts account-service-type
(list (user-group (name "chrony") (system? #t))
(user-account
(name "chrony")
(group "chrony")
(system? #t)
(comment "chronyd")
(home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin"))))))
(define %chrony-service
(simple-service 'chronyd shepherd-root-service-type
(list (shepherd-service
(documentation "Keep the clock in sync with chronyd.")
(provision '(chronyd))
(requirement '(user-processes networking))
(start #~(make-forkexec-constructor
(list #$(file-append chrony "/sbin/chronyd")
"-n" "-f" #$%chrony.conf)))
(stop #~(make-kill-destructor))))))
;; uid 0 replaces Guix's default (passwordless) root. Lab password "guix"
;; (hardening pass before real use).
(define %router-root-account
(user-account
(name "root")
(uid 0)
(group "root")
(comment "System administrator")
(home-directory "/root")
(password
"$6$nnmyfYtFSHLofLdC$KDdG0jRoBx20o701YQT2It087UhCmZZGMLm2WZ7SVmNx/gQ6GoMeKhU8DAxajmdgFsv4TiL2CUR/NNJAqfFyY0")))
;; Sysctls for both routers: forwarding, and hardening -- no ICMP redirects
;; taken (as OpenWrt's defaults; IPv6's were on), loose reverse-path
;; filtering (strict would break asymmetric/multi-WAN routing), kernel
;; pointers hidden, the BPF JIT hardened.
(define %router-sysctls
'(("net.ipv4.ip_forward" . "1")
("net.ipv4.conf.all.accept_redirects" . "0")
("net.ipv4.conf.default.accept_redirects" . "0")
("net.ipv6.conf.all.accept_redirects" . "0")
("net.ipv6.conf.default.accept_redirects" . "0")
("net.ipv4.conf.all.rp_filter" . "2")
("net.ipv4.conf.default.rp_filter" . "2")
("kernel.kptr_restrict" . "1")
("net.core.bpf_jit_harden" . "1")))