diff --git a/lib/facter/fw_builder_is_docker.rb b/lib/facter/fw_builder_is_docker.rb new file mode 100644 index 0000000000000000000000000000000000000000..6388b74e49a41b2117f45a65f52a6bd9316270d5 --- /dev/null +++ b/lib/facter/fw_builder_is_docker.rb @@ -0,0 +1,9 @@ +Facter.add(:fw_builder_is_docker) do + setcode do + if Facter::Util::Resolution.which('docker') + true + else + false + end + end +end diff --git a/manifests/chains.pp b/manifests/chains.pp new file mode 100644 index 0000000000000000000000000000000000000000..4b21c21abfa27068a675275d920e13400ffee7cb --- /dev/null +++ b/manifests/chains.pp @@ -0,0 +1,112 @@ +# == Class: fw_builder::chains +# +# Pre IPtables allows several icmp type, loopback connection +# either on IPv6 and IPv4 +# +# This class opens the firewall to Geant specific servers +# +# === Parameters +# +# === Requires +# +# === Examples +# +class fw_builder::chains ( + $ipv4_enable, + $ipv6_enable +) { + + assert_private() + + if ($ipv4_enable) { + ['udp', 'tcp', 'trust', 'public'].each | $chain | { + firewallchain { "INPUT_${chain}:filter:IPv4": + ensure => present; + } + } + firewall { + default: + chain => 'INPUT', + action => accept, + provider => 'iptables'; + '010 accept all icmp for provider iptables': + proto => 'icmp'; + '003 accept inbound related established rules for provider iptables': + proto => all, + state => ['RELATED', 'ESTABLISHED']; + } + firewall { + default: + chain => 'INPUT', + jump => 'INPUT_public', + state => ['NEW'], + provider => 'ip6tables'; + '090 IPv4 UDP INPUT_public for all public services': + proto => 'udp'; + '090 IPv4 TCP INPUT_public for all public services': + proto => 'tcp'; + } + firewall { '095 IPv4 INPUT_trust this is for all ip ranges (mostly internal)': + chain => 'INPUT', + proto => all, + state => ['NEW'], + jump => 'INPUT_trust', + ipset => 'trusted_networks_v4 src', + provider => 'iptables'; + } + firewall { '001 IPv4 accept all inbound to localhost': + chain => 'INPUT', + proto => all, + iniface => 'lo', + action => accept, + provider => 'iptables'; + } + } + + if ($ipv6_enable) { + ['udp', 'tcp', 'trust', 'public'].each | $chain | { + firewallchain { "INPUT_${chain}:filter:IPv6": + ensure => present, + } + } + firewall { + default: + chain => 'INPUT', + action => accept, + provider => 'ip6tables'; + '010 accept all icmp for provider ip6tables': + proto => 'ipv6-icmp'; + '003 accept inbound related established rules for provider ip6tables': + proto => all, + state => ['RELATED', 'ESTABLISHED']; + } + firewall { + default: + chain => 'INPUT', + jump => 'INPUT_public', + state => ['NEW'], + provider => 'ip6tables'; + '090 IPv6 UDP INPUT_public for all public services': + proto => 'udp'; + '090 IPv6 TCP INPUT_public for all public services': + proto => 'tcp'; + } + firewall { '095 IPv6 INPUT_trust this is for all ip ranges (mostly internal)': + chain => 'INPUT', + proto => all, + state => ['NEW'], + jump => 'INPUT_trust', + ipset => 'trusted_networks_v6 src', + provider => 'ip6tables'; + } + firewall { '001 IPv6 accept all inbound to localhost6': + chain => 'INPUT', + proto => all, + iniface => 'lo', + action => accept, + provider => 'ip6tables'; + } + } + +} +# vim:ts=2:sw=2 diff --git a/manifests/docker.pp b/manifests/docker.pp new file mode 100644 index 0000000000000000000000000000000000000000..0ba5dc2c1e7141da52202a6be758df7c5fb3ee11 --- /dev/null +++ b/manifests/docker.pp @@ -0,0 +1,64 @@ +# == Class: fw_builder::docker +# +# Pre IPtables allows several icmp type, loopback connection +# either on IPv6 and IPv4 +# +# This class opens the firewall to Geant specific servers +# +# === Parameters +# +# === Requires +# +# === Examples +# +class fw_builder::docker ( + $manage_docker, + $ipv4_enable, + $ipv6_enable +) { + + assert_private() + + # IPv6 IS STILL MISSING + + firewallchain { ['INPUT:filter:IPv4', 'OUTPUT:filter:IPv4']: + purge => true, + ignore => ['docker', 'br-', 'cali-', 'KUBE'], + } + + firewallchain { 'FORWARD:filter:IPv4': + purge => true, + ignore => ['docker', 'br-', 'cali-', 'KUBE'], + } + + firewallchain { ['DOCKER:nat:IPv4', 'DOCKER:filter:IPv4']: + purge => false, + } + + firewallchain { 'POSTROUTING:nat:IPv4': + purge => false, + } + + firewallchain { [ + 'INPUT:nat:IPv4', 'PREROUTING:nat:IPv4', + 'OUTPUT:nat:IPv4', 'PREROUTING:mangle:IPv4', + 'POSTROUTING:mangle:IPv4', 'INPUT:mangle:IPv4', + 'FORWARD:mangle:IPv4', 'OUTPUT:mangle:IPv4', + 'OUTPUT:raw:IPv4', 'PREROUTING:raw:IPv4' + ]: + purge => true, + ignore => ['DOCKER', 'cali-', 'KUBE'], + } + + # this is is for kube / cali + firewallchain { [ + 'cali-PREROUTING:mangle:IPv4', 'cali-failsafe-in:mangle:IPv4', + 'cali-from-host-endpoint:mangle:IPv4', 'cali-failsafe-in:raw:IPv4', + 'cali-failsafe-out:raw:IPv4', 'cali-from-host-endpoint:raw:IPv4', + 'cali-to-host-endpoint:raw:IPv4', 'KUBE-SERVICES:filter:IPv4' + ]: + purge => false, + } + +} +# vim:ts=2:sw=2 diff --git a/manifests/init.pp b/manifests/init.pp index dad27e829e53f357322e69b9b619afaa253c3896..a2ec1d65ccc34ada6d5fafeab9f29208a980868b 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -5,6 +5,84 @@ # Pete Pedersen<pete.pedersen@geant.org> # Massimiliano Adamo<massimiliano.adamo@geant.org> # -class fw_builder { - # resources +class fw_builder ( + Array $trusted_networks, + Boolean $manage_docker = false, + Boolean $ipv4_enable = true, + Boolean $ipv6_enable = true, + Boolean $logging = true, + Boolean $purge_rules = true, + Integer $log_rotation_days = '7', + $ipset_package_ensure = 'present', + $limit = '1000/sec' +) { + + if ! ($purge_rules) and ($manage_docker) { + fail('cannot set purge_rules to false and manage_docker to true') + } + + if ! ($ipv4_enable) and ! ($ipv6_enable) { + fail('you cannot disable ipv4 and ipv6 at the same time') + } + + if ($ipv4_enable) and ($ipv6_enable) { + $ip_proto_array = ['ip6tables', 'iptables'] + } elsif ($ipv4_enable) and ! ($ipv6_enable) { + $ip_proto_array = ['iptables'] + } elsif ! ($ipv4_enable) and ($ipv6_enable) { + $ip_proto_array = ['iptables'] + } + + class { + 'fw_builder::ipset': + ipset_package_ensure => $ipset_package_ensure, + trusted_networks => $trusted_networks, + ipv4_enable => $ipv4_enable, + ipv6_enable => $ipv6_enable, + before => Class['fw_builder::chains', 'fw_builder::docker']; + 'fw_builder::chains': + ipv4_enable => $ipv4_enable, + ipv6_enable => $ipv6_enable; + 'fw_builder::post': + ipv4_enable => $ipv4_enable, + ipv6_enable => $ipv6_enable, + limit => $limit; + 'fw_builder::logrotate': + logging => $logging, + log_rotation_days => $log_rotation_days, + } + + if ($purge_rules) { + if ($facts['fw_builder_is_docker']) and ($manage_docker) { + echo { 'Docker detected': + message => 'not purging iptables rules set by docker'; + } + resources { 'firewallchain': + purge => false; + } + class { 'fw_builder::docker': + ipv4_enable => $ipv4_enable, + ipv6_enable => $ipv6_enable; + } + } else { + if ($ipv4_enable) { + firewallchain { 'FORWARD:filter:IPv4': + ensure => present, + policy => drop, + purge => true; + } + } + if ($ipv6_enable) { + firewallchain { 'FORWARD:filter:IPv6': + ensure => present, + policy => drop, + purge => true; + } + } + resources { 'firewall': + purge => true; + } + } + } + } diff --git a/manifests/ipset.pp b/manifests/ipset.pp new file mode 100644 index 0000000000000000000000000000000000000000..23f4459867917dd53e85d70671402dd608d2757b --- /dev/null +++ b/manifests/ipset.pp @@ -0,0 +1,49 @@ +# Class: fw_builder::ipset +# +# +class fw_builder::ipset ( + $trusted_networks, + $ipset_package_ensure, + $ipv4_enable, + $ipv6_enable +) { + + assert_private() + + $firewall_service = $facts['os']['family'] ? { + 'Debian' => 'netfilter-persistent.service', + default => undef + } + + $packages = "${facts['os']['family']}_${facts['os']['release']['major']}" ? { + 'RedHat_6' => ['ipset'], + default => undef + } + + class { 'ipset': + packages => $packages, + package_ensure => $ipset_package_ensure, + firewall_service => $firewall_service + } + + if ($ipv4_enable) { + $trusted_networks_v4 = $trusted_networks.filter |$ip_range| { $ip_range =~ Stdlib::IP::Address::V4 } + ipset::set { 'trusted_networks_v4': + ensure => 'present', + type => 'hash:net', + set => $trusted_networks_v4; + } + } + + if ($ipv6_enable) { + $trusted_networks_v6 = $trusted_networks.filter |$ip_range| { $ip_range =~ Stdlib::IP::Address::V6 } + ipset::set { 'trusted_networks_v6': + ensure => 'present', + type => 'hash:net', + set => $trusted_networks_v6, + options => {'family' => 'inet6'} + } + } + +} +# vim:ts=2:sw=2 diff --git a/manifests/logrotate.pp b/manifests/logrotate.pp new file mode 100644 index 0000000000000000000000000000000000000000..168916319f950783c7a9b63d5a38dc83add14452 --- /dev/null +++ b/manifests/logrotate.pp @@ -0,0 +1,29 @@ +# == Class: fw_builder +# +# == Authors: +# +# Pete Pedersen<pete.pedersen@geant.org> +# Massimiliano Adamo<massimiliano.adamo@geant.org> +# +class fw_builder::logrotate ( + $logging, + $log_rotation_days, +) { + + assert_private() + + file { ['/var/log/iptables.log', '/var/log/ip6tables.log']: ensure => file; } + + if ($logging) { + logrotate::rule { 'iptables': + rotate => $log_rotation_days, + dateext => true, + copytruncate => true, + missingok => true, + compress => true, + ifempty => false, + path => '/var/log/ip*tables.log'; + } + } + +} diff --git a/manifests/post.pp b/manifests/post.pp new file mode 100644 index 0000000000000000000000000000000000000000..08b5d43b301fed39309aaeec65bb5b6f5ac56514 --- /dev/null +++ b/manifests/post.pp @@ -0,0 +1,46 @@ +# == Class: fw_builder::post +# +class fw_builder::post ( + $ipv4_enable, + $ipv6_enable, + $logging, + $limit +) { + + assert_private() + + if ($logging) { + $fw_builder::ip_proto_array.each | String $provider | { + firewall { + default: + chain => 'INPUT', + provider => $provider, + jump => 'LOG', + limit => $limit, + log_level => '4'; + "889 log RST dropped inbound chain for provider ${provider}": + log_prefix => "[${provider.upcase()} RST RST] dropped"; + "900 log dropped inbound chain for provider ${provider}": + proto => all, + log_prefix => "[${provider.upcase()} INPUT] dropped ", + } + } + } + + $fw_builder::ip_proto_array.each | String $provider | { + firewall { + default: + chain => 'INPUT', + provider => $provider; + "910 deny all other inbound requests for provider ${provider}": + before => undef, + proto => all, + action => 'drop'; + "890 drop RST RST connections for provider ${provider}": + tcp_flags => 'RST RST', + action => 'drop'; + } + } + +} +# vim:ts=2:sw=2