From 9a4bc6a81cf0cd4a56ba458fadac830a2c4df529 Mon Sep 17 00:00:00 2001 From: Trey Dockendorf Date: Fri, 31 Jan 2020 09:13:19 -0500 Subject: [PATCH] Add random_fully support --- lib/puppet/provider/firewall/ip6tables.rb | 6 ++++ lib/puppet/provider/firewall/iptables.rb | 12 ++++++- lib/puppet/type/firewall.rb | 14 +++++++++ .../firewall_attributes_exceptions_spec.rb | 31 +++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/puppet/provider/firewall/ip6tables.rb b/lib/puppet/provider/firewall/ip6tables.rb index 9d3c3c0..089ab94 100644 --- a/lib/puppet/provider/firewall/ip6tables.rb +++ b/lib/puppet/provider/firewall/ip6tables.rb @@ -49,6 +49,12 @@ Puppet::Type.type(:firewall).provide :ip6tables, parent: :iptables, source: :ip6 '--set-xmark' end + kernelversion = Facter.value('kernelversion') + if (kernelversion && Puppet::Util::Package.versioncmp(kernelversion, '3.13') >= 0) && + (ip6tables_version && Puppet::Util::Package.versioncmp(ip6tables_version, '1.6.2') >= 0) + has_feature :random_fully + end + def initialize(*args) ip6tables_version = Facter.value('ip6tables_version') raise ArgumentError, 'The ip6tables provider is not supported on version 1.3 of iptables' if ip6tables_version && ip6tables_version.match(%r{1\.3\.\d}) diff --git a/lib/puppet/provider/firewall/iptables.rb b/lib/puppet/provider/firewall/iptables.rb index ae22900..75e3e49 100644 --- a/lib/puppet/provider/firewall/iptables.rb +++ b/lib/puppet/provider/firewall/iptables.rb @@ -59,6 +59,12 @@ Puppet::Type.type(:firewall).provide :iptables, parent: Puppet::Provider::Firewa '--set-xmark' end + kernelversion = Facter.value('kernelversion') + if (kernelversion && Puppet::Util::Package.versioncmp(kernelversion, '3.13') >= 0) && + (iptables_version && Puppet::Util::Package.versioncmp(iptables_version, '1.6.2') >= 0) + has_feature :random_fully + end + @protocol = 'IPv4' @resource_map = { @@ -115,6 +121,7 @@ Puppet::Type.type(:firewall).provide :iptables, parent: Puppet::Provider::Firewa proto: '-p', queue_num: '--queue-num', queue_bypass: '--queue-bypass', + random_fully: '--random-fully', random: '--random', rdest: '--rdest', reap: '--reap', @@ -195,6 +202,7 @@ Puppet::Type.type(:firewall).provide :iptables, parent: Puppet::Provider::Firewa :clamp_mss_to_pmtu, :isfragment, :log_uid, + :random_fully, :random, :rdest, :reap, @@ -319,7 +327,7 @@ Puppet::Type.type(:firewall).provide :iptables, parent: Puppet::Provider::Firewa :string_from, :string_to, :jump, :goto, :clusterip_new, :clusterip_hashmode, :clusterip_clustermac, :clusterip_total_nodes, :clusterip_local_node, :clusterip_hash_init, :queue_num, :queue_bypass, :nflog_group, :nflog_prefix, :nflog_range, :nflog_threshold, :clamp_mss_to_pmtu, :gateway, - :set_mss, :set_dscp, :set_dscp_class, :todest, :tosource, :toports, :to, :checksum_fill, :random, :log_prefix, + :set_mss, :set_dscp, :set_dscp_class, :todest, :tosource, :toports, :to, :checksum_fill, :random_fully, :random, :log_prefix, :log_level, :log_uid, :reject, :set_mark, :match_mark, :mss, :connlimit_above, :connlimit_mask, :connmark, :time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone, :src_cc, :dst_cc, :hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst, @@ -493,6 +501,8 @@ Puppet::Type.type(:firewall).provide :iptables, parent: Puppet::Provider::Firewa values.sub(%r{\s-f(?!l)(?=.*--comment)}, ' -f true') elsif resource_map[bool].eql?(%r{'--physdev-is-\S+'}) values.sub(%r{'#{resource_map[bool]} "! "'}, "#{resource_map[bool]} true") + elsif bool == :random + values.sub(%r{#{resource_map[bool]}(\s|$)(?!"!")}, "#{resource_map[bool]} true") else # append `true` to booleans that are not already negated (followed by "!") values.sub(%r{#{resource_map[bool]}(?! "!")}, "#{resource_map[bool]} true") diff --git a/lib/puppet/type/firewall.rb b/lib/puppet/type/firewall.rb index a837da4..d0cc10a 100644 --- a/lib/puppet/type/firewall.rb +++ b/lib/puppet/type/firewall.rb @@ -133,6 +133,8 @@ Puppet::Type.newtype(:firewall) do * ipvs: The ability to match IP Virtual Server packets. * ct_target: The ability to set connection tracking parameters for a packet or its associated connection. + + * random_fully: The ability to use --random-fully flag. PUPPETCODE feature :connection_limiting, 'Connection limiting features.' @@ -179,6 +181,7 @@ Puppet::Type.newtype(:firewall) do feature :bpf, 'Berkeley Paket Filter feature' feature :ipvs, 'Packet belongs to an IP Virtual Server connection' feature :ct_target, 'The ability to set connection tracking parameters for a packet or its associated connection' + feature :random_fully, 'The ability to use --random-fully flag' # provider specific features feature :iptables, 'The provider provides iptables features.' @@ -721,6 +724,17 @@ Puppet::Type.newtype(:firewall) do PUPPETCODE end + newproperty(:random_fully, required_features: :random_fully) do + desc <<-PUPPETCODE + When using a jump value of "MASQUERADE", "DNAT", "REDIRECT", or "SNAT" + this boolean will enable fully randomized port mapping. + + **NOTE** Requires Kernel >= 3.13 and iptables >= 1.6.2 + PUPPETCODE + + newvalues(:true, :false) + end + newproperty(:random, required_features: :dnat) do desc <<-PUPPETCODE When using a jump value of "MASQUERADE", "DNAT", "REDIRECT", or "SNAT" diff --git a/spec/acceptance/firewall_attributes_exceptions_spec.rb b/spec/acceptance/firewall_attributes_exceptions_spec.rb index c19e1f1..03937a7 100644 --- a/spec/acceptance/firewall_attributes_exceptions_spec.rb +++ b/spec/acceptance/firewall_attributes_exceptions_spec.rb @@ -1338,4 +1338,35 @@ describe 'firewall basics', docker: true do expect(result.stdout).to match(%r{-A INPUT -p tcp -m hashlimit --hashlimit-upto 16\/sec --hashlimit-burst 640 --hashlimit-name upto --hashlimit-htable-size 1310000 --hashlimit-htable-max 320000 --hashlimit-htable-expire 36000000 -m comment --comment "806 - hashlimit_upto test" -j ACCEPT}) # rubocop:disable Metrics/LineLength : Cannot reduce line to required length end end + + describe 'random-fully' do + supports_random_fully = if os[:family] == 'redhat' && os[:release].start_with?('8') + true + elsif os[:family] == 'debian' && os[:release].start_with?('10') + true + else + false + end + + before(:all) do + pp = <<-PUPPETCODE + firewall { '901 - set random-fully': + table => 'nat', + chain => 'POSTROUTING', + jump => 'MASQUERADE', + random_fully => true, + } + PUPPETCODE + idempotent_apply(pp) + end + + let(:result) { run_shell('iptables-save') } + + it 'adds random-fully rule', if: supports_random_fully do + expect(result.stdout).to match(%r{-A POSTROUTING -p tcp -m comment --comment "901 - set random-fully" -j MASQUERADE --random-fully}) + end + it 'adds rule without random-fully', unless: supports_random_fully do + expect(result.stdout).to match(%r{-A POSTROUTING -p tcp -m comment --comment "901 - set random-fully" -j MASQUERADE}) + end + end end -- 2.45.2