Files
ansible-mln/infra/playbook-app-firewall-lockdown.yml
T
2026-08-07 18:58:50 +02:00

133 lines
4.7 KiB
YAML

---
# Les ports 80/443 sont publiés par Docker (docker-compose du conteneur waf), donc
# UFW seul ne suffit pas : Docker insère ses propres règles NAT/FORWARD directement
# dans iptables et les contourne. On filtre donc dans la chaîne DOCKER-USER, seul
# point garanti d'être évalué avant les règles de Docker.
#
# Résultat : seul le load-balancer (IP VPN) peut atteindre 80/443 sur ces hôtes,
# tout le reste d'internet est bloqué. SSH et le reste du trafic ne sont pas touchés.
- name: Restreindre l'accès HTTP/HTTPS des serveurs applicatifs au load-balancer
hosts: prod:replica-prod
become: true
gather_facts: false
vars:
lb_vpn_ip: "{{ hostvars['load-balancer']['vpn_ip'] }}"
tasks:
- name: Installer iptables-persistent
ansible.builtin.apt:
name: iptables-persistent
state: present
update_cache: yes
- name: Bloquer les connexions 80/443 non issues du load-balancer
ansible.builtin.iptables:
chain: DOCKER-USER
protocol: tcp
destination_port: "{{ item }}"
jump: DROP
action: insert
comment: "app-firewall: bloque {{ item }} hors load-balancer"
loop:
- "80"
- "443"
- name: Autoriser les connexions 80/443 depuis le load-balancer (VPN)
ansible.builtin.iptables:
chain: DOCKER-USER
protocol: tcp
source: "{{ lb_vpn_ip }}/32"
destination_port: "{{ item }}"
jump: RETURN
action: insert
comment: "app-firewall: autorise {{ item }} depuis le load-balancer"
loop:
- "80"
- "443"
- name: Sauvegarder les règles iptables (persistance au reboot)
ansible.builtin.command: netfilter-persistent save
changed_when: false
# Le load-balancer n'a besoin que de faire du reverse-proxy HTTP/HTTPS vers
# prod/replica-prod : il n'a aucune raison de se connecter en SSH à quoi que
# ce soit. On bloque donc son SSH sortant vers toutes les autres machines du
# réseau (chaîne INPUT, en tête de chaîne pour passer avant les ACCEPT VPN
# existants), afin de limiter le rayon d'action en cas de compromission du
# load-balancer (seul hôte exposé publiquement sur 80/443).
- name: Empêcher le load-balancer de se connecter en SSH aux autres machines
hosts: all:!load-balancer
become: true
gather_facts: false
vars:
lb_vpn_ip: "{{ hostvars['load-balancer']['vpn_ip'] }}"
lb_public_ip: "{{ hostvars['load-balancer']['ansible_host'] }}"
tasks:
- name: Installer iptables-persistent
ansible.builtin.apt:
name: iptables-persistent
state: present
update_cache: yes
- name: Bloquer le SSH entrant depuis le load-balancer
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
source: "{{ item }}/32"
destination_port: "22"
jump: DROP
action: insert
rule_num: 1
comment: "app-firewall: bloque SSH depuis le load-balancer"
loop:
- "{{ lb_vpn_ip }}"
- "{{ lb_public_ip }}"
- name: Sauvegarder les règles iptables (persistance au reboot)
ansible.builtin.command: netfilter-persistent save
changed_when: false
# Le replica n'a besoin de parler à bdd-redis-prod que sur le port Postgres
# (5432, réplication). On bloque son SSH vers bdd-redis-prod (chaîne INPUT,
# en tête de chaîne pour passer avant l'ACCEPT VPN existant sur dpt:22) sans
# toucher au port 5432, déjà autorisé pour toute la plage VPN 10.0.0.0/24.
- name: Empêcher le replica de se connecter en SSH à bdd-redis-prod
hosts: bdd-redis-prod
become: true
gather_facts: false
vars:
replica_vpn_ip: "{{ hostvars['replica-prod-uber']['vpn_ip'] }}"
replica_public_ip: "{{ hostvars['replica-prod-uber']['ansible_host'] }}"
tasks:
- name: Installer iptables-persistent
ansible.builtin.apt:
name: iptables-persistent
state: present
update_cache: yes
- name: Bloquer le SSH entrant depuis le replica
ansible.builtin.iptables:
chain: INPUT
protocol: tcp
source: "{{ item }}/32"
destination_port: "22"
jump: DROP
action: insert
rule_num: 1
comment: "app-firewall: bloque SSH depuis le replica"
loop:
- "{{ replica_vpn_ip }}"
- "{{ replica_public_ip }}"
- name: Sauvegarder les règles iptables (persistance au reboot)
ansible.builtin.command: netfilter-persistent save
changed_when: false