This adds four new features to the firewall type: nflog_groups, _range, _prefix, and _threshold. Unit tests and acceptance tests were also added.
}
~~~
+Setup NFLOG for a rule.
+
+~~~puppet
+firewall {'666 for NFLOG':
+ proto => 'all',
+ jump => 'NFLOG',
+ nflog_group => 3,
+ nflog_prefix => "nflog-test",
+ nflog_range = 256,
+ nflog_threshold => 1,
+}
+~~~
+
### Additional Information
Access the inline documentation:
* `islastfrag`: If true, matches when the packet is the last fragment of a fragmented ipv6 packet. Supported by ipv6 only. Valid values are 'true', 'false'. Requires the `islastfrag`.
-* `jump`: The value for the iptables `--jump` parameter. Any valid chain name is allowed, but normal values are: 'QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'MASQUERADE', 'REDIRECT', 'MARK', 'TCPMSS', 'DSCP'.
+* `jump`: The value for the iptables `--jump` parameter. Any valid chain name is allowed, but normal values are: 'QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'MASQUERADE', 'REDIRECT', 'MARK', 'TCPMSS', 'DSCP', 'NFLOG'.
For the values 'ACCEPT', 'DROP', and 'REJECT', you must use the generic `action` parameter. This is to enforce the use of generic parameters where possible for maximum cross-platform modeling.
* `log_uid`: The ability to log the userid of the process which generated the packet.
+* `nflog_group`: When combined with `jump => 'NFLOG'` grants the ability to specify the NFLOG group number. Requires the `nflog_group` feature.
+
+* `nflog_prefix`: When combined with `jump => 'NFLOG'` grants the ability to specify a prefix for log entries. Requires the `nflog_prefix` feature.
+
+* `nflog_range`: When combined with `jump => 'NFLOG'` grants the ability to specify the number of bytes to be copied to userspace. Requires the `nflog_range` feature.
+
+* `nflog_threshold`: When combined with `jump => 'NFLOG'` grants the ability to specify the size of the NFLOG threshold. Requires the `nflog_threshold` feature.
+
* `mask`: Sets the mask to use when `recent` is enabled. Requires the `mask` feature.
* `month_days`: Only match on the given days of the month. Possible values are '1' to '31'. Note that specifying '31' will not match on months that do not have a 31st day; the same goes for 28- or 29-day February.
has_feature :log_uid
has_feature :mark
has_feature :mss
+ has_feature :nflog_group
+ has_feature :nflog_prefix
+ has_feature :nflog_range
+ has_feature :nflog_threshold
has_feature :tcp_flags
has_feature :pkttype
has_feature :isfragment
:match_mark => "-m mark --mark",
:mss => '-m tcpmss --mss',
:name => "-m comment --comment",
+ :nflog_group => "--nflog-group",
+ :nflog_prefix => "--nflog-prefix",
+ :nflog_range => "--nflog-range",
+ :nflog_threshold => "--nflog-threshold",
:outiface => "-o",
:pkttype => "-m pkttype --pkt-type",
:port => '-m multiport --ports',
:rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :string, :string_algo,
: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,
- :clamp_mss_to_pmtu, :gateway, :set_mss, :set_dscp, :set_dscp_class, :todest, :tosource, :toports, :to, :checksum_fill, :random, :log_prefix,
+ :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,
: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
- ]
+ :src_cc, :dst_cc ]
def insert
debug 'Inserting rule %s' % resource[:name]
end
end
-
# Convert booleans removing the previous cludge we did
@known_booleans.each do |bool|
unless [nil, 'true', '!'].include?(hash[bool])
feature :ipsec_policy, "Match IPsec policy"
feature :ipsec_dir, "Match IPsec policy direction"
feature :mask, "Ability to match recent rules based on the ipv4 mask"
+ feature :nflog_group, "netlink group to subscribe to for logging"
+ feature :nflog_prefix, ""
+ feature :nflog_range, ""
+ feature :nflog_threshold, ""
feature :ipset, "Match against specified ipset list"
feature :clusterip, "Configure a simple cluster of nodes that share a certain IP and MAC address without an explicit load balancer in front of them."
feature :length, "Match the length of layer-3 payload"
* DNAT
* SNAT
* LOG
+ * NFLOG
* MASQUERADE
* REDIRECT
* MARK
newvalues(:true, :false)
end
+ newproperty(:nflog_group, :required_features => :nflog_group) do
+ desc <<-EOS
+ Used with the jump target NFLOG.
+ The netlink group (0 - 2^16-1) to which packets are (only applicable
+ for nfnetlink_log). Defaults to 0.
+ EOS
+
+ validate do |value|
+ if value.to_i > (2**16)-1 || value.to_i < 0
+ raise ArgumentError, "nflog_group must be between 0 and 2^16-1"
+ end
+ end
+
+ munge do |value|
+ if value.is_a?(String) and value =~ /^[-0-9]+$/
+ Integer(value)
+ else
+ value
+ end
+ end
+ end
+
+ newproperty(:nflog_prefix, :required_features => :nflog_prefix) do
+ desc <<-EOS
+ Used with the jump target NFLOG.
+ A prefix string to include in the log message, up to 64 characters long,
+ useful for distinguishing messages in the logs.
+ EOS
+
+ validate do |value|
+ if value.length > 64
+ raise ArgumentError, "nflog_prefix must be less than 64 characters."
+ end
+ end
+ end
+
+ newproperty(:nflog_range, :required_features => :nflog_range) do
+ desc <<-EOS
+ Used with the jump target NFLOG.
+ The number of bytes to be copied to userspace (only applicable for nfnetlink_log).
+ nfnetlink_log instances may specify their own range, this option overrides it.
+ EOS
+ end
+
+ newproperty(:nflog_threshold, :required_features => :nflog_threshold) do
+ desc <<-EOS
+ Used with the jump target NFLOG.
+ Number of packets to queue inside the kernel before sending them to userspace
+ (only applicable for nfnetlink_log). Higher values result in less overhead
+ per packet, but increase delay until the packets reach userspace. Defaults to 1.
+ EOS
+
+ munge do |value|
+ if value.is_a?(String) and value =~ /^[-0-9]+$/
+ Integer(value)
+ else
+ value
+ end
+ end
+ end
+
# ICMP matching property
newproperty(:icmp, :required_features => :icmp_match) do
desc <<-EOS
--- /dev/null
+require 'spec_helper_acceptance'
+
+describe 'nflog' do
+ describe 'nflog_group' do
+
+ let(:group) { 3 }
+
+ it 'applies' do
+ pp = <<-EOS
+ class {'::firewall': }
+ firewall { '503 - test':
+ jump => 'NFLOG',
+ proto => 'all',
+ nflog_group => #{group},
+ }
+ EOS
+ apply_manifest(pp, :catch_failures => true)
+ end
+
+ it 'contains the rule' do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(/NFLOG --nflog-group #{group}/)
+ end
+ end
+ end
+
+ describe 'nflog_prefix' do
+
+ let(:prefix) { "TEST PREFIX" }
+
+ it 'applies' do
+ pp = <<-EOS
+ class {'::firewall': }
+ firewall { '503 - test':
+ jump => 'NFLOG',
+ proto => 'all',
+ nflog_prefix => '#{prefix}',
+ }
+ EOS
+ apply_manifest(pp, :catch_failures => true)
+ end
+
+ it 'contains the rule' do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(/NFLOG --nflog-prefix "#{prefix}"/)
+ end
+ end
+ end
+
+ describe 'nflog_range' do
+
+ let(:range) { 16 }
+
+ it 'applies' do
+ pp = <<-EOS
+ class {'::firewall': }
+ firewall { '503 - test':
+ jump => 'NFLOG',
+ proto => 'all',
+ nflog_range => #{range},
+ }
+ EOS
+ apply_manifest(pp, :catch_failures => true)
+ end
+
+ it 'contains the rule' do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(/NFLOG --nflog-range #{range}/)
+ end
+ end
+ end
+
+ describe 'nflog_threshold' do
+
+ let(:threshold) { 2 }
+
+ it 'applies' do
+ pp = <<-EOS
+ class {'::firewall': }
+ firewall { '503 - test':
+ jump => 'NFLOG',
+ proto => 'all',
+ nflog_threshold => #{threshold},
+ }
+ EOS
+ apply_manifest(pp, :catch_failures => true)
+ end
+
+ it 'contains the rule' do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(/NFLOG --nflog-threshold #{threshold}/)
+ end
+ end
+ end
+
+ describe 'multiple rules' do
+ let(:threshold) { 2 }
+ let(:group) { 3 }
+
+ it 'applies' do
+ pp = <<-EOS
+ class {'::firewall': }
+ firewall { '503 - test':
+ jump => 'NFLOG',
+ proto => 'all',
+ nflog_threshold => #{threshold},
+ nflog_group => #{group}
+ }
+ EOS
+ apply_manifest(pp, :catch_failures => true)
+ end
+
+ it 'contains the rules' do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(/NFLOG --nflog-group #{group} --nflog-threshold #{threshold}/)
+ end
+ end
+
+ end
+end
expect(res.parameters[:jump]).to eql nil
end
- ['QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'MASQUERADE', 'REDIRECT', 'MARK'].each do |jump|
+ ['QUEUE', 'RETURN', 'DNAT', 'SNAT', 'LOG', 'NFLOG', 'MASQUERADE', 'REDIRECT', 'MARK'].each do |jump|
it "should accept jump value #{jump}" do
@resource[:jump] = jump
expect(@resource[:jump]).to eql jump
end
end
+ describe 'NFLOG' do
+ describe ':nflog_group' do
+
+ [0,1,5,10].each do |v|
+ it {
+ @resource[:nflog_group] = v
+ expect(@resource[:nflog_group]).to eq v
+ }
+ end
+
+ [-3,999999].each do |v|
+ it {
+ expect(lambda { @resource[:nflog_group] = v }).to raise_error(Puppet::Error, /2\^16\-1/)
+ }
+ end
+ end
+
+ describe ':nflog_prefix' do
+ let(:valid_prefix) { "This is a valid prefix" }
+ let(:invalid_prefix) { "This is not a valid prefix. !t is longer than 64 char@cters for sure. How do I know? I c0unted." }
+
+ it {
+ @resource[:nflog_prefix] = valid_prefix
+ expect(@resource[:nflog_prefix]).to eq valid_prefix
+ }
+
+ it {
+ expect(lambda { @resource[:nflog_prefix] = invalid_prefix }).to raise_error(Puppet::Error, /64 characters/)
+ }
+ end
+ end
+
describe ':icmp' do
icmp_codes = {
:iptables => {