From patchwork Fri Nov 4 07:25:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: antlers X-Patchwork-Id: 44292 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id B4D2227BBEA; Fri, 4 Nov 2022 07:38:52 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id F086727BBE9 for ; Fri, 4 Nov 2022 07:38:51 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oqrFa-00006B-BF; Fri, 04 Nov 2022 03:36:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oqr6U-0002zO-IP for guix-patches@gnu.org; Fri, 04 Nov 2022 03:27:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oqr6U-0002nW-94 for guix-patches@gnu.org; Fri, 04 Nov 2022 03:27:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1oqr6U-0000UI-48 for guix-patches@gnu.org; Fri, 04 Nov 2022 03:27:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#48975] [PATCH] gnu: simple-firewall-service: Add a simple service wrapping iptables References: <20210612191959.6394494e@perso.pw> In-Reply-To: <20210612191959.6394494e@perso.pw> Resent-From: antlers Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 04 Nov 2022 07:27:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 48975 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: To: 48975@debbugs.gnu.org Cc: antlers Received: via spool by 48975-submit@debbugs.gnu.org id=B48975.16675467871809 (code B ref 48975); Fri, 04 Nov 2022 07:27:02 +0000 Received: (at 48975) by debbugs.gnu.org; 4 Nov 2022 07:26:27 +0000 Received: from localhost ([127.0.0.1]:51498 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oqr5u-0000T7-D4 for submit@debbugs.gnu.org; Fri, 04 Nov 2022 03:26:26 -0400 Received: from mail-pf1-f170.google.com ([209.85.210.170]:34376) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oqr5p-0000Sp-4u for 48975@debbugs.gnu.org; Fri, 04 Nov 2022 03:26:24 -0400 Received: by mail-pf1-f170.google.com with SMTP id z26so3806087pff.1 for <48975@debbugs.gnu.org>; Fri, 04 Nov 2022 00:26:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=I6d6pyk6zolvcsx1GKJPROVwP6nb3W8LjaHpqzfhrn8=; b=AWLy3/5RoVNjSCWUs5HbJObTbAUtMkF419fa2U7pO+waKKpkhPDdB1dAo7mSoMcF3g o84z0GaPf/6sMv2ZKEpBbnwaKxJYNLm0EVRTWgpLjcbuFuR3x4VMBKvWveV6ZHETxex4 oUpLDjqRhHXK35DfiPeimU2d0RQtNidQy5qEFJ0PUF5l6C/e5FBjve4OTfQOjygn6zko LbhxeMbBEQPT10ZZe6h3wlitDMskUl+DVO5OPvCKRj5wdDjp8ik3Q+C4PDGiygFk7U4n Fn7cf/ZIpmbNdZb77//HI5u7tU9dy4KZGW3EVypuT8Rp1xzKGEgprPU7cQtPXsGGiYhQ az2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=I6d6pyk6zolvcsx1GKJPROVwP6nb3W8LjaHpqzfhrn8=; b=v6X8kTJ6sp5dNibbG9R1q69+bth3ipSxFuKGGm5ATSniPD4kLq+RFj8HTbRC2/gKfV khfMwUkFWGWsLigNzPXw0oC1MPqli5jBfBos1zNXDr1UhbIiD2pnt+uZ4x4hHYZ8vMZB +thy1hcNWmyxLwncXS4aZgY+AnUeDbZGZ1rEAHYW0hatfwi0PMrF9rU5Pg+tbC7PQ9oX qq0S1yRsVfPB4vzqbyC4RbPmB7J6eoJ/uPWfSRY3hNLlfVuoS3loL9P2ZiAJQXZ8FBe4 EtLPoLvOUpDPe3D9t8YYmsz5jGJotRpbOeVOPQCP+/3pWSoJ0P+uOOwNEQvztEkTcwRU 7AAA== X-Gm-Message-State: ACrzQf2GOsbIS0zyMPL2wp2ip65BIlDj1dZHk5NCx4YQQ+XtYy1RrW32 DBoK9+FS/WCsbCR3BwjmzJz/8VzOI5s= X-Google-Smtp-Source: AMsMyM5MixrBWFMzfzTgsn5Oow8yDHpgYsHK+pRLDKwK/YREutSNxYbGXsxgkTtdKcYb/fCkhOlO3g== X-Received: by 2002:a63:da4f:0:b0:43f:6af:74ed with SMTP id l15-20020a63da4f000000b0043f06af74edmr30139647pgj.290.1667546774887; Fri, 04 Nov 2022 00:26:14 -0700 (PDT) Received: from localhost.localdomain (static-24-113-160-104.wavecable.com. [24.113.160.104]) by smtp.gmail.com with ESMTPSA id v5-20020a17090a898500b00217090ece49sm758463pjn.31.2022.11.04.00.26.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Nov 2022 00:26:14 -0700 (PDT) From: antlers Date: Fri, 4 Nov 2022 00:25:50 -0700 Message-Id: <20221104072550.32038-1-autumnalantlers@gmail.com> X-Mailer: git-send-email 2.38.0 MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Guix-patches" Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches From: antlers * 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 ;;; Copyright © 2021 Maxime Devos ;;; Copyright © 2021 Guillaume Le Vaillant +;;; Copyright © 2021 Solene Rapenne +;;; Copyright © 2022 antlers ;;; ;;; 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 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 + (($ + 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