Package: guix-patches;
Reported by: Solene Rapenne <solene <at> perso.pw>
Date: Sat, 12 Jun 2021 17:21:02 UTC
Severity: normal
Message #17 received at 48975 <at> debbugs.gnu.org (full text, mbox):
From: antlers <autumnalantlers <at> gmail.com> To: 48975 <at> debbugs.gnu.org Cc: antlers <antlers <at> luris.net> Subject: [PATCH] gnu: simple-firewall-service: Add a simple service wrapping iptables Date: Fri, 4 Nov 2022 00:25:50 -0700
From: antlers <antlers <at> luris.net> * gnu/services/networking.scm (simple-firewall-service): Add. (iptables-service): Allow a crude sort of service extension. I tried out a keyword-based syntax: ``` (simple-firewall-configuration (allow-forwarding? #t) (allowed-ports '(#:both 51234 #:tcp 80 443 #:udp 4444)) ``` But kept the more verbose tcp and udp fields because I don't want people to have to use quasiquotes to splice in evaluated port-numbers after the keywords. I like the suggestion that there should be a field for redirecting packets, whether to loopback or another box, as it took me a while to learn about eg. masquerading last time I needed to set something like that up. Not sure what command would be equivalent to the NAT suggestion? I guess nftables has superseded iptables, but I'm not as familiar with it? Perhaps I can add it as a second back-end in the future. My primary concern right now is a pure Scheme interface for networking configuration; most notably via service inheritance! Simple-firewall now lets you open ports via extensions in other services; in order for this option to be widely available, perhaps it's the {nf,ip}tables-services that should be extensible? It's a tricky problem atm because we don't really want services that need ports depending on a specific backend, there are existing API's, they use plain-file's over structs or strings, and rule orders need to be really specific/coordinated. Idk, maybe that isn't something we really want in the first place, but it sure feels good from a configuration / organizational point-of-view. Happy to tweak this again if anyone has ideas. --- gnu/services/networking.scm | 79 ++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm index 19aba8c266..0866c10b34 100644 --- a/gnu/services/networking.scm +++ b/gnu/services/networking.scm @@ -18,6 +18,8 @@ ;;; Copyright © 2021 Christine Lemmer-Webber <cwebber <at> dustycloud.org> ;;; Copyright © 2021 Maxime Devos <maximedevos <at> telenet.be> ;;; Copyright © 2021 Guillaume Le Vaillant <glv <at> posteo.net> +;;; Copyright © 2021 Solene Rapenne +;;; Copyright © 2022 antlers <autumnalantlers <at> gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -225,7 +227,11 @@ (define-module (gnu services networking) keepalived-configuration keepalived-configuration? - keepalived-service-type)) + keepalived-service-type + + simple-firewall-service-type + simple-firewall-configuration + simple-firewall-configuration?)) ;;; Commentary: ;;; @@ -1721,7 +1727,13 @@ (define iptables-service-type "Run @command{iptables-restore}, setting up the specified rules.") (extensions (list (service-extension shepherd-root-service-type - (compose list iptables-shepherd-service)))))) + (compose list iptables-shepherd-service)))) + ;; Some services extend iptables, but such services are mutually exclusive, + ;; and should be either extended directly or superseded entirely depending + ;; the complexity of your desired configuration. + (compose identity) + (extend (lambda (config entries) + (last entries))))) ;;; ;;; nftables @@ -2186,4 +2198,67 @@ (define keepalived-service-type "Run @uref{https://www.keepalived.org/, Keepalived} routing software."))) + +;;; +;;; Simple Firewall +;;; + +(define-record-type* <simple-firewall-configuration> + simple-firewall-configuration make-simple-firewall-configuration + simple-firewall-configuration? + (allow-icmp? simple-firewall-configuration-allow-icmp? + (default #f)) + (allow-forwarding? simple-firewall-configuration-allow-forwarding? + (default #f)) + + (open-tcp-ports simple-firewall-configuration-open-tcp-ports + (default '())) + (open-udp-ports simple-firewall-configuration-open-udp-ports + (default '()))) + +(define simple-firewall-configuration->iptables-rules + (match-lambda + (($ <simple-firewall-configuration> + allow-icmp? allow-forwarding? + open-tcp-ports open-udp-ports) + (string-join + `("*filter" + ":INPUT DROP" + ,(string-append ":FORWARD " (if allow-forwarding? "ACCEPT" "DROP")) + ":OUTPUT ACCEPT" + "-A INPUT -i lo -j ACCEPT" + "-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT" + ,@(unless allow-icmp? '("-A INPUT -p icmp -j DROP" + "-A INPUT -p icmpv6 -j DROP")) + ,@(map (cut string-append "-A INPUT -p tcp --dport " <> " -j ACCEPT") (map number->string open-tcp-ports)) + ,@(map (cut string-append "-A INPUT -p udp --dport " <> " -j ACCEPT") (map number->string open-udp-ports)) + "-A INPUT -j REJECT --reject-with icmp-port-unreachable" + "COMMIT") + "\n" 'suffix)))) + +(define (simple-firewall-configuration->iptables-configuration config) + (let ((rules (simple-firewall-configuration->iptables-rules config))) + (iptables-configuration + (ipv4-rules (plain-file "iptables.rules" rules)) + (ipv6-rules (plain-file "ip6tables.rules" rules))))) + +(define simple-firewall-service-type + (service-type + (name 'simple-firewall) + (description + "Run @command{iptables-restore}, setting up the specified rules.") + (extensions + (list (service-extension iptables-service-type + simple-firewall-configuration->iptables-configuration))) + (compose concatenate) + (extend (lambda (config entries) + (simple-firewall-configuration + (inherit config) + (open-tcp-ports + (concatenate (map simple-firewall-configuration-open-tcp-ports + (cons config entries)))) + (open-udp-ports + (concatenate (map simple-firewall-configuration-open-udp-ports + (cons config entries))))))))) + ;;; networking.scm ends here -- 2.38.0
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.