diff --git a/handlers/main.yml b/handlers/main.yml index 93b81d4..322e192 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -4,3 +4,9 @@ daemon_reload: true name: sshd state: restarted + +- name: common | Load iptables rules for IPv4 + shell: 'cat {{ common__conf_ipv4 }} | iptables-restore' + +- name: common | Load iptables rules for IPv6 + shell: 'cat {{ common__conf_ipv6 }} | ip6tables-restore' diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py index 2b8e047..1a823c0 100644 --- a/molecule/default/tests/test_default.py +++ b/molecule/default/tests/test_default.py @@ -9,7 +9,14 @@ testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( @pytest.mark.parametrize( 'package_name', - ['bash-completion', 'colordiff', 'curl', 'less', 'vim'], + [ + 'bash-completion', + 'colordiff', + 'curl', + 'iptables-persistent', + 'less', + 'vim', + ], ) def test_packages(host, package_name): assert host.package(package_name).is_installed @@ -31,3 +38,14 @@ def test_default_editor(host): assert f.exists assert f.is_symlink assert f.linked_to == '/usr/bin/vim.basic' + + +@pytest.mark.parametrize('version', [4, 6]) +def test_iptables_config(host, version): + f = host.file('/etc/iptables/rules.v%d' % version) + + assert f.exists + assert f.is_file + assert f.user == 'root' + assert f.group == 'root' + assert f.mode == 0o644 diff --git a/tasks/iptables.yml b/tasks/iptables.yml new file mode 100644 index 0000000..fc592de --- /dev/null +++ b/tasks/iptables.yml @@ -0,0 +1,31 @@ +--- +- name: Install iptables-persistent + apt: + update_cache: true + name: iptables-persistent + +- name: Create directory for iptables configuration + file: + state: directory + path: '{{ common__conf_dir }}' + mode: 'u=rwx,g=rx,o=rx' + owner: root + group: root + +- name: Install iptables rules for IPv4 + template: + src: templates/rules.v4 + dest: '{{ common__conf_ipv4 }}' + mode: 'u=rw,g=r,o=r' + owner: root + group: root + notify: common | Load iptables rules for IPv4 + +- name: Install iptables rules for IPv6 + template: + src: templates/rules.v6 + dest: '{{ common__conf_ipv6 }}' + mode: 'u=rw,g=r,o=r' + owner: root + group: root + notify: common | Load iptables rules for IPv6 diff --git a/tasks/main.yml b/tasks/main.yml index 4884b0e..4315e38 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,3 +1,4 @@ --- - include_tasks: usability.yml - include_tasks: ssh.yml +- include_tasks: iptables.yml diff --git a/templates/rules.v4 b/templates/rules.v4 new file mode 100644 index 0000000..e29ac89 --- /dev/null +++ b/templates/rules.v4 @@ -0,0 +1,44 @@ +######## +*filter +######## + +:INPUT ACCEPT [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] + +# Remove all rules from all chains, +# delete all user-defined chains. +-F +-X + +# Allow all loopback (lo) traffic and reject anything +# to localhost that does not originate from lo. +-A INPUT -i lo -j ACCEPT +-A INPUT ! -i lo -s 127.0.0.0/8 -j REJECT +-A OUTPUT -o lo -j ACCEPT + +# Allow all outgoing clearnet traffic. +-A OUTPUT -o eth0 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -i eth0 -m conntrack --ctstate ESTABLISHED -j ACCEPT + +# Allow all outgoing private network traffic. +-A OUTPUT -o eth1 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -i eth1 -m conntrack --ctstate ESTABLISHED -j ACCEPT + +# Allow incoming ICMP ping. +-A INPUT -p icmp --icmp-type echo-request -j ACCEPT +-A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT + +# Allow outgoing ICMP ping. +-A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT +-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT + +# Deny other ICMP. +-A INPUT -p icmp -j DROP +-A OUTPUT -p icmp -j DROP + +# Allow incoming SSH. +-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT + +COMMIT diff --git a/templates/rules.v6 b/templates/rules.v6 new file mode 100644 index 0000000..261a4b1 --- /dev/null +++ b/templates/rules.v6 @@ -0,0 +1,44 @@ +######## +*filter +######## + +:INPUT ACCEPT [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] + +# Remove all rules from all chains, +# delete all user-defined chains. +-F +-X + +# Allow all loopback (lo) traffic and reject anything +# to localhost that does not originate from lo. +-A INPUT -i lo -j ACCEPT +-A INPUT ! -i lo -s ::/128 -j REJECT +-A OUTPUT -o lo -j ACCEPT + +# Allow all outgoing clearnet traffic. +-A OUTPUT -o eth0 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -i eth0 -m conntrack --ctstate ESTABLISHED -j ACCEPT + +# Allow all outgoing private network traffic. +-A OUTPUT -o eth1 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -i eth1 -m conntrack --ctstate ESTABLISHED -j ACCEPT + +# Allow incoming ICMPv6 ping. +-A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT + +# Allow outgoing ICMPv6 ping. +-A OUTPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT + +# Deny other ICMPv6. +-A INPUT -p icmpv6 -j DROP +-A OUTPUT -p icmpv6 -j DROP + +# Allow incoming SSH. +-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT + +COMMIT diff --git a/vars/main.yml b/vars/main.yml index ed97d53..8a21aab 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1 +1,4 @@ --- +common__conf_dir: '/etc/iptables' +common__conf_ipv4: '{{ common__conf_dir }}/rules.v4' +common__conf_ipv6: '{{ common__conf_dir }}/rules.v6'