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>
95 lines
3.6 KiB
Scheme
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")))
|