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.
This commit is contained in:
parent
3e63a83c0f
commit
9926b8f809
|
@ -11612,6 +11612,54 @@ Thus, it can be instantiated like this:
|
||||||
@end lisp
|
@end lisp
|
||||||
@end defvr
|
@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 NTP
|
||||||
@cindex real time clock
|
@cindex real time clock
|
||||||
@deffn {Scheme Procedure} ntp-service [#:ntp @var{ntp}] @
|
@deffn {Scheme Procedure} ntp-service [#:ntp @var{ntp}] @
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
|
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
|
||||||
;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
|
;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
|
||||||
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
|
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
|
||||||
|
;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
|
||||||
;;;
|
;;;
|
||||||
;;; This file is part of GNU Guix.
|
;;; This file is part of GNU Guix.
|
||||||
;;;
|
;;;
|
||||||
|
@ -103,7 +104,14 @@
|
||||||
wpa-supplicant-service-type
|
wpa-supplicant-service-type
|
||||||
|
|
||||||
openvswitch-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:
|
;;; Commentary:
|
||||||
;;;
|
;;;
|
||||||
|
@ -1108,4 +1116,50 @@ networking."))))
|
||||||
switch designed to enable massive network automation through programmatic
|
switch designed to enable massive network automation through programmatic
|
||||||
extension.")))
|
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
|
;;; networking.scm ends here
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
;;; Copyright © 2017 Thomas Danckaert <post@thomasdanckaert.be>
|
;;; Copyright © 2017 Thomas Danckaert <post@thomasdanckaert.be>
|
||||||
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
|
;;; Copyright © 2017 Marius Bakke <mbakke@fastmail.com>
|
||||||
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
|
;;; Copyright © 2018 Chris Marusich <cmmarusich@gmail.com>
|
||||||
|
;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
|
||||||
;;;
|
;;;
|
||||||
;;; This file is part of GNU Guix.
|
;;; This file is part of GNU Guix.
|
||||||
;;;
|
;;;
|
||||||
|
@ -29,9 +30,11 @@
|
||||||
#:use-module (guix store)
|
#:use-module (guix store)
|
||||||
#:use-module (guix monads)
|
#:use-module (guix monads)
|
||||||
#:use-module (gnu packages bash)
|
#:use-module (gnu packages bash)
|
||||||
|
#:use-module (gnu packages linux)
|
||||||
#:use-module (gnu packages networking)
|
#:use-module (gnu packages networking)
|
||||||
#:use-module (gnu services shepherd)
|
#: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
|
(define %inetd-os
|
||||||
;; Operating system with 2 inetd services.
|
;; Operating system with 2 inetd services.
|
||||||
|
@ -434,3 +437,127 @@ subnet 192.168.1.0 netmask 255.255.255.0 {
|
||||||
(name "tor")
|
(name "tor")
|
||||||
(description "Test a running Tor daemon configuration.")
|
(description "Test a running Tor daemon configuration.")
|
||||||
(value (run-tor-test))))
|
(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))
|
||||||
|
|
||||||
|
;; TODO: This test freezes up at the login prompt without any
|
||||||
|
;; relevant messages on the console. Perhaps it is waiting for some
|
||||||
|
;; timeout. Find and fix this issue.
|
||||||
|
;; (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)))
|
||||||
|
|
||||||
|
(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))))
|
||||||
|
|
Loading…
Reference in New Issue