# A simple ferm rule. # # This rule will send IPv4 and/or IPv6 traffic using either TCP and/or UDP # optionally going to a port, optionally from/to addresses/networks from # one table (INPUT by default) to some target (ACCEPT by default). # # Sample uses: # # ferm::rule::simple { '01-dsa-bind': # description => 'Allow nameserver access', # proto => ['udp', 'tcp'], # port => 'domain', # } # # or: # # ferm::rule::simple { 'dsa-smtp': # description => 'Allow smtp access from the world', # port => '25', # } # # or: # # @@ferm::rule::simple { "submission-from-${::fqdn}": # tag => 'smtp::server::submission::to::mail-relay', # chain => 'submission', # saddr => $base::public_addresses, # } # combined with: # ferm::rule::simple { 'submission-from-satellites': # target => 'submission', # port => 'submission', # } # Ferm::Rule::Simple <<| tag == 'smtp::server::submission::to::mail-relay' |>> # # # @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 %> { <%- # netfilter chain names are limited to 28 characters, so if name is too long, we'll have to do something about that name = @name if name.size > 20 then require 'digest' name = 'dgst-' + Digest::SHA256.hexdigest(name)[0,15] end 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 } }