unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
* [bug#32465] Add iptables service
@ 2018-08-17 11:24 Arun Isaac
  2018-09-04 13:14 ` Ludovic Courtès
  2018-09-11  6:53 ` [bug#32465] " Björn Höfling
  0 siblings, 2 replies; 16+ messages in thread
From: Arun Isaac @ 2018-08-17 11:24 UTC (permalink / raw)
  To: 32465

[-- Attachment #1: Type: text/plain, Size: 543 bytes --]


I have written a service to configure iptables rules. What tests should
I write for this service? I see the following two approaches to tests:

- Dump the iptables rules using iptables-save and verify that they
  matches the configured rules.
- Configure iptables to block certain ports and allow some other
  ports. Then, run a service on those ports and check if it is possible to
  reach them.

After we have iterated a few times, and converged on the final patch for
this service, I will also contribute a similar service for ip6tables.


[-- Attachment #2: 0001-gnu-services-Add-iptables-service.patch --]
[-- Type: text/x-patch, Size: 4087 bytes --]

From 53e0b56ea0ee4de75ab8749b0ce0ad9a2eebe671 Mon Sep 17 00:00:00 2001
From: Arun Isaac <arunisaac@systemreboot.net>
Date: Fri, 17 Aug 2018 16:39:07 +0530
Subject: [PATCH] gnu: services: Add iptables service.

* gnu/services/networking.scm (<iptables-configuration>): New record type.
(iptables-service-type): New variable.
* doc/guix.texi (Networking Services): Document it.
---
 doc/guix.texi               | 27 ++++++++++++++++++++++
 gnu/services/networking.scm | 45 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 0b72e5d8c..d5ff43811 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -11287,6 +11287,33 @@ Thus, it can be instantiated like this:
 @end lisp
 @end defvr
 
+@cindex iptables
+@defvr {Scheme Variabe} iptables-service-type
+This is the service type to set up an iptables coniguration. iptables is a
+packet filtering framework supported by the Linux kernel.  It can be
+instantiated as:
+
+@lisp
+(service iptables-service-type
+	 (iptables-configuration
+	  (rules (local-file "iptables.rules"))))
+@end lisp
+
+@deftp {Data Type} iptables-configuration
+The data type representing the configuration of @command{iptables}.
+
+@table @asis
+@item @code{iptables} (default: @code{iptables})
+The iptables package that provides @code{iptables-restore}.
+@item @code{rules}
+The iptables rules to use.  This is required.  It will be passed to
+@code{iptables-restore}.  This may be any ``file-like'' object
+(@pxref{G-Expressions, file-like objects}).
+@end table
+@end deftp
+
+@end defvr
+
 @cindex NTP
 @cindex real time clock
 @deffn {Scheme Procedure} ntp-service [#:ntp @var{ntp}] @
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index d5d0cf9d1..46e0ee3d0 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -7,6 +7,7 @@
 ;;; Copyright © 2017 Thomas Danckaert <post@thomasdanckaert.be>
 ;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
 ;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
+;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -102,7 +103,13 @@
             wpa-supplicant-service-type
 
             openvswitch-service-type
-            openvswitch-configuration))
+            openvswitch-configuration
+
+            iptables-configuration
+            iptables-configuration?
+            iptables-configuration-iptables
+            iptables-configuration-rules
+            iptables-service-type))
 
 ;;; Commentary:
 ;;;
@@ -1086,4 +1093,40 @@ networking."))))
 switch designed to enable massive network automation through programmatic
 extension.")))
 
+;;;
+;;; iptables
+;;;
+
+(define-record-type* <iptables-configuration>
+  iptables-configuration make-iptables-configuration iptables-configuration?
+  (iptables iptables-configuration-iptables
+            (default iptables))
+  (rules iptables-configuration-rules))
+
+(define iptables-shepherd-service
+  (match-lambda
+    (($ <iptables-configuration> iptables rules)
+     (let ((iptables-restore (file-append iptables "/sbin/iptables-restore")))
+       (shepherd-service
+        (documentation "Packet filtering framework")
+        (provision '(iptables))
+        (start #~(lambda _ (invoke #$iptables-restore #$rules)))
+        (stop #~(lambda _ (invoke #$iptables-restore
+                                  #$(plain-file "iptables.rules"
+                                                "*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+COMMIT
+")))))))))
+
+(define iptables-service-type
+  (service-type
+   (name 'iptables)
+   (description
+    "Run @command{iptables-restore}, setting up the specified rules.")
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             (compose list iptables-shepherd-service))))))
+
 ;;; networking.scm ends here
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-08-17 11:24 [bug#32465] Add iptables service Arun Isaac
@ 2018-09-04 13:14 ` Ludovic Courtès
  2018-09-04 13:52   ` Julien Lepiller
  2018-09-05  9:42   ` Arun Isaac
  2018-09-11  6:53 ` [bug#32465] " Björn Höfling
  1 sibling, 2 replies; 16+ messages in thread
From: Ludovic Courtès @ 2018-09-04 13:14 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465

Hello Arun,

Sorry for the delay, everyone must have been on vacations for a while.
:-)

Arun Isaac <arunisaac@systemreboot.net> skribis:

> I have written a service to configure iptables rules. What tests should
> I write for this service? I see the following two approaches to tests:
>
> - Dump the iptables rules using iptables-save and verify that they
>   matches the configured rules.
> - Configure iptables to block certain ports and allow some other
>   ports. Then, run a service on those ports and check if it is possible to
>   reach them.

Both approaches LGTM.

> After we have iterated a few times, and converged on the final patch for
> this service, I will also contribute a similar service for ip6tables.

Neat!

>>From 53e0b56ea0ee4de75ab8749b0ce0ad9a2eebe671 Mon Sep 17 00:00:00 2001
> From: Arun Isaac <arunisaac@systemreboot.net>
> Date: Fri, 17 Aug 2018 16:39:07 +0530
> Subject: [PATCH] gnu: services: Add iptables service.
>
> * gnu/services/networking.scm (<iptables-configuration>): New record type.
> (iptables-service-type): New variable.
> * doc/guix.texi (Networking Services): Document it.

[...]

> +@defvr {Scheme Variabe} iptables-service-type
> +This is the service type to set up an iptables coniguration. iptables is a
> +packet filtering framework supported by the Linux kernel.  It can be
> +instantiated as:
> +
> +@lisp
> +(service iptables-service-type
> +	 (iptables-configuration
> +	  (rules (local-file "iptables.rules"))))
> +@end lisp

“@end defvr” should be here.

What about adding either an “iptables.rules” example, a link to
upstream’s documentation, or both?

> +(define iptables-shepherd-service
> +  (match-lambda
> +    (($ <iptables-configuration> iptables rules)
> +     (let ((iptables-restore (file-append iptables "/sbin/iptables-restore")))
> +       (shepherd-service
> +        (documentation "Packet filtering framework")
> +        (provision '(iptables))
> +        (start #~(lambda _ (invoke #$iptables-restore #$rules)))
> +        (stop #~(lambda _ (invoke #$iptables-restore
> +                                  #$(plain-file "iptables.rules"
> +                                                "*filter
> +:INPUT ACCEPT [0:0]
> +:FORWARD ACCEPT [0:0]
> +:OUTPUT ACCEPT [0:0]
> +COMMIT
> +")))))))))

I was thinking that ‘stop’ might undo more than we want, but OTOH, when
the service starts, there are no rules loaded anyway.  So I guess this
is fine.

It would be great if you could get a system test as you suggest, but
anyhow it looks great to me.

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-04 13:14 ` Ludovic Courtès
@ 2018-09-04 13:52   ` Julien Lepiller
  2018-09-05  9:40     ` Arun Isaac
  2018-09-05  9:42   ` Arun Isaac
  1 sibling, 1 reply; 16+ messages in thread
From: Julien Lepiller @ 2018-09-04 13:52 UTC (permalink / raw)
  To: 32465

Hi,

it's not directly an answer to arun's patch (it is great), but I 
recently came accross firemason 
(http://www.cs.yale.edu/homes/zhai-ennan/firemason.pdf and 
https://github.com/BillHallahan/FireMason) and I thought we could 
implement something similar. Basically, we declare a list of rules in 
the iptables service, and we let other services extend that. A rule 
would be a specification, independent of the order in which they are 
specified. "Any packet that matches this rule must be rejected".

Of course, this means that we may have conflicting specifications, for 
instance "any packet from this ip must be dropped" and "any packet 
entering on this port must be accepted" are in conflict for packets 
entering on this port from this ip address. All we need is a mechanism 
to explicit these cases (when a packet may be dropped or accepted at the 
same time), such as "repair: packets from this ip on this port must be 
dropped", so the service will effectively see these rules: "any packet 
from this ip must be dropped" and "any packet entering on this port but 
not this ip must be accepted", then translated to:

-A INPUT -s ! <ip> -p tcp --dport <port> -j ACCEPT
-A INPUT -s <ip> ACCEPT

(see how they are independent from the order in which they are 
declared?)

The hard part is to detect a conflict between two rules and give hints 
to the user as to how to fix that.

Of course, we should provide a mechanism to load files as a fallback, in 
which case additional rules from services should be ignored.

What do you think?



PS: Arun, in your patch for the manual you say: "This is the service 
type to set up an iptables coniguration". This should be 
"configuration".

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-04 13:52   ` Julien Lepiller
@ 2018-09-05  9:40     ` Arun Isaac
  2018-09-10 12:51       ` Ludovic Courtès
  0 siblings, 1 reply; 16+ messages in thread
From: Arun Isaac @ 2018-09-05  9:40 UTC (permalink / raw)
  To: Julien Lepiller, 32465


> it's not directly an answer to arun's patch (it is great), but I 
> recently came accross firemason 
> (http://www.cs.yale.edu/homes/zhai-ennan/firemason.pdf and 
> https://github.com/BillHallahan/FireMason) and I thought we could 
> implement something similar.

This sounds interesting. I'll read about it, and if I can, try to
implement something similar for Guix.

> Of course, we should provide a mechanism to load files as a fallback, in 
> which case additional rules from services should be ignored.

Yes, I think this iptables service should exist independently as a
fallback. So, I'll finish and push these services before studying
firemason.

> PS: Arun, in your patch for the manual you say: "This is the service 
> type to set up an iptables coniguration". This should be 
> "configuration".

Sure, will fix this typo.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-04 13:14 ` Ludovic Courtès
  2018-09-04 13:52   ` Julien Lepiller
@ 2018-09-05  9:42   ` Arun Isaac
  2018-09-14 10:59     ` Arun Isaac
  1 sibling, 1 reply; 16+ messages in thread
From: Arun Isaac @ 2018-09-05  9:42 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 32465


> It would be great if you could get a system test as you suggest, but
> anyhow it looks great to me.

I'll make the corrections you suggested, write the system test, and send
an updated patch.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-05  9:40     ` Arun Isaac
@ 2018-09-10 12:51       ` Ludovic Courtès
  0 siblings, 0 replies; 16+ messages in thread
From: Ludovic Courtès @ 2018-09-10 12:51 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465

Hello,

Arun Isaac <arunisaac@systemreboot.net> skribis:

>> it's not directly an answer to arun's patch (it is great), but I 
>> recently came accross firemason 
>> (http://www.cs.yale.edu/homes/zhai-ennan/firemason.pdf and 
>> https://github.com/BillHallahan/FireMason) and I thought we could 
>> implement something similar.
>
> This sounds interesting. I'll read about it, and if I can, try to
> implement something similar for Guix.

Agreed, it looks nice.

>> Of course, we should provide a mechanism to load files as a fallback, in 
>> which case additional rules from services should be ignored.
>
> Yes, I think this iptables service should exist independently as a
> fallback. So, I'll finish and push these services before studying
> firemason.

The nice thing is that we could detect conflicting iptables rules
statically if we wanted to: ‘guix system reconfigure’ would proceed if
and only if there are no conflicting rules.  I don’t know how difficult
and how annoying that could be, but it might be worth considering (as
future work…).

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-08-17 11:24 [bug#32465] Add iptables service Arun Isaac
  2018-09-04 13:14 ` Ludovic Courtès
@ 2018-09-11  6:53 ` Björn Höfling
  2018-09-11  8:43   ` Arun Isaac
  1 sibling, 1 reply; 16+ messages in thread
From: Björn Höfling @ 2018-09-11  6:53 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465, Rutger Helling

[-- Attachment #1: Type: text/plain, Size: 864 bytes --]

On Fri, 17 Aug 2018 16:54:19 +0530
Arun Isaac <arunisaac@systemreboot.net> wrote:

> After we have iterated a few times, and converged on the final patch
> for this service, I will also contribute a similar service for
> ip6tables.


Hi Arun,

thanks for the patch. I have one little comment:

During holidays I read an article about nftables:

https://netfilter.org/projects/nftables/
https://wiki.archlinux.org/index.php/nftables

It aims to be the successor for iptables and is ipv4, ipv6 and others
in one tool/ruleset.

I have no knowledge about the firewall tools, I have no idea of how
mature or accepted that is, I just thought it might be worth
considering instead of writing 3 services.

We already have the userspace package 'nftables' and 'libnftnl' thanks
to Rutger Helling. Maybe he knows more? I put him on CC.

Björn


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-11  6:53 ` [bug#32465] " Björn Höfling
@ 2018-09-11  8:43   ` Arun Isaac
  2018-09-15 12:27     ` Rutger Helling
  0 siblings, 1 reply; 16+ messages in thread
From: Arun Isaac @ 2018-09-11  8:43 UTC (permalink / raw)
  To: Björn Höfling; +Cc: 32465, Rutger Helling


> I have no knowledge about the firewall tools, I have no idea of how
> mature or accepted that is, I just thought it might be worth
> considering instead of writing 3 services.

I have heard of nftables, but I haven't yet learnt how to use it. So,
for now, I'll just do 2 services (one for iptables, and another for
ip6tables). I think someone else who understands nftables should write
the nftables service.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-05  9:42   ` Arun Isaac
@ 2018-09-14 10:59     ` Arun Isaac
  2018-09-17 21:05       ` Ludovic Courtès
  0 siblings, 1 reply; 16+ messages in thread
From: Arun Isaac @ 2018-09-14 10:59 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 32465

[-- Attachment #1: Type: text/plain, Size: 755 bytes --]


Hi,

I generalized this service to work for both iptables and ip6tables. I
added system tests, and made the other corrections that were
suggested. Some questions follow.

- Is the example I added for the iptables.rules sufficient? I couldn't
  find upstream documentation for the iptables.rules format. I suspect
  it doesn't exist. Do you know of any upstream documentation that can
  be referred to here?
- In the attached patch, the fourth test ("inetd echo service is
  accessible after iptables firewall is stopped") doesn't work. In that
  service, I am trying to stop the iptables service, but I'm not able
  to. How do I programmatically stop the iptables service? Is what I
  have done correct?

Any other feedback is also welcome.

Thank you.


[-- Attachment #2: 0001-gnu-services-Add-iptables-service.patch --]
[-- Type: text/x-patch, Size: 11331 bytes --]

From dcfdd0bd981aa9da4835f322173490e239048e65 Mon Sep 17 00:00:00 2001
From: Arun Isaac <arunisaac@systemreboot.net>
Date: Fri, 17 Aug 2018 16:39:07 +0530
Subject: [PATCH] gnu: services: Add iptables service.

* gnu/services/networking.scm (<iptables-configuration>): New record type.
(iptables-service-type): New variable.
* gnu/tests/networking.scm (run-iptables-test): New procedure.
(%test-iptables): New variable.
* doc/guix.texi (Networking Services): Document it.
---
 doc/guix.texi               |  48 ++++++++++++++
 gnu/services/networking.scm |  56 ++++++++++++++++-
 gnu/tests/networking.scm    | 122 +++++++++++++++++++++++++++++++++++-
 3 files changed, 224 insertions(+), 2 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index cccf166d0..7dd7f8fc9 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -11575,6 +11575,54 @@ Thus, it can be instantiated like this:
 @end lisp
 @end defvr
 
+@cindex iptables
+@defvr {Scheme Variable} iptables-service-type
+This is the service type to set up an iptables configuration. iptables is a
+packet filtering framework supported by the Linux kernel.  This service
+supports configuring iptables for both IPv4 and IPv6.  A simple example
+configuration rejecting all incoming connections except those to the ssh port
+22 is shown below.
+
+@lisp
+(service iptables-service-type
+         (iptables-configuration
+          (ipv4-rules (plain-file "iptables.rules" "*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+-A INPUT -p tcp --dport 22 -j ACCEPT
+-A INPUT -j REJECT --reject-with icmp-port-unreachable
+COMMIT
+"))
+          (ipv6-rules (plain-file "ip6tables.rules" "*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+-A INPUT -p tcp --dport 22 -j ACCEPT
+-A INPUT -j REJECT --reject-with icmp6-port-unreachable
+COMMIT
+"))))
+@end lisp
+@end defvr
+
+@deftp {Data Type} iptables-configuration
+The data type representing the configuration of iptables.
+
+@table @asis
+@item @code{iptables} (default: @code{iptables})
+The iptables package that provides @code{iptables-restore} and
+@code{ip6tables-restore}.
+@item @code{ipv4-rules} (default: @code{%iptables-accept-all-rules})
+The iptables rules to use.  It will be passed to @code{iptables-restore}.
+This may be any ``file-like'' object (@pxref{G-Expressions, file-like
+objects}).
+@item @code{ipv6-rules} (default: @code{%iptables-accept-all-rules})
+The ip6tables rules to use.  It will be passed to @code{ip6tables-restore}.
+This may be any ``file-like'' object (@pxref{G-Expressions, file-like
+objects}).
+@end table
+@end deftp
+
 @cindex NTP
 @cindex real time clock
 @deffn {Scheme Procedure} ntp-service [#:ntp @var{ntp}] @
diff --git a/gnu/services/networking.scm b/gnu/services/networking.scm
index b6b5ee3fe..bd1d5a270 100644
--- a/gnu/services/networking.scm
+++ b/gnu/services/networking.scm
@@ -8,6 +8,7 @@
 ;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
 ;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
 ;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
+;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -103,7 +104,14 @@
             wpa-supplicant-service-type
 
             openvswitch-service-type
-            openvswitch-configuration))
+            openvswitch-configuration
+
+            iptables-configuration
+            iptables-configuration?
+            iptables-configuration-iptables
+            iptables-configuration-ipv4-rules
+            iptables-configuration-ipv6-rules
+            iptables-service-type))
 
 ;;; Commentary:
 ;;;
@@ -1108,4 +1116,50 @@ networking."))))
 switch designed to enable massive network automation through programmatic
 extension.")))
 
+;;;
+;;; iptables
+;;;
+
+(define %iptables-accept-all-rules
+  (plain-file "iptables-accept-all.rules"
+              "*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+COMMIT
+"))
+
+(define-record-type* <iptables-configuration>
+  iptables-configuration make-iptables-configuration iptables-configuration?
+  (iptables iptables-configuration-iptables
+            (default iptables))
+  (ipv4-rules iptables-configuration-ipv4-rules
+              (default %iptables-accept-all-rules))
+  (ipv6-rules iptables-configuration-ipv6-rules
+              (default %iptables-accept-all-rules)))
+
+(define iptables-shepherd-service
+  (match-lambda
+    (($ <iptables-configuration> iptables ipv4-rules ipv6-rules)
+     (let ((iptables-restore (file-append iptables "/sbin/iptables-restore"))
+           (ip6tables-restore (file-append iptables "/sbin/ip6tables-restore")))
+       (shepherd-service
+        (documentation "Packet filtering framework")
+        (provision '(iptables))
+        (start #~(lambda _
+                   (invoke #$iptables-restore #$ipv4-rules)
+                   (invoke #$ip6tables-restore #$ipv6-rules)))
+        (stop #~(lambda _
+                  (invoke #$iptables-restore #$%iptables-accept-all-rules)
+                  (invoke #$ip6tables-restore #$%iptables-accept-all-rules))))))))
+
+(define iptables-service-type
+  (service-type
+   (name 'iptables)
+   (description
+    "Run @command{iptables-restore}, setting up the specified rules.")
+   (extensions
+    (list (service-extension shepherd-root-service-type
+                             (compose list iptables-shepherd-service))))))
+
 ;;; networking.scm ends here
diff --git a/gnu/tests/networking.scm b/gnu/tests/networking.scm
index 381c5caf1..58fe61a49 100644
--- a/gnu/tests/networking.scm
+++ b/gnu/tests/networking.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2017 Thomas Danckaert <post@thomasdanckaert.be>
 ;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
 ;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
+;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -29,9 +30,11 @@
   #:use-module (guix store)
   #:use-module (guix monads)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages linux)
   #:use-module (gnu packages networking)
   #:use-module (gnu services shepherd)
-  #:export (%test-inetd %test-openvswitch %test-dhcpd %test-tor))
+  #:use-module (ice-9 match)
+  #:export (%test-inetd %test-openvswitch %test-dhcpd %test-tor %test-iptables))
 
 (define %inetd-os
   ;; Operating system with 2 inetd services.
@@ -434,3 +437,120 @@ subnet 192.168.1.0 netmask 255.255.255.0 {
    (name "tor")
    (description "Test a running Tor daemon configuration.")
    (value (run-tor-test))))
+
+(define* (run-iptables-test)
+  "Run tests of 'iptables-service-type'."
+  (define iptables-rules
+    "*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+-A INPUT -p tcp -m tcp --dport 7 -j REJECT --reject-with icmp-port-unreachable
+COMMIT
+")
+
+  (define ip6tables-rules
+    "*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+-A INPUT -p tcp -m tcp --dport 7 -j REJECT --reject-with icmp6-port-unreachable
+COMMIT
+")
+
+  (define inetd-echo-port 7)
+
+  (define os
+    (marionette-operating-system
+     (simple-operating-system
+      (dhcp-client-service)
+      (service inetd-service-type
+               (inetd-configuration
+                (entries (list
+                          (inetd-entry
+                           (name "echo")
+                           (socket-type 'stream)
+                           (protocol "tcp")
+                           (wait? #f)
+                           (user "root"))))))
+      (service iptables-service-type
+               (iptables-configuration
+                (ipv4-rules (plain-file "iptables.rules" iptables-rules))
+                (ipv6-rules (plain-file "ip6tables.rules" ip6tables-rules)))))
+     #:imported-modules '((gnu services herd))
+     #:requirements '(inetd iptables)))
+
+  (define test
+    (with-imported-modules '((gnu build marionette))
+      #~(begin
+          (use-modules (srfi srfi-64)
+                       (gnu build marionette))
+          (define marionette
+            (make-marionette (list #$(virtual-machine os))))
+
+          (define (dump-iptables iptables-save marionette)
+            (marionette-eval
+             `(begin
+                (use-modules (ice-9 popen)
+                             (ice-9 rdelim)
+                             (ice-9 regex))
+                (call-with-output-string
+                  (lambda (out)
+                    (call-with-port
+                     (open-pipe* OPEN_READ ,iptables-save)
+                     (lambda (in)
+                       (let loop ((line (read-line in)))
+                         ;; iptables-save does not output rules in the exact
+                         ;; same format we loaded using iptables-restore. It
+                         ;; adds comments, packet counters, etc. We remove
+                         ;; these additions.
+                         (unless (eof-object? line)
+                           (cond
+                            ;; Remove comments
+                            ((string-match "^#" line) #t)
+                            ;; Remove packet counters
+                            ((string-match "^:([A-Z]*) ([A-Z]*) .*" line)
+                             => (lambda (match-record)
+                                  (format out ":~a ~a~%"
+                                          (match:substring match-record 1)
+                                          (match:substring match-record 2))))
+                            ;; Pass other lines without modification
+                            (else (display line out)
+                                  (newline out)))
+                           (loop (read-line in)))))))))
+             marionette))
+
+          (mkdir #$output)
+          (chdir #$output)
+
+          (test-begin "iptables")
+
+          (test-equal "iptables-save dumps the same rules that were loaded"
+            (dump-iptables #$(file-append iptables "/sbin/iptables-save")
+                           marionette)
+            #$iptables-rules)
+
+          (test-equal "ip6tables-save dumps the same rules that were loaded"
+            (dump-iptables #$(file-append iptables "/sbin/ip6tables-save")
+                           marionette)
+            #$ip6tables-rules)
+
+          (test-error "iptables firewall blocks access to inetd echo service"
+                      'misc-error
+                      (wait-for-tcp-port inetd-echo-port marionette #:timeout 5))
+
+          (test-assert "inetd echo service is accessible after iptables firewall is stopped"
+            (begin
+              (marionette-eval '(stop-service 'iptables) marionette)
+              (wait-for-tcp-port inetd-echo-port marionette #:timeout 5)))
+
+          (test-end)
+          (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
+
+  (gexp->derivation "iptables" test))
+
+(define %test-iptables
+  (system-test
+   (name "iptables")
+   (description "Test a running iptables daemon.")
+   (value (run-iptables-test))))
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-11  8:43   ` Arun Isaac
@ 2018-09-15 12:27     ` Rutger Helling
  0 siblings, 0 replies; 16+ messages in thread
From: Rutger Helling @ 2018-09-15 12:27 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465

[-- Attachment #1: Type: text/plain, Size: 625 bytes --]

Hi everyone,

sorry for the late reply. For the record, I'm not working on a nftables
service.

On Tue, 11 Sep 2018 14:13:03 +0530
Arun Isaac <arunisaac@systemreboot.net> wrote:

> > I have no knowledge about the firewall tools, I have no idea of how
> > mature or accepted that is, I just thought it might be worth
> > considering instead of writing 3 services.  
> 
> I have heard of nftables, but I haven't yet learnt how to use it. So,
> for now, I'll just do 2 services (one for iptables, and another for
> ip6tables). I think someone else who understands nftables should write
> the nftables service.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-14 10:59     ` Arun Isaac
@ 2018-09-17 21:05       ` Ludovic Courtès
  2018-09-18  6:24         ` Arun Isaac
  0 siblings, 1 reply; 16+ messages in thread
From: Ludovic Courtès @ 2018-09-17 21:05 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465

Hi Arun,

Arun Isaac <arunisaac@systemreboot.net> skribis:

> I generalized this service to work for both iptables and ip6tables. I
> added system tests, and made the other corrections that were
> suggested. Some questions follow.
>
> - Is the example I added for the iptables.rules sufficient? I couldn't
>   find upstream documentation for the iptables.rules format. I suspect
>   it doesn't exist. Do you know of any upstream documentation that can
>   be referred to here?

From a quick search it must be <https://netfilter.org/documentation/>,
specifically <https://netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html>.

> - In the attached patch, the fourth test ("inetd echo service is
>   accessible after iptables firewall is stopped") doesn't work. In that
>   service, I am trying to stop the iptables service, but I'm not able
>   to. How do I programmatically stop the iptables service? Is what I
>   have done correct?

[...]

> +       (shepherd-service
> +        (documentation "Packet filtering framework")
> +        (provision '(iptables))
> +        (start #~(lambda _
> +                   (invoke #$iptables-restore #$ipv4-rules)
> +                   (invoke #$ip6tables-restore #$ipv6-rules)))
> +        (stop #~(lambda _
> +                  (invoke #$iptables-restore #$%iptables-accept-all-rules)
> +                  (invoke #$ip6tables-restore #$%iptables-accept-all-rules))))))))

There’s a peculiarity of ‘stop’ which is that it must return #f on
success.  So here, you just need to add a trailing #f after the second
‘invoke’ call.  If you do that, I suppose the test that stops the
firewall will pass.

And if it does, I think you can go ahead and push!  :-)

Thank you,
Ludo’.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-17 21:05       ` Ludovic Courtès
@ 2018-09-18  6:24         ` Arun Isaac
  2018-09-18 14:39           ` Ludovic Courtès
  0 siblings, 1 reply; 16+ messages in thread
From: Arun Isaac @ 2018-09-18  6:24 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 32465


>> - Is the example I added for the iptables.rules sufficient? I couldn't
>>   find upstream documentation for the iptables.rules format. I suspect
>>   it doesn't exist. Do you know of any upstream documentation that can
>>   be referred to here?
>
> From a quick search it must be <https://netfilter.org/documentation/>,
> specifically <https://netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html>.

This is general documentation for netfilter, not specific documentation
about the iptables.rules format. For that, I don't think there is
upstream documentation.

https://unix.stackexchange.com/questions/400163/netfilter-iptables-restore-file-format-documentation/400203

>> +        (stop #~(lambda _
>> +                  (invoke #$iptables-restore #$%iptables-accept-all-rules)
>> +                  (invoke #$ip6tables-restore #$%iptables-accept-all-rules))))))))
>
> There’s a peculiarity of ‘stop’ which is that it must return #f on
> success.  So here, you just need to add a trailing #f after the second
> ‘invoke’ call.  If you do that, I suppose the test that stops the
> firewall will pass.

There was one problem with stop-service being an unbound variable. I
fixed that by adding (use-modules (gnu services herd)). But, now the
test just freezes up. I wonder if it is waiting for some timeout. Here
is the snippet for the test I am currently using. Also, returning #f
from stop didn't make a difference.

(test-assert "inetd echo service is accessible after iptables firewall is stopped"
  (begin
    (marionette-eval
     '(begin
        (use-modules (gnu services herd))
        (stop-service 'iptables))
     marionette)
    (wait-for-tcp-port inetd-echo-port marionette #:timeout 5)))

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-18  6:24         ` Arun Isaac
@ 2018-09-18 14:39           ` Ludovic Courtès
  2018-09-18 16:02             ` Arun Isaac
  0 siblings, 1 reply; 16+ messages in thread
From: Ludovic Courtès @ 2018-09-18 14:39 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465

Hi,

Arun Isaac <arunisaac@systemreboot.net> skribis:

>>> - Is the example I added for the iptables.rules sufficient? I couldn't
>>>   find upstream documentation for the iptables.rules format. I suspect
>>>   it doesn't exist. Do you know of any upstream documentation that can
>>>   be referred to here?
>>
>> From a quick search it must be <https://netfilter.org/documentation/>,
>> specifically <https://netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html>.
>
> This is general documentation for netfilter, not specific documentation
> about the iptables.rules format. For that, I don't think there is
> upstream documentation.
>
> https://unix.stackexchange.com/questions/400163/netfilter-iptables-restore-file-format-documentation/400203

Oh indeed.

>>> +        (stop #~(lambda _
>>> +                  (invoke #$iptables-restore #$%iptables-accept-all-rules)
>>> +                  (invoke #$ip6tables-restore #$%iptables-accept-all-rules))))))))
>>
>> There’s a peculiarity of ‘stop’ which is that it must return #f on
>> success.  So here, you just need to add a trailing #f after the second
>> ‘invoke’ call.  If you do that, I suppose the test that stops the
>> firewall will pass.
>
> There was one problem with stop-service being an unbound variable. I
> fixed that by adding (use-modules (gnu services herd)). But, now the
> test just freezes up. I wonder if it is waiting for some timeout. Here
> is the snippet for the test I am currently using. Also, returning #f
> from stop didn't make a difference.
>
> (test-assert "inetd echo service is accessible after iptables firewall is stopped"
>   (begin
>     (marionette-eval
>      '(begin
>         (use-modules (gnu services herd))
>         (stop-service 'iptables))
>      marionette)
>     (wait-for-tcp-port inetd-echo-port marionette #:timeout 5)))

Do you see any messages on the console?

Thanks,
Ludo’.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-18 14:39           ` Ludovic Courtès
@ 2018-09-18 16:02             ` Arun Isaac
  2018-09-19 20:41               ` Ludovic Courtès
  0 siblings, 1 reply; 16+ messages in thread
From: Arun Isaac @ 2018-09-18 16:02 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 32465


>> (test-assert "inetd echo service is accessible after iptables firewall is stopped"
>>   (begin
>>     (marionette-eval
>>      '(begin
>>         (use-modules (gnu services herd))
>>         (stop-service 'iptables))
>>      marionette)
>>     (wait-for-tcp-port inetd-echo-port marionette #:timeout 5)))
>
> Do you see any messages on the console?

I see no relevant messages on the console. It just gets stuck at
"komputilo login:".

I could just skip this test, and push with a TODO comment in
gnu/tests/networking.scm. WDYT?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [bug#32465] Add iptables service
  2018-09-18 16:02             ` Arun Isaac
@ 2018-09-19 20:41               ` Ludovic Courtès
  2018-09-20  7:50                 ` bug#32465: " Arun Isaac
  0 siblings, 1 reply; 16+ messages in thread
From: Ludovic Courtès @ 2018-09-19 20:41 UTC (permalink / raw)
  To: Arun Isaac; +Cc: 32465

Arun Isaac <arunisaac@systemreboot.net> skribis:

>>> (test-assert "inetd echo service is accessible after iptables firewall is stopped"
>>>   (begin
>>>     (marionette-eval
>>>      '(begin
>>>         (use-modules (gnu services herd))
>>>         (stop-service 'iptables))
>>>      marionette)
>>>     (wait-for-tcp-port inetd-echo-port marionette #:timeout 5)))
>>
>> Do you see any messages on the console?
>
> I see no relevant messages on the console. It just gets stuck at
> "komputilo login:".
>
> I could just skip this test, and push with a TODO comment in
> gnu/tests/networking.scm. WDYT?

Yes, sounds good!

Thank you,
Ludo’.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#32465: Add iptables service
  2018-09-19 20:41               ` Ludovic Courtès
@ 2018-09-20  7:50                 ` Arun Isaac
  0 siblings, 0 replies; 16+ messages in thread
From: Arun Isaac @ 2018-09-20  7:50 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: 32465-done


Pushed, thanks!

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-09-20  7:51 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-17 11:24 [bug#32465] Add iptables service Arun Isaac
2018-09-04 13:14 ` Ludovic Courtès
2018-09-04 13:52   ` Julien Lepiller
2018-09-05  9:40     ` Arun Isaac
2018-09-10 12:51       ` Ludovic Courtès
2018-09-05  9:42   ` Arun Isaac
2018-09-14 10:59     ` Arun Isaac
2018-09-17 21:05       ` Ludovic Courtès
2018-09-18  6:24         ` Arun Isaac
2018-09-18 14:39           ` Ludovic Courtès
2018-09-18 16:02             ` Arun Isaac
2018-09-19 20:41               ` Ludovic Courtès
2018-09-20  7:50                 ` bug#32465: " Arun Isaac
2018-09-11  6:53 ` [bug#32465] " Björn Höfling
2018-09-11  8:43   ` Arun Isaac
2018-09-15 12:27     ` Rutger Helling

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).