Try a new ferm rule class
authorPeter Palfrader <peter@palfrader.org>
Mon, 16 Sep 2019 08:07:18 +0000 (10:07 +0200)
committerPeter Palfrader <peter@palfrader.org>
Mon, 16 Sep 2019 08:07:18 +0000 (10:07 +0200)
modules/ferm/manifests/rule/simple.pp [new file with mode: 0644]
modules/named/manifests/geodns.pp

diff --git a/modules/ferm/manifests/rule/simple.pp b/modules/ferm/manifests/rule/simple.pp
new file mode 100644 (file)
index 0000000..fff04a3
--- /dev/null
@@ -0,0 +1,70 @@
+# a plain, simple ferm rule
+#
+# @param proto  tcp or udp or both.
+# @param port   one or more ports or port ranges.
+# @param saddr  one or more source addresses/networks.
+# @param daddr  one or more destination addresses/networks.
+# @param domain netfilter domain: ip (IPv4), ip6 (IPv6), or both.
+# @param table  netfilter table
+# @param chain  netfilter chain
+# @param target netfilter target
+# @param description a description of the rule
+# @param prio   Priority/Order of the rule
+define ferm::rule::simple (
+  String $description = '',
+  Variant[Enum['tcp', 'udp'], Array[Enum['tcp', 'udp']]] $proto = 'tcp',
+  Optional[Variant[Integer, Array[Integer], String, Array[String]]] $port = undef,
+  Optional[Variant[Stdlib::IP::Address, Array[Stdlib::IP::Address]]] $saddr = undef,
+  Optional[Variant[Stdlib::IP::Address, Array[Stdlib::IP::Address]]] $daddr = undef,
+  Variant[Enum['ip', 'ip6'], Array[Enum['ip', 'ip6']]] $domain = ['ip', 'ip6'],
+  String $table = 'filter',
+  String $chain = 'INPUT',
+  String $target = 'ACCEPT',
+  String $prio = '10',
+) {
+  include ferm
+
+  $filter_port  = $port  != undef
+  $filter_saddr = $saddr != undef
+  $filter_daddr = $daddr != undef
+
+  $real_domain = Array($domain, true)
+  $real_proto  = Array($proto, true)
+  $real_port   = Array($port, true)
+  $real_saddr  = Array($saddr, true)
+  $real_daddr  = Array($daddr, true)
+
+  file {
+    "/etc/ferm/dsa.d/${prio}_${name}":
+      ensure  => 'present',
+      mode    => '0400',
+      notify  => Exec['ferm reload'],
+      content => inline_template( @(EOF) ),
+                    domain (<%= @real_domain.join(' ') %>) {
+                      table <%= @table %> {
+                        <%-
+                        name = @name
+                        tail = "jump #{@target}"
+                        -%>
+                        <%=
+                          out = []
+                          [ [@filter_daddr, 'daddr', @real_daddr],
+                            [@filter_saddr, 'saddr', @real_saddr],
+                            [@filter_port , 'dport', @real_port ] ].each do |do_filter, filter_name, arr|
+                            next unless do_filter
+                            filter = "#{filter_name} (#{ arr.join(' ') })"
+                            if (arr.size > 2) then
+                              target = "#{name}-#{filter_name}"; prev_tail = tail; tail = "jump #{target}"
+                              out << "chain #{target} { #{filter} #{prev_tail}; }"
+                            else
+                              tail = "#{filter} #{tail}"
+                            end
+                          end
+                          out << "chain #{@chain} proto (#{ @real_proto.join(' ') }) #{tail};"
+                          out.join("\n")
+                        %>
+                      }
+                    }
+                    | EOF
+  }
+}
index 1611be1..49a9663 100644 (file)
@@ -55,9 +55,9 @@ class named::geodns inherits named {
       | EOF
   }
 
-  ferm::rule { '01-dsa-bind':
-    domain      => '(ip ip6)',
+  ferm::rule::simple { '01-dsa-bind':
     description => 'Allow nameserver access',
-    rule        => '&TCP_UDP_SERVICE(53)'
+    proto       => ['udp', 'tcp'],
+    port        => 'domain',
   }
 }