--- # 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. # # IMPORTANT : DOCKER-USER voit TOUT le trafic FORWARD, y compris le trafic # sortant initié par les conteneurs eux-mêmes (ex: un bot qui appelle une API # externe en HTTPS) — un match uniquement sur --dport 443 bloque donc aussi # ces requêtes sortantes, pas seulement les connexions entrantes. On restreint # donc les règles à l'interface externe (in_interface, ext_iface) : le trafic # entrant depuis internet arrive par là, alors que le trafic sortant d'un # conteneur entre dans la chaîne par le bridge Docker, pas par eth0. # # Résultat : seul le load-balancer (IP VPN) peut atteindre 80/443 sur ces hôtes # depuis l'extérieur, tout le reste d'internet est bloqué en entrée — mais les # conteneurs gardent un accès sortant normal. 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'] }}" ext_iface: "eth0" tasks: - name: Installer iptables-persistent ansible.builtin.apt: name: iptables-persistent state: present update_cache: yes - name: Bloquer les connexions entrantes 80/443 non issues du load-balancer ansible.builtin.iptables: chain: DOCKER-USER in_interface: "{{ ext_iface }}" protocol: tcp destination_port: "{{ item }}" jump: DROP action: insert comment: "app-firewall: bloque {{ item }} hors load-balancer" loop: - "80" - "443" - name: Autoriser les connexions entrantes 80/443 depuis le load-balancer (VPN) ansible.builtin.iptables: chain: DOCKER-USER in_interface: "{{ ext_iface }}" 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