diff --git a/README.md b/README.md index a43a99d..4be3420 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,67 @@ # firewall +Role Ansible pour déployer un pare-feu iptables/ip6tables via un script shell et un service systemd. + +## Prérequis + +- Distribution Debian/Ubuntu (gestion des paquets via apt) +- Privilèges root (become: true) +- Fact gathering activé (utilisé pour l'interface réseau par défaut) + +## Comportement + +- Installe iptables +- Déploie le script [templates/firewall.j2](templates/firewall.j2) +- Déploie le service systemd [files/firewall.service](files/firewall.service) +- Active et démarre le service firewall + +## Variables + +Variables par défaut dans [defaults/main.yml](defaults/main.yml). + +- firewall_public_interface: interface publique pour les logs optionnels. Si null, utilise ansible_default_ipv4.interface. +- firewall_admin_sources: liste des CIDR autorisés sur les services admin. +- firewall_admin_rules_ipv4: liste des règles IPv4 limitées aux sources admin. +- firewall_public_tcp_ports_ipv4: ports TCP IPv4 ouverts publiquement. +- firewall_public_tcp_ports_ipv6: ports TCP IPv6 ouverts publiquement. + +## Exemple d'inventaire + +```yaml +firewall_admin_sources: + - cidr: "203.0.113.10/32" + comment: "bastion" + +firewall_admin_rules_ipv4: + - proto: "udp" + dport: 51820 + comment: "wireguard" + - proto: "tcp" + dport: 22 + comment: "ssh admin" + +firewall_public_tcp_ports_ipv4: + - 22 + - 80 + - 443 + +firewall_public_tcp_ports_ipv6: + - 80 + - 443 +``` + +## Exemple de playbook + +```yaml +- name: Configure firewall + hosts: all + become: true + roles: + - role: firewall +``` + +## Notes + +- Le script applique une politique restrictive (DROP sur INPUT/OUTPUT/FORWARD) puis ouvre explicitement les flux requis. +- Toute erreur de syntaxe shell du template est validée avant déploiement via /bin/sh -n. + diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..ce2caea --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,37 @@ +--- +# Interface used for optional logging rules in the firewall script. +# If null, ansible_default_ipv4.interface is used. +firewall_public_interface: null + +# IPv4 source networks allowed to access admin-restricted services. +firewall_admin_sources: + - cidr: "51.158.69.165/32" + comment: "monit.brainsys.io" + - cidr: "82.66.138.56/32" + comment: "wireguard.brainsys.io" + +# IPv4 services restricted to firewall_admin_sources. +firewall_admin_rules_ipv4: + - proto: "udp" + dport: 51820 + comment: "admin - IPv4 wireguard" + - proto: "tcp" + dport: 873 + comment: "admin - IPv4 rsync" + - proto: "tcp" + dport: 5666 + comment: "admin - IPv4 nrpe" + - proto: "tcp" + dport: 4949 + comment: "admin - IPv4 munin-node" + +# Public IPv4 TCP ports open to everyone. +firewall_public_tcp_ports_ipv4: + - 22 + - 80 + - 443 + +# Public IPv6 TCP ports open to everyone. +firewall_public_tcp_ports_ipv6: + - 80 + - 443 diff --git a/files/firewall.service b/files/firewall.service index 3e345cc..0c36daf 100644 --- a/files/firewall.service +++ b/files/firewall.service @@ -5,8 +5,7 @@ After=network.target [Service] RemainAfterExit=yes ExecStart=/usr/local/bin/firewall start -ExecStartPost=/bin/systemctl restart fail2ban.service -ExecReload=/usr/local/bin/firewall reload +ExecReload=/usr/local/bin/firewall force-reload ExecStop=/usr/local/bin/firewall stop User=root diff --git a/handlers/main.yml b/handlers/main.yml index aa56a8d..a943ecd 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,5 +1,9 @@ --- - name: restart firewall - systemd_service: - name: postfix + systemd: + name: firewall state: restarted + +- name: reload systemd + systemd: + daemon_reload: yes diff --git a/meta/main.yml b/meta/main.yml index 26fc090..14d6a66 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -4,6 +4,17 @@ galaxy_info: description: Simple firewall ! company: brainsys license: MIT - min_ansible_version: 2.8 + min_ansible_version: "2.8" issue_tracker_url: https://git.brainsys.io/ansible-roles/firewall/issues github_branch: main + platforms: + - name: Debian + versions: + - all + - name: Ubuntu + versions: + - all + galaxy_tags: + - firewall + - security + - iptables diff --git a/tasks/install.yml b/tasks/install.yml index 4610749..d74c77f 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -16,20 +16,23 @@ dest: "/usr/local/bin/firewall" mode: "0755" force: yes + validate: /bin/sh -n %s notify: - restart firewall - name: firewall | copy systemd unit file copy: src: "firewall.service" - dest: "/lib/systemd/system/firewall.service" + dest: "/etc/systemd/system/firewall.service" mode: "0644" force: yes notify: + - reload systemd - restart firewall -- name: fireall | enable on boot - systemd: +- name: firewall | enable and start service + systemd: name: firewall enabled: yes masked: no + state: started diff --git a/templates/firewall.j2 b/templates/firewall.j2 index 7b922d9..86c09da 100644 --- a/templates/firewall.j2 +++ b/templates/firewall.j2 @@ -10,7 +10,7 @@ IPT6=/sbin/ip6tables NAME=firewall DESC="packet filter" -PUBIF="{{ ansible_default_ipv4.interface }}" +PUBIF="{{ firewall_public_interface | default(ansible_default_ipv4.interface | default('eth0')) }}" #PRIVATEIF=eth1 case "$1" in @@ -40,28 +40,24 @@ case "$1" in echo " * Accept request & reply ICMP requests : \033[32m[OK] \033[0m" ## Protection rules - # SMURF attack protection - $IPT4 -A INPUT -p icmp -j DROP - $IPT4 -A INPUT -p icmp -m limit --limit 2/second -j ACCEPT - # Drop excessive RST packets to avoid smurf attacks + # Drop excessive RST packets $IPT4 -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT echo " * IPv4 protection rules : \033[32m[OK] \033[0m" # Admin chain $IPT4 -N ADMIN - $IPT4 -A ADMIN -s 51.158.69.165/32 -j ACCEPT -m comment --comment "monit.brainsys.io" - $IPT4 -A ADMIN -s 82.66.138.56/32 -j ACCEPT -m comment --comment "wireguard.brainsys.io" +{% for source in firewall_admin_sources %} + $IPT4 -A ADMIN -s {{ source.cidr }} -j ACCEPT -m comment --comment "{{ source.comment }}" +{% endfor %} echo " * Creating admin chain : \033[32m[OK] \033[0m" # Custom rules - $IPT4 -A INPUT -j ADMIN -p udp --dport 51820 --syn -m comment --comment "admin - IPv4 wireguard" - #$IPT4 -A INPUT -j ADMIN -p tcp --dport 22 --syn -m comment --comment "admin - IPv4 ssh" - $IPT4 -A INPUT -j ADMIN -p tcp --dport 873 --syn -m comment --comment "admin - IPv4 rsync" - $IPT4 -A INPUT -j ADMIN -p tcp --dport 5666 --syn -m comment --comment "admin - IPv4 nrpe" - $IPT4 -A INPUT -j ADMIN -p tcp --dport 4949 --syn -m comment --comment "admin - IPv4 munin-node" - $IPT4 -A INPUT -j ACCEPT -p tcp --dport 22 -m comment --comment "IPv4 ssh" - $IPT4 -A INPUT -j ACCEPT -p tcp --dport 80 -m comment --comment "IPv4 http" - $IPT4 -A INPUT -j ACCEPT -p tcp --dport 443 -m comment --comment "IPv4 https" +{% for rule in firewall_admin_rules_ipv4 %} + $IPT4 -A INPUT -j ADMIN -p {{ rule.proto }} --dport {{ rule.dport }}{% if rule.proto == 'tcp' %} --syn{% endif %} -m comment --comment "{{ rule.comment }}" +{% endfor %} +{% for port in firewall_public_tcp_ports_ipv4 %} + $IPT4 -A INPUT -j ACCEPT -p tcp --dport {{ port }} -m comment --comment "IPv4 tcp/{{ port }}" +{% endfor %} echo " * Custom IPv4 rules : \033[32m[OK] \033[0m" # REJECT everything else @@ -95,18 +91,14 @@ case "$1" in echo " * Accept request & reply ICMP requests : \033[32m[OK] \033[0m" ## Protection rules - # SMURF attack protection - $IPT6 -A INPUT -p icmpv6 -j DROP - $IPT6 -A INPUT -p icmpv6 -m limit --limit 2/second -j ACCEPT - # Drop excessive RST packets to avoid smurf attacks + # Drop excessive RST packets $IPT6 -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT echo " * IPv6 protection rules : \033[32m[OK] \033[0m" # Custom rules - $IPT6 -A INPUT -j ACCEPT -p tcp --dport 80 --syn -m comment --comment "IPv6 http" - $IPT6 -A INPUT -j ACCEPT -p tcp --dport 443 --syn -m comment --comment "IPv6 https" - #$IPT6 -A INPUT -j ACCEPT -p tcp --dport 22 -m comment --comment "IPv6 ssh" - #$IPT6 -A INPUT -j ACCEPT -p tcp --dport 25 -m comment --comment "IPv6 smtp" +{% for port in firewall_public_tcp_ports_ipv6 %} + $IPT6 -A INPUT -j ACCEPT -p tcp --dport {{ port }} --syn -m comment --comment "IPv6 tcp/{{ port }}" +{% endfor %} echo " * Custom IPv6 rules : \033[32m[OK] \033[0m" # REJECT everything else