ajoute le réseau pour OpenStack : dummy0, paire veth, NAT restreint au réseau externe
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
e879a214a9
commit
87c8aac5f5
14 changed files with 247 additions and 0 deletions
21
ansible/reseau-openstack.yml
Normal file
21
ansible/reseau-openstack.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
# Étape 4 du déploiement Syllabus : réseau pour OpenStack (dummy0, paire veth,
|
||||
# NAT). Touche le réseau et le pare-feu — à exécuter uniquement après accord
|
||||
# explicite d'Adam (règle 3). Se termine par un redémarrage, lui aussi
|
||||
# soumis à son accord explicite.
|
||||
#
|
||||
# `reseau-openstack` tourne avant `durcissement` : ce dernier re-rend le
|
||||
# pare-feu (nftables.conf.j2) en tenant compte du nouveau sous-réseau externe
|
||||
# OpenStack (variables ci-dessous), et son filet de sécurité anti-coupure
|
||||
# protège donc aussi ce changement-ci.
|
||||
- name: Réseau pour OpenStack
|
||||
hosts: syllabus
|
||||
become: true
|
||||
gather_facts: true
|
||||
vars:
|
||||
reseau_veth_gw: veth-ext-gw
|
||||
reseau_veth_gw_subnet: 172.24.4.0/24
|
||||
reseau_interface_publique: eno1
|
||||
roles:
|
||||
- reseau-openstack
|
||||
- durcissement
|
||||
|
|
@ -55,6 +55,14 @@
|
|||
mode: "0644"
|
||||
notify: redémarrer fail2ban
|
||||
|
||||
- name: créer le répertoire des règles nftables additionnelles
|
||||
ansible.builtin.file:
|
||||
path: /etc/nftables.d
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0750"
|
||||
|
||||
- name: déployer le script de retour à l'état d'avant durcissement
|
||||
ansible.builtin.template:
|
||||
src: durcissement-rollback.sh.j2
|
||||
|
|
|
|||
|
|
@ -21,9 +21,22 @@ table inet filter {
|
|||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
|
||||
{% if reseau_veth_gw_subnet is defined %}
|
||||
# Un seul sens autorisé : réseau externe OpenStack -> Internet (NAT),
|
||||
# plus les réponses à ce trafic. Rien n'entre depuis Internet vers les
|
||||
# réseaux internes ; tout le reste est refusé par la politique drop.
|
||||
iifname "{{ reseau_veth_gw }}" oifname "{{ reseau_interface_publique }}" ip saddr {{ reseau_veth_gw_subnet }} accept
|
||||
iifname "{{ reseau_interface_publique }}" oifname "{{ reseau_veth_gw }}" ct state established,related accept
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
}
|
||||
}
|
||||
|
||||
# Autres règles (NAT, etc.), déposées par d'autres rôles. Un glob sans fichier
|
||||
# correspondant n'est pas une erreur pour nft : cette ligne ne casse rien tant
|
||||
# que /etc/nftables.d/ est vide.
|
||||
include "/etc/nftables.d/*.conf"
|
||||
|
|
|
|||
16
ansible/roles/reseau-openstack/defaults/main.yml
Normal file
16
ansible/roles/reseau-openstack/defaults/main.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
# Réseau privé pour Kolla (interface de management / VIP interne, pas de HAProxy).
|
||||
reseau_dummy_nom: dummy0
|
||||
reseau_dummy_ip: 10.10.0.1/24
|
||||
|
||||
# Paire veth : un bout ira à Neutron (neutron_external_interface, étape 5),
|
||||
# l'autre reste dans le réseau racine et porte la passerelle du réseau
|
||||
# "externe" OpenStack (celui des routeurs de VM, pas les VM elles-mêmes).
|
||||
reseau_veth_ovs: veth-ext-ovs
|
||||
reseau_veth_gw: veth-ext-gw
|
||||
reseau_veth_gw_ip: 172.24.4.1/24
|
||||
reseau_veth_gw_subnet: 172.24.4.0/24
|
||||
|
||||
reseau_interface_publique: eno1
|
||||
|
||||
durcissement_delai_filet_secondes: 300
|
||||
6
ansible/roles/reseau-openstack/handlers/main.yml
Normal file
6
ansible/roles/reseau-openstack/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: redémarrer systemd-networkd
|
||||
ansible.builtin.systemd:
|
||||
name: systemd-networkd
|
||||
state: restarted
|
||||
enabled: true
|
||||
88
ansible/roles/reseau-openstack/tasks/main.yml
Normal file
88
ansible/roles/reseau-openstack/tasks/main.yml
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
# Étape 4 : réseau pour OpenStack. N'est jamais exécuté seul : ce rôle tourne
|
||||
# dans le même play que `durcissement` (voir ansible/reseau-openstack.yml),
|
||||
# pour que le pare-feu soit re-rendu avec la règle qui autorise ce nouveau
|
||||
# sous-réseau — et pour réutiliser son filet de sécurité anti-coupure.
|
||||
|
||||
- name: charger le module noyau dummy au démarrage
|
||||
ansible.builtin.copy:
|
||||
content: "dummy\n"
|
||||
dest: /etc/modules-load.d/reseau-openstack.conf
|
||||
mode: "0644"
|
||||
|
||||
- name: charger le module dummy maintenant (sans attendre le prochain redémarrage)
|
||||
community.general.modprobe:
|
||||
name: dummy
|
||||
state: present
|
||||
|
||||
- name: déployer l'interface dummy0 (management interne Kolla)
|
||||
ansible.builtin.template:
|
||||
src: 10-dummy0.netdev.j2
|
||||
dest: /etc/systemd/network/10-dummy0.netdev
|
||||
mode: "0644"
|
||||
notify: redémarrer systemd-networkd
|
||||
|
||||
- name: déployer le réseau de dummy0
|
||||
ansible.builtin.template:
|
||||
src: 10-dummy0.network.j2
|
||||
dest: /etc/systemd/network/10-dummy0.network
|
||||
mode: "0644"
|
||||
notify: redémarrer systemd-networkd
|
||||
|
||||
- name: déployer la paire veth (externe OpenStack)
|
||||
ansible.builtin.template:
|
||||
src: 20-veth-ext.netdev.j2
|
||||
dest: /etc/systemd/network/20-veth-ext.netdev
|
||||
mode: "0644"
|
||||
notify: redémarrer systemd-networkd
|
||||
|
||||
- name: déployer le réseau du bout OVS de la paire veth (pas d'IP, pour Neutron)
|
||||
ansible.builtin.template:
|
||||
src: 21-veth-ext-ovs.network.j2
|
||||
dest: /etc/systemd/network/21-veth-ext-ovs.network
|
||||
mode: "0644"
|
||||
notify: redémarrer systemd-networkd
|
||||
|
||||
- name: déployer le réseau du bout passerelle de la paire veth
|
||||
ansible.builtin.template:
|
||||
src: 22-veth-ext-gw.network.j2
|
||||
dest: /etc/systemd/network/22-veth-ext-gw.network
|
||||
mode: "0644"
|
||||
notify: redémarrer systemd-networkd
|
||||
|
||||
- name: "activer systemd-networkd (ne gère que les interfaces déclarées, eno1 reste sous ifupdown)"
|
||||
ansible.builtin.systemd:
|
||||
name: systemd-networkd
|
||||
enabled: true
|
||||
# Pas de state ici : le handler s'occupe du (re)démarrage une fois tous les
|
||||
# fichiers en place, pour n'appliquer qu'une seule fois.
|
||||
|
||||
- name: appliquer les nouvelles interfaces réseau
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: activer le routage IPv4 (nécessaire au NAT)
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: "1"
|
||||
sysctl_file: /etc/sysctl.d/99-reseau-openstack.conf
|
||||
state: present
|
||||
reload: true
|
||||
|
||||
- name: créer le répertoire des règles nftables additionnelles
|
||||
ansible.builtin.file:
|
||||
path: /etc/nftables.d
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0750"
|
||||
|
||||
- name: déployer le NAT masquerade pour le réseau externe OpenStack
|
||||
ansible.builtin.template:
|
||||
src: 10-nat-openstack.conf.j2
|
||||
dest: /etc/nftables.d/10-nat-openstack.conf
|
||||
mode: "0640"
|
||||
owner: root
|
||||
group: root
|
||||
# Handler défini dans le rôle durcissement (même play) : nft relit le fichier
|
||||
# principal ET ses inclusions en une seule recharge.
|
||||
notify: recharger nftables
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
[NetDev]
|
||||
Name={{ reseau_dummy_nom }}
|
||||
Kind=dummy
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[Match]
|
||||
Name={{ reseau_dummy_nom }}
|
||||
|
||||
[Network]
|
||||
Address={{ reseau_dummy_ip }}
|
||||
# Pas de route par défaut ni de DNS ici : cette interface sert uniquement de
|
||||
# point d'ancrage interne pour Kolla (network_interface, kolla_internal_vip_address).
|
||||
DHCP=no
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Géré par Ansible (rôle reseau-openstack) — ne pas modifier à la main.
|
||||
# NAT masquerade : seul le sous-réseau "externe" OpenStack ({{ reseau_veth_gw_subnet }},
|
||||
# utilisé par les routeurs de VM qui en ont explicitement besoin, jamais les
|
||||
# VM de lab elles-mêmes — voir étape 10 du prompt de déploiement) sort vers
|
||||
# Internet via {{ reseau_interface_publique }}.
|
||||
table ip nat {
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100;
|
||||
ip saddr {{ reseau_veth_gw_subnet }} oifname "{{ reseau_interface_publique }}" masquerade
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[NetDev]
|
||||
Name={{ reseau_veth_ovs }}
|
||||
Kind=veth
|
||||
|
||||
[Peer]
|
||||
Name={{ reseau_veth_gw }}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[Match]
|
||||
Name={{ reseau_veth_ovs }}
|
||||
|
||||
[Network]
|
||||
# Pas d'IP : ce bout sera donné à Neutron (neutron_external_interface) à
|
||||
# l'étape 5, qui l'attachera lui-même à son bridge OVS/OVN. On se contente de
|
||||
# le faire monter et de le laisser persister au redémarrage.
|
||||
DHCP=no
|
||||
LinkLocalAddressing=no
|
||||
ConfigureWithoutCarrier=yes
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
[Match]
|
||||
Name={{ reseau_veth_gw }}
|
||||
|
||||
[Network]
|
||||
Address={{ reseau_veth_gw_ip }}
|
||||
DHCP=no
|
||||
# Passerelle du réseau "externe" OpenStack (celui des routeurs de VM). Pas de
|
||||
# route par défaut ajoutée ici : c'est le NAT masquerade nftables qui fait
|
||||
# sortir ce sous-réseau vers Internet via {{ reseau_interface_publique }},
|
||||
# pas une route système.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Géré par Ansible (rôle reseau-openstack) — ne pas modifier à la main.
|
||||
# Nécessaire pour que le NAT masquerade du réseau externe OpenStack fonctionne.
|
||||
net.ipv4.ip_forward = 1
|
||||
|
|
@ -105,3 +105,47 @@ Chiffrer avant d'envoyer (plutôt que de compter sur un transport chiffré) a un
|
|||
**Suite**
|
||||
|
||||
Étape 4 : réseau pour OpenStack (`dummy0`, paire veth, NAT). Touche le réseau → accord explicite d'Adam obligatoire avant d'appliquer, filet anti-coupure, et redémarrage du serveur seulement avec son accord.
|
||||
|
||||
## 2026-10-07 — Étape 4 : réseau pour OpenStack
|
||||
|
||||
**Fait**
|
||||
|
||||
- Rôle Ansible `reseau-openstack` + playbook `ansible/reseau-openstack.yml` (qui rejoue aussi `durcissement` pour le pare-feu et son filet anti-coupure). Appliqué après accord explicite d'Adam, puis redémarrage avec son accord.
|
||||
- `dummy0` : 10.10.0.1/24, futur `network_interface` / `kolla_internal_vip_address` (Kolla sans HAProxy).
|
||||
- Paire veth : `veth-ext-ovs` (sans IP, futur `neutron_external_interface`) ↔ `veth-ext-gw` (172.24.4.1/24, passerelle du réseau externe OpenStack).
|
||||
- Persistance par `systemd-networkd`, limité à ces trois interfaces : `eno1` reste sous `ifupdown`, inchangé.
|
||||
- `net.ipv4.ip_forward=1` (`/etc/sysctl.d/99-reseau-openstack.conf`).
|
||||
- nftables : NAT masquerade de 172.24.4.0/24 vers `eno1` (`/etc/nftables.d/10-nat-openstack.conf`, inclus depuis `/etc/nftables.conf`). Chaîne `forward` resserrée à la demande d'Adam : seulement `veth-ext-gw → eno1` depuis 172.24.4.0/24, et les réponses `eno1 → veth-ext-gw` (`established,related`). Tout le reste est refusé ; rien n'entre depuis Internet vers les réseaux internes.
|
||||
|
||||
**Règles nftables finales (relues après redémarrage)**
|
||||
|
||||
```
|
||||
chain forward { policy drop;
|
||||
iifname "veth-ext-gw" oifname "eno1" ip saddr 172.24.4.0/24 accept
|
||||
iifname "eno1" oifname "veth-ext-gw" ct state established,related accept
|
||||
}
|
||||
table ip nat { chain postrouting {
|
||||
ip saddr 172.24.4.0/24 oifname "eno1" masquerade
|
||||
} }
|
||||
```
|
||||
|
||||
**Problèmes rencontrés et solution**
|
||||
|
||||
- 1er lancement : `Destination directory /etc/nftables.d does not exist`. Le dossier était créé par `durcissement`, qui tourne après `reseau-openstack`. Échec survenu avant toute modification du pare-feu. Corrigé en créant aussi le dossier dans `reseau-openstack`.
|
||||
- Un lancement a été bloqué par le garde-fou de Claude Code parce que la règle `forward` avait été modifiée après l'accord d'Adam sans lui être remontrée. On a fait une simulation `--check --diff`, Adam a validé le diff, puis on a appliqué.
|
||||
- Table `f2b-table` de fail2ban absente après rechargement du pare-feu et après redémarrage : c'est normal, fail2ban 1.0 ne la crée qu'au premier bannissement. Point encore à vérifier : `flush ruleset` à chaque rechargement efface une table de bannissement déjà créée. fail2ban devrait la recréer au bannissement suivant (vérification automatique de ses actions), mais ce n'est pas encore testé.
|
||||
|
||||
**Critère vérifié (après redémarrage à 11:37, SSH revenu à 11:39)**
|
||||
|
||||
- SSH répond, `dummy0` et la paire veth sont présents avec leurs IP, `ip_forward=1`.
|
||||
- Internet joignable depuis le serveur (ping 9.9.9.9, résolution de `deb.debian.org`), route par défaut inchangée.
|
||||
- Services actifs : ssh, nftables, fail2ban, chrony, systemd-networkd, timer de sauvegarde. RAID `[UU]` sur `md0` et `md1`.
|
||||
- `nmap` depuis le Mac : seul le port 22 est ouvert.
|
||||
|
||||
**Comprendre**
|
||||
|
||||
OpenStack a besoin de deux réseaux en plus de l'accès public : un réseau interne pour que ses services se parlent, et un réseau « externe » pour que les routeurs virtuels puissent sortir. Sur un serveur qui n'a qu'une seule IP publique, mettre Neutron directement sur `eno1` reviendrait à lui confier notre seule porte d'entrée. On a donc créé des interfaces virtuelles : `dummy0`, une carte réseau factice qui porte une adresse privée stable pour les services, et une paire veth, qui fonctionne comme un câble virtuel dont un bout ira à Neutron et l'autre sert de passerelle. Le NAT fait sortir ce réseau externe vers Internet en se faisant passer pour l'IP publique. Le pare-feu n'autorise que ce sens-là, plus les réponses, si bien que personne ne peut entrer depuis Internet vers les réseaux internes. Le redémarrage prouve que tout cela est persistant, et pas seulement appliqué en mémoire.
|
||||
|
||||
**Suite**
|
||||
|
||||
Étape 5 : Kolla-Ansible 2025.2 tout-en-un. `bootstrap-servers` peut toucher au pare-feu et à Docker : vérifier avant, rejouer `durcissement` après, et demander l'accord d'Adam pour ce qui touche au pare-feu.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue