From 91a44682cfc6f66bf5277fc5ece9c383419a4e5c Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 12 Sep 2021 18:28:46 +0500 Subject: [PATCH] Add existing code --- .gitignore | 1 + LICENSE | 21 +++++++++++++++ defaults/main.yml | 8 ++++++ handlers/main.yml | 6 +++++ meta/main.yml | 24 +++++++++++++++++ tasks/install.yml | 30 ++++++++++++++++++++++ tasks/main.yml | 13 ++++++++++ tasks/purge.yml | 13 ++++++++++ tasks/remove.yml | 8 ++++++ templates/rules.v4 | 53 ++++++++++++++++++++++++++++++++++++++ templates/rules.v6 | 64 ++++++++++++++++++++++++++++++++++++++++++++++ vars/main.yml | 4 +++ 12 files changed, 245 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/install.yml create mode 100644 tasks/main.yml create mode 100644 tasks/purge.yml create mode 100644 tasks/remove.yml create mode 100644 templates/rules.v4 create mode 100644 templates/rules.v6 create mode 100644 vars/main.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..83eeb06 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Alex Kotov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..4077575 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,8 @@ +--- +iptables__state: install +iptables__drop_by_default: false +iptables__allow_output_ifaces: [] +iptables__v4_filter_prepend: null +iptables__v4_filter_append: null +iptables__v6_filter_prepend: null +iptables__v6_filter_append: null diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..2467e24 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Load iptables rules for IPv4 + shell: 'cat {{ iptables__conf_ipv4 }} | iptables-restore' + +- name: Load iptables rules for IPv6 + shell: 'cat {{ iptables__conf_ipv6 }} | ip6tables-restore' diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..ebd9bba --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,24 @@ +--- +allow_duplicates: false +dependencies: [] + +galaxy_info: + role_name: iptables + author: Alex Kotov + description: Common configuration + license: MIT + min_ansible_version: 2.8 + + galaxy_tags: + - iptables + + platforms: + - name: Debian + versions: + - stretch # Debian 9 Stretch + - buster # Debian 10 Buster + - name: Ubuntu + versions: + - xenial # Ubuntu 16.04 LTS Xenial Xerus + - bionic # Ubuntu 18.04 LTS Bionic Beaver + - focal # Ubuntu 20.04 LTS Focal Fossa diff --git a/tasks/install.yml b/tasks/install.yml new file mode 100644 index 0000000..3a35b2e --- /dev/null +++ b/tasks/install.yml @@ -0,0 +1,30 @@ +--- +- name: Install iptables-persistent + apt: + name: iptables-persistent + +- name: Create directory for iptables configuration + file: + state: directory + path: '{{ iptables__conf_dir }}' + mode: 'u=rwx,go=rx' + owner: root + group: root + +- name: Install iptables rules for IPv4 + template: + src: templates/rules.v4 + dest: '{{ iptables__conf_ipv4 }}' + mode: 'u=rw,go=r' + owner: root + group: root + notify: Load iptables rules for IPv4 + +- name: Install iptables rules for IPv6 + template: + src: templates/rules.v6 + dest: '{{ iptables__conf_ipv6 }}' + mode: 'u=rw,go=r' + owner: root + group: root + notify: Load iptables rules for IPv6 diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..4dcaade --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- fail: + msg: 'Invalid `iptables__state`: {{ iptables__state }}' + when: (iptables__state != None) and + (iptables__state != 'purge') and + (iptables__state != 'remove') and + (iptables__state != 'install') +- include_tasks: purge.yml + when: iptables__state == 'purge' +- include_tasks: remove.yml + when: iptables__state == 'remove' +- include_tasks: install.yml + when: iptables__state == 'install' diff --git a/tasks/purge.yml b/tasks/purge.yml new file mode 100644 index 0000000..95eec5c --- /dev/null +++ b/tasks/purge.yml @@ -0,0 +1,13 @@ +--- +- name: Purge iptables-persistent + apt: + state: absent + purge: true + name: + - iptables-persistent + - netfilter-persistent + +- name: Delete iptables-persistent configuration + file: + state: absent + path: '{{ iptables__conf_dir }}' diff --git a/tasks/remove.yml b/tasks/remove.yml new file mode 100644 index 0000000..4e26fd7 --- /dev/null +++ b/tasks/remove.yml @@ -0,0 +1,8 @@ +--- +- name: Uninstall iptables-persistent + apt: + state: absent + purge: false + name: + - iptables-persistent + - netfilter-persistent diff --git a/templates/rules.v4 b/templates/rules.v4 new file mode 100644 index 0000000..33186be --- /dev/null +++ b/templates/rules.v4 @@ -0,0 +1,53 @@ +######## +*filter +######## + +:INPUT {{ 'DROP' if iptables__drop_by_default else 'ACCEPT' }} [0:0] +:FORWARD DROP [0:0] +:OUTPUT {{ 'DROP' if iptables__drop_by_default else 'ACCEPT' }} [0:0] + +# Remove all rules from all chains, +# delete all user-defined chains. +-F +-X + +{{ iptables__v4_filter_prepend }} + +# 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 traffic. +{% if iptables__allow_output_ifaces %} +{% for iface in iptables__allow_output_ifaces %} +-A OUTPUT -o {{ iface }} -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -i {{ iface }} -m conntrack --ctstate ESTABLISHED -j ACCEPT +{% endfor %} +{% else %} +-A OUTPUT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT +{% endif %} + +# Allow some important ICMP. +-A INPUT -p icmp --icmp-type echo-request -j ACCEPT +-A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT +-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT +-A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT +-A INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT +-A OUTPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT +-A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT +-A OUTPUT -p icmp --icmp-type time-exceeded -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 + +{{ iptables__v4_filter_append }} + +COMMIT diff --git a/templates/rules.v6 b/templates/rules.v6 new file mode 100644 index 0000000..bca10ad --- /dev/null +++ b/templates/rules.v6 @@ -0,0 +1,64 @@ +######## +*filter +######## + +:INPUT {{ 'DROP' if iptables__drop_by_default else 'ACCEPT' }} [0:0] +:FORWARD DROP [0:0] +:OUTPUT {{ 'DROP' if iptables__drop_by_default else 'ACCEPT' }} [0:0] + +# Remove all rules from all chains, +# delete all user-defined chains. +-F +-X + +{{ iptables__v6_filter_prepend }} + +# 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 traffic. +{% if iptables__allow_output_ifaces %} +{% for iface in iptables__allow_output_ifaces %} +-A OUTPUT -o {{ iface }} -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -i {{ iface }} -m conntrack --ctstate ESTABLISHED -j ACCEPT +{% endfor %} +{% else %} +-A OUTPUT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT +-A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT +{% endif %} + +# Allow some important ICMP. +-A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT +# TODO: maybe it's better to only allow these inside private network? +-A INPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type neighbour-solicitation -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type neighbour-solicitation -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type neighbour-advertisement -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type neighbour-advertisement -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type redirect -j ACCEPT +-A OUTPUT -p icmpv6 --icmpv6-type redirect -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 + +{{ iptables__v6_filter_append }} + +COMMIT diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..701e92d --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,4 @@ +--- +iptables__conf_dir: '/etc/iptables' +iptables__conf_ipv4: '{{ iptables__conf_dir }}/rules.v4' +iptables__conf_ipv6: '{{ iptables__conf_dir }}/rules.v6'