summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Cournoyer <maxim.cournoyer@gmail.com>2025-05-10 22:54:19 +0900
committerMaxim Cournoyer <maxim.cournoyer@gmail.com>2025-05-26 13:43:28 +0900
commitcfa2de2a77df3876061c8d26c104d2ebbae2631b (patch)
tree85f0a654fe923bd39d1705939b00bc023a0236c8
parent8c5be5f31c6181eb71212f055b6dad216b5f60f4 (diff)
services: Modernize and test nftables service.
* doc/guix.texi (Networking Services) <nftables>: Update doc. * gnu/services/networking.scm (list-of-debug-levels?): (debug-level?, maybe-list-of-debug-levels?): (nftables-configuration): Rewrite using `define-configuration'. [debug-levels]: New field. (nftables-shepherd-service): Honor it. * gnu/tests/networking.scm (%inetd-echo-port): Extract to top level. (run-iptables-test): Adjust accordingly. (make-nftables-os): New procedure. (%default-nftables-ruleset-for-tests): New variable. (%nftables-os): Likewise. (%test-nftables): New test. Change-Id: I2889603342ff6d2be6261c3de6e4fddd9a9bbe2d
-rw-r--r--doc/guix.texi40
-rw-r--r--gnu/services/networking.scm49
-rw-r--r--gnu/tests/networking.scm113
3 files changed, 172 insertions, 30 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 65c64f022ef..d69e6ed215b 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -22632,32 +22632,48 @@ objects}).
22632@end deftp 22632@end deftp
22633 22633
22634@cindex nftables 22634@cindex nftables
22635@cindex firewall, nftables
22635@defvar nftables-service-type 22636@defvar nftables-service-type
22636This is the service type to set up a nftables configuration. nftables is a 22637This is the service type to set up a nftables configuration. nftables
22637netfilter project that aims to replace the existing iptables, ip6tables, 22638is a netfilter project that aims to replace the iptables, ip6tables,
22638arptables and ebtables framework. It provides a new packet filtering 22639arptables and ebtables framework. It provides a new packet filtering
22639framework, a new user-space utility @command{nft}, and a compatibility layer 22640framework, a new user-space utility @command{nft}, and a compatibility
22640for iptables. This service comes with a default ruleset 22641layer for iptables. This service comes with a default ruleset,
22641@code{%default-nftables-ruleset} that rejecting all incoming connections 22642@code{%default-nftables-ruleset}, that rejects all incoming connections
22642except those to the ssh port 22. To use it, simply write: 22643except those to the SSH port 22 (TCP). To use it, simply write:
22643 22644
22644@lisp 22645@lisp
22645(service nftables-service-type) 22646(service nftables-service-type)
22646@end lisp 22647@end lisp
22647@end defvar 22648@end defvar
22648 22649
22650@c %start of fragment
22651
22649@deftp {Data Type} nftables-configuration 22652@deftp {Data Type} nftables-configuration
22650The data type representing the configuration of nftables. 22653Available @code{nftables-configuration} fields are:
22651 22654
22652@table @asis 22655@table @asis
22653@item @code{package} (default: @code{nftables}) 22656@item @code{package} (default: @code{nftables}) (type: file-like)
22654The nftables package that provides @command{nft}. 22657The @code{nftables} package to use.
22655@item @code{ruleset} (default: @code{%default-nftables-ruleset}) 22658
22656The nftables ruleset to use. This may be any ``file-like'' object 22659@item @code{debug-levels} (type: maybe-list-of-debug-levels)
22657(@pxref{G-Expressions, file-like objects}). 22660A list of debug levels, for enabling debugging output. Valid debug
22661level values are the @samp{scanner}, @samp{parser}, @samp{eval},
22662@samp{netlink}, @samp{mnl}, @samp{proto-ctx}, @samp{segtree} or
22663@samp{all} symbols.
22664
22665@item @code{ruleset} (type: file-like)
22666A file-like object containing the complete nftables ruleset. The
22667default ruleset rejects all incoming connections except those to TCP
22668port 22, with connections from the loopback interface are allowed.
22669
22658@end table 22670@end table
22671
22659@end deftp 22672@end deftp
22660 22673
22674
22675@c %end of fragment
22676
22661@cindex NTP (Network Time Protocol), service 22677@cindex NTP (Network Time Protocol), service
22662@cindex ntpd, service for the Network Time Protocol daemon 22678@cindex ntpd, service for the Network Time Protocol daemon
22663@cindex real time clock 22679@cindex real time clock
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index 67653e2cbf5..8b7bf668927 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -10,7 +10,7 @@
10;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com> 10;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
11;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net> 11;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
12;;; Copyright © 2019 Florian Pelz <pelzflorian@pelzflorian.de> 12;;; Copyright © 2019 Florian Pelz <pelzflorian@pelzflorian.de>
13;;; Copyright © 2019, 2021, 2024 Maxim Cournoyer <maxim.cournoyer@gmail.com> 13;;; Copyright © 2019, 2021, 2024, 2025 Maxim Cournoyer <maxim.cournoyer@gmail.com>
14;;; Copyright © 2019 Sou Bunnbu <iyzsong@member.fsf.org> 14;;; Copyright © 2019 Sou Bunnbu <iyzsong@member.fsf.org>
15;;; Copyright © 2019 Alex Griffin <a@ajgrf.com> 15;;; Copyright © 2019 Alex Griffin <a@ajgrf.com>
16;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re> 16;;; Copyright © 2020 Brice Waegeneire <brice@waegenei.re>
@@ -80,6 +80,7 @@
80 #:use-module (srfi srfi-9) 80 #:use-module (srfi srfi-9)
81 #:use-module (srfi srfi-26) 81 #:use-module (srfi srfi-26)
82 #:use-module (srfi srfi-43) 82 #:use-module (srfi srfi-43)
83 #:use-module (ice-9 format)
83 #:use-module (ice-9 match) 84 #:use-module (ice-9 match)
84 #:use-module (ice-9 string-fun) 85 #:use-module (ice-9 string-fun)
85 #:use-module (json) 86 #:use-module (json)
@@ -258,6 +259,7 @@
258 nftables-configuration 259 nftables-configuration
259 nftables-configuration? 260 nftables-configuration?
260 nftables-configuration-package 261 nftables-configuration-package
262 nftables-configuration-debug-levels
261 nftables-configuration-ruleset 263 nftables-configuration-ruleset
262 %default-nftables-ruleset 264 %default-nftables-ruleset
263 265
@@ -2279,12 +2281,12 @@ COMMIT
2279 (compose list iptables-shepherd-service)))))) 2281 (compose list iptables-shepherd-service))))))
2280 2282
2281;;; 2283;;;
2282;;; nftables 2284;;; nftables.
2283;;; 2285;;;
2284 2286
2285(define %default-nftables-ruleset 2287(define %default-nftables-ruleset
2286 (plain-file "nftables.conf" 2288 (plain-file "nftables.conf" "\
2287 "# A simple and safe firewall 2289# A simple and safe firewall
2288table inet filter { 2290table inet filter {
2289 chain input { 2291 chain input {
2290 type filter hook input priority 0; policy drop; 2292 type filter hook input priority 0; policy drop;
@@ -2320,25 +2322,44 @@ table inet filter {
2320} 2322}
2321")) 2323"))
2322 2324
2323(define-record-type* <nftables-configuration> 2325(define (debug-level? x)
2324 nftables-configuration 2326 (member x '(scanner parser eval netlink mnl proto-ctx segtree all)))
2325 make-nftables-configuration 2327
2326 nftables-configuration? 2328(define list-of-debug-levels?
2327 (package nftables-configuration-package 2329 (list-of debug-level?))
2328 (default nftables)) 2330
2329 (ruleset nftables-configuration-ruleset ; file-like object 2331(define-maybe/no-serialization list-of-debug-levels)
2330 (default %default-nftables-ruleset))) 2332
2333(define-configuration/no-serialization nftables-configuration
2334 (package
2335 (file-like nftables)
2336 "The @code{nftables} package to use.")
2337 (debug-levels
2338 maybe-list-of-debug-levels
2339 "A list of debug levels, for enabling debugging output. Valid debug level values
2340are the @samp{scanner}, @samp{parser}, @samp{eval}, @samp{netlink},
2341@samp{mnl}, @samp{proto-ctx}, @samp{segtree} or @samp{all} symbols.")
2342 (ruleset
2343 (file-like %default-nftables-ruleset)
2344 "A file-like object containing the complete nftables ruleset. The default
2345ruleset rejects all incoming connections except those to TCP port 22, with
2346connections from the loopback interface are allowed."))
2331 2347
2332(define (nftables-shepherd-service config) 2348(define (nftables-shepherd-service config)
2333 (match-record config <nftables-configuration> 2349 (match-record config <nftables-configuration>
2334 (package ruleset) 2350 (package debug-levels ruleset)
2335 (let ((nft (file-append package "/sbin/nft"))) 2351 (let ((nft (file-append package "/sbin/nft")))
2336 (shepherd-service 2352 (shepherd-service
2337 (documentation "Packet filtering and classification") 2353 (documentation "Packet filtering and classification")
2338 (actions (list (shepherd-configuration-action ruleset))) 2354 (actions (list (shepherd-configuration-action ruleset)))
2339 (provision '(nftables)) 2355 (provision '(nftables))
2340 (start #~(lambda _ 2356 (start #~(lambda _
2341 (invoke #$nft "--file" #$ruleset))) 2357 (invoke #$nft
2358 #$@(if (maybe-value-set? debug-levels)
2359 (list (format #f "--debug=~{~a~^,~}"
2360 debug-levels))
2361 #~())
2362 "--file" #$ruleset)))
2342 (stop #~(lambda _ 2363 (stop #~(lambda _
2343 (invoke #$nft "flush" "ruleset"))))))) 2364 (invoke #$nft "flush" "ruleset")))))))
2344 2365
diff --git a/gnu/tests/networking.scm b/gnu/tests/networking.scm
index 25f61034c66..2865e6ff350 100644
--- a/gnu/tests/networking.scm
+++ b/gnu/tests/networking.scm
@@ -5,6 +5,7 @@
5;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net> 5;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
6;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be> 6;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
7;;; Copyright © 2021, 2023-2024 Ludovic Courtès <ludo@gnu.org> 7;;; Copyright © 2021, 2023-2024 Ludovic Courtès <ludo@gnu.org>
8;;; Copyright © 2025 Maxim Cournoyer <maxim.cournoyer@gmail.com>
8;;; 9;;;
9;;; This file is part of GNU Guix. 10;;; This file is part of GNU Guix.
10;;; 11;;;
@@ -29,6 +30,7 @@
29 #:use-module (gnu services base) 30 #:use-module (gnu services base)
30 #:use-module (gnu services dns) 31 #:use-module (gnu services dns)
31 #:use-module (gnu services networking) 32 #:use-module (gnu services networking)
33 #:use-module (gnu services ssh)
32 #:use-module (guix gexp) 34 #:use-module (guix gexp)
33 #:use-module (guix store) 35 #:use-module (guix store)
34 #:use-module (guix monads) 36 #:use-module (guix monads)
@@ -50,6 +52,7 @@
50 %test-dnsmasq 52 %test-dnsmasq
51 %test-tor 53 %test-tor
52 %test-iptables 54 %test-iptables
55 %test-nftables
53 %test-ipfs)) 56 %test-ipfs))
54 57
55 58
@@ -968,6 +971,8 @@ subnet 192.168.1.0 netmask 255.255.255.0 {
968 (description "Test a running Tor daemon configuration.") 971 (description "Test a running Tor daemon configuration.")
969 (value (run-tor-test)))) 972 (value (run-tor-test))))
970 973
974(define %inetd-echo-port 7)
975
971(define* (run-iptables-test) 976(define* (run-iptables-test)
972 "Run tests of 'iptables-service-type'." 977 "Run tests of 'iptables-service-type'."
973 (define iptables-rules 978 (define iptables-rules
@@ -988,8 +993,6 @@ COMMIT
988COMMIT 993COMMIT
989") 994")
990 995
991 (define inetd-echo-port 7)
992
993 (define os 996 (define os
994 (marionette-operating-system 997 (marionette-operating-system
995 (simple-operating-system 998 (simple-operating-system
@@ -1065,7 +1068,8 @@ COMMIT
1065 1068
1066 (test-error "iptables firewall blocks access to inetd echo service" 1069 (test-error "iptables firewall blocks access to inetd echo service"
1067 'misc-error 1070 'misc-error
1068 (wait-for-tcp-port inetd-echo-port marionette #:timeout 5)) 1071 (wait-for-tcp-port #$%inetd-echo-port marionette
1072 #:timeout 5))
1069 1073
1070 ;; TODO: This test freezes up at the login prompt without any 1074 ;; TODO: This test freezes up at the login prompt without any
1071 ;; relevant messages on the console. Perhaps it is waiting for some 1075 ;; relevant messages on the console. Perhaps it is waiting for some
@@ -1077,7 +1081,7 @@ COMMIT
1077 ;; (use-modules (gnu services herd)) 1081 ;; (use-modules (gnu services herd))
1078 ;; (stop-service 'iptables)) 1082 ;; (stop-service 'iptables))
1079 ;; marionette) 1083 ;; marionette)
1080 ;; (wait-for-tcp-port inetd-echo-port marionette #:timeout 5))) 1084 ;; (wait-for-tcp-port #$%inetd-echo-port marionette #:timeout 5)))
1081 1085
1082 (test-end)))) 1086 (test-end))))
1083 1087
@@ -1091,6 +1095,107 @@ COMMIT
1091 1095
1092 1096
1093;;; 1097;;;
1098;;; nftables.
1099;;;
1100
1101(define (make-nftables-os ruleset)
1102 (simple-operating-system
1103 (service dhcp-client-service-type)
1104 (service inetd-service-type
1105 (inetd-configuration
1106 (entries (list
1107 (inetd-entry
1108 (name "echo")
1109 (socket-type 'stream)
1110 (protocol "tcp")
1111 (wait? #f)
1112 (user "root"))))))
1113 (service openssh-service-type)
1114 (service nftables-service-type
1115 (nftables-configuration
1116 (debug-levels '(all))
1117 (ruleset ruleset)))))
1118
1119(define %default-nftables-ruleset-for-tests
1120 ;; This is like the %default-nftables-ruleset, but without allowing any
1121 ;; connections from the loopback interface.
1122 (plain-file "nftables.conf" "\
1123table inet filter {
1124 chain input {
1125 type filter hook input priority 0; policy drop;
1126
1127 # early drop of invalid connections
1128 ct state invalid drop
1129
1130 # allow established/related connections
1131 ct state { established, related } accept
1132
1133 # allow from loopback
1134 # iif lo accept # COMMENTED OUT FOR TESTS
1135 # drop connections to lo not coming from lo
1136 iif != lo ip daddr 127.0.0.1/8 drop
1137 iif != lo ip6 daddr ::1/128 drop
1138
1139 # allow icmp
1140 ip protocol icmp accept
1141 ip6 nexthdr icmpv6 accept
1142
1143 # allow ssh
1144 tcp dport ssh accept
1145
1146 # reject everything else
1147 reject with icmpx type port-unreachable
1148 }
1149 chain forward {
1150 type filter hook forward priority 0; policy drop;
1151 }
1152 chain output {
1153 type filter hook output priority 0; policy accept;
1154 }
1155}"))
1156
1157(define %nftables-os
1158 (make-nftables-os %default-nftables-ruleset-for-tests))
1159
1160(define (run-nftables-test)
1161 (define os
1162 (marionette-operating-system
1163 %nftables-os
1164 #:imported-modules '((gnu services herd))
1165 #:requirements '(inetd nftables ssh)))
1166
1167 (define test
1168 (with-imported-modules '((gnu build marionette))
1169 #~(begin
1170 (use-modules (gnu build marionette)
1171 (srfi srfi-64))
1172 (define marionette
1173 (make-marionette (list #$(virtual-machine os))))
1174
1175 (test-runner-current (system-test-runner #$output))
1176 (test-begin "nftables")
1177
1178 (test-error "nftables blocks access to inetd echo service"
1179 'misc-error
1180 (wait-for-tcp-port #$%inetd-echo-port marionette
1181 #:timeout 5))
1182
1183 (test-assert "nftables allows access to SSH TCP port 22"
1184 (wait-for-tcp-port 22 marionette))
1185
1186 (test-end))))
1187
1188 (gexp->derivation "nftables-test" test))
1189
1190(define %test-nftables
1191 (system-test
1192 (name "nftables")
1193 (description "Test the nftables service properly allow or block
1194connection to ports.")
1195 (value (run-nftables-test))))
1196
1197
1198;;;
1094;;; IPFS service 1199;;; IPFS service
1095;;; 1200;;;
1096 1201