Message ID | 20210612191959.6394494e@perso.pw |
---|---|
State | New |
Headers | show |
Series | [bug#48975] New firewall service | expand |
Context | Check | Description |
---|---|---|
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
On 12.06.21 19:19, Solene Rapenne via Guix-patches via wrote: > Hello, > > I wrote a new firewall service, I already wrote an email to guix-devel > about it and I've been suggested to submit it here. > > The idea is to propose an easy way to manage your firewall. On a > personal computer or a server with no fancy network, you certainly want > to block access from the outside to all the ports except a few ones. Hi Solene, that is a really good idea. So I could get rid of my growing lines of plain iptables in my Guix config :) > The configuration looks like this, currently it only supports TCP and > UDP ports. Maybe NAT could be added later or other feature, I'm opened > to suggestions. > > (service firewall-service-type > (firewall-configuration > (udp '(53)) > (tcp '(22 70 1965)))) I think we could improve the syntax as to be honest I'm unsure if the listed ports are the open or the closed ones. Maybe we could call this service simple-firewall-service-type or something along this. > > Here is the code, I took bits from iptables as a base and then used the > Tor service way to generate the configuration file. > > diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm > index 87b3d754a3..d311f95448 100644 > --- a/gnu/services/networking.scm > +++ b/gnu/services/networking.scm You should add a copyright line for yourself at the top of the file. > @@ -221,7 +221,11 @@ > > keepalived-configuration > keepalived-configuration? > - keepalived-service-type)) > + keepalived-service-type > + > + firewall-service-type > + firewall-configuration > + firewall-configuration?)) > > ;;; Commentary: > ;;; > @@ -2190,4 +2194,76 @@ of the IPFS peer-to-peer storage network."))) > "Run @uref{https://www.keepalived.org/, Keepalived} > routing software."))) > > + > +;;; > +;;; Firewall > +;;; > + > +(define-record-type* <firewall-configuration> > + firewall-configuration make-firewall-configuration > + firewall-configuration? > + (tcp firewall-configuration-tcp > + (default '())) > + (udp firewall-configuration-udp > + (default '()))) > + > +(define (firewall-configuration->file tcp udp) > + "Return the iptables rules from the ports list" > + (computed-file > + "firewall-generated-rules" > + (with-imported-modules '((guix build utils)) > + #~(begin > + (use-modules (guix build utils) > + (ice-9 match)) > + (call-with-output-file #$output > + (lambda (out) > + (display "\ > +*filter > +:INPUT DROP > +:FORWARD DROP > +:OUTPUT ACCEPT > +-A INPUT -i lo -j ACCEPT > +-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT\n" out) > + > + ;; tcp rules > + (when (not (null? (list #$@tcp))) > + (format out "\ > +~{-A INPUT -p tcp --dport ~a -j ACCEPT~%~}" > + (list #$@tcp))) > + > + ;; udp rules > + (when (not (null? (list #$@udp))) > + (format out "\ > +~{-A INPUT -p udp --dport ~a -j ACCEPT~%~}" > + (list #$@udp))) > + > + (display "COMMIT\n" out) > + #t)))))) I'm not an iptables expert but does this config block/open IPv4 as well as IPv6? > +(define firewall-shepherd-service > + (match-lambda > + (($ <firewall-configuration> tcp udp) > + (let* ((iptables-restore (file-append iptables "/sbin/iptables-restore")) > + (ip6tables-restore (file-append iptables "/sbin/ip6tables-restore")) > + (ruleset (firewall-configuration->file tcp udp))) > + (shepherd-service > + (documentation "Easy firewall management") > + (provision '(firewall)) > + (start #~(lambda _ > + (invoke #$iptables-restore #$ruleset) > + (invoke #$ip6tables-restore #$ruleset))) > + (stop #~(lambda _ > + (invoke #$iptables-restore #$ruleset) > + (invoke #$ip6tables-restore #$ruleset)))))))) > + > +(define firewall-service-type > + (service-type > + (name 'firewall) > + (description > + "Run @command{iptables-restore}, setting up the specified rules.") > + (extensions > + (list (service-extension shepherd-root-service-type > + (compose list firewall-shepherd-service)))))) > + > + > ;;; networking.scm ends here > > >
On Sat, 12 Jun 2021 21:59:53 +0200 Jonathan Brielmaier <jonathan.brielmaier@web.de>: > On 12.06.21 19:19, Solene Rapenne via Guix-patches via wrote: > > Hello, > > > > I wrote a new firewall service, I already wrote an email to guix-devel > > about it and I've been suggested to submit it here. > > > > The idea is to propose an easy way to manage your firewall. On a > > personal computer or a server with no fancy network, you certainly want > > to block access from the outside to all the ports except a few ones. > > Hi Solene, > > that is a really good idea. So I could get rid of my growing lines of > plain iptables in my Guix config :) > > > The configuration looks like this, currently it only supports TCP and > > UDP ports. Maybe NAT could be added later or other feature, I'm opened > > to suggestions. > > > > (service firewall-service-type > > (firewall-configuration > > (udp '(53)) > > (tcp '(22 70 1965)))) > > I think we could improve the syntax as to be honest I'm unsure if the > listed ports are the open or the closed ones. > > Maybe we could call this service simple-firewall-service-type or > something along this. hello, thanks a lot for your feedback. I have no argument for a rename, as long as it's understandable. As it's simple, I like simple-firewall. Do you think this would be easier to understand by adding "open" to the names? (service simple-firewall-service-type (simple-firewall-configuration (open-udp '(53)) (open-tcp '(22 ...)))) I think we must decided if ICMP is allowed by default or not and the syntax to enable/disable it. Maybe this? I would disable it by default. (allow-icmp? #t) If you stop simple-firewall with the current code, it will block every inbound ports, I'm not sure if it's the correct way to proceed, I suppose it should flush absolutely everything. To match most simple use case, a simple NAT and port redirection could be done too. ;; do NAT on eth0 and set the according sysctl (nat-on "eth0") ;; redirect incoming connections on ports 22 and 8080 to another box (redirect '((22 "192.168.1.50:22") (8080 "192.168.1.50:80")) > > > > Here is the code, I took bits from iptables as a base and then used the > > Tor service way to generate the configuration file. > > > > diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm > > index 87b3d754a3..d311f95448 100644 > > --- a/gnu/services/networking.scm > > +++ b/gnu/services/networking.scm > > You should add a copyright line for yourself at the top of the file. > I've been told it's not mandatory. I have no issue adding it though. I found a ^L character at many paces in networking.scm, I don't know if its appearance is legit or not. I think it's a garbage character that got copy/pasted over and over. I copied it just in case. > > > > + > > +;;; > > +;;; Firewall > > +;;; > > +
Hi Solene, Thanks for the great work! I wrote the iptables service in the hope of some day extending it to something like this, but you've beaten me to it! :-) Some feedback follows. Your implementation duplicates some of the code in the iptables service. How about making it simply /extend/ the iptables service with the generated rules? This way, you won't have to handle the start/stop iptables-restore gexps. The iptables service, when stopped, already has the correct behaviour of opening all ports. WDYT? Regards, Arun
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm index 87b3d754a3..d311f95448 100644 --- a/gnu/services/networking.scm +++ b/gnu/services/networking.scm @@ -221,7 +221,11 @@ keepalived-configuration keepalived-configuration? - keepalived-service-type)) + keepalived-service-type + + firewall-service-type + firewall-configuration + firewall-configuration?)) ;;; Commentary: ;;; @@ -2190,4 +2194,76 @@ of the IPFS peer-to-peer storage network."))) "Run @uref{https://www.keepalived.org/, Keepalived} routing software."))) + +;;; +;;; Firewall +;;; + +(define-record-type* <firewall-configuration> + firewall-configuration make-firewall-configuration + firewall-configuration? + (tcp firewall-configuration-tcp + (default '())) + (udp firewall-configuration-udp + (default '()))) + +(define (firewall-configuration->file tcp udp) + "Return the iptables rules from the ports list" + (computed-file + "firewall-generated-rules" + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils) + (ice-9 match)) + (call-with-output-file #$output + (lambda (out) + (display "\ +*filter +:INPUT DROP +:FORWARD DROP +:OUTPUT ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT\n" out) + + ;; tcp rules + (when (not (null? (list #$@tcp))) + (format out "\ +~{-A INPUT -p tcp --dport ~a -j ACCEPT~%~}" + (list #$@tcp))) + + ;; udp rules + (when (not (null? (list #$@udp))) + (format out "\ +~{-A INPUT -p udp --dport ~a -j ACCEPT~%~}" + (list #$@udp))) + + (display "COMMIT\n" out) + #t)))))) + +(define firewall-shepherd-service + (match-lambda + (($ <firewall-configuration> tcp udp) + (let* ((iptables-restore (file-append iptables "/sbin/iptables-restore")) + (ip6tables-restore (file-append iptables "/sbin/ip6tables-restore")) + (ruleset (firewall-configuration->file tcp udp))) + (shepherd-service + (documentation "Easy firewall management") + (provision '(firewall)) + (start #~(lambda _ + (invoke #$iptables-restore #$ruleset) + (invoke #$ip6tables-restore #$ruleset))) + (stop #~(lambda _ + (invoke #$iptables-restore #$ruleset) + (invoke #$ip6tables-restore #$ruleset)))))))) + +(define firewall-service-type + (service-type + (name 'firewall) + (description + "Run @command{iptables-restore}, setting up the specified rules.") + (extensions + (list (service-extension shepherd-root-service-type + (compose list firewall-shepherd-service)))))) + + ;;; networking.scm ends here