Ansible : Déploiement de 3 routeurs Linux en milieu hétérogène

Ansible : Déploiement de 3 routeurs Linux en milieu hétérogène

Table of Contents

Contexte de l'environnement

  • 1 Serveur sous Debian 10 où sera installé la solution Ansible
  • 1 Serveur sous Debian 10 qui sera un routeur pour le LAN 11
  • 1 Serveur sous Ubuntu Server 20.04 qui sera un routeur pour le LAN 12
  • 1 Serveur sous CentOS 7 qui sera un routeur pour le LAN 13

Objectif

  • L’objectif de ce document est d’obtenir l’environnement ci-dessous après le déploiement automatisé à l’aide de la solution Ansible.

Pré-requis

  • Tous les serveurs sont installés avec leur distribution respective.
  • La configuration IP de SRV-ANSIBLE est effectuée sur la carte réseau ens32 avec pour IP 10.0.0.11/16.
  • La configuration IP de RNAT-11 est effectuée sur la carte réseau ens32 avec pour IP 10.0.0.11/16. Une seconde carte réseau ens34 est également présente sans aucun paramétrage.
  • La configuration IP de RNAT-12 est effectuée sur la carte réseau ens32 avec pour IP 10.0.0.12/16. Une seconde carte réseau ens35 est également présente sans aucun paramétrage.
  • La configuration IP de RNAT-13 est effectuée sur la carte réseau ens33 avec pour IP 10.0.0.13/16. Une seconde carte réseau ens32 est également présente sans aucun paramétrage.
  • Un serveur SSH est opérationnel sur chaque RNAT.
  • Le compte root est activé sur RNAT-12 (Ubuntu) :
sudo passwd root

Installation d'Ansible

  • L’installation d’Ansible se fait sur SRV-ANSIBLE. Ansible est présent nativement dans les dépôts de Debian 10. L’installation peut donc se faire à l’aide d’apt :
sudo apt-get install ansible

A ce jour, la version 2.7.7 d’Ansible est installée ainsi que Python version 3.7.3.

Modification du fichier /etc/hosts

  • Pour des questions de praticité, le fichier /etc/hosts de SRV-ANSIBLE est modifié afin de travailler avec des noms d’hôtes plutôt que les adresses IP des différents RNAT.

Création d'un utilisateur ansible

  • Pour éviter d’exécuter le déploiement en tant que root sur SRV-ANSIBLE, un utilisateur ansible est crée :
sudo useradd -d /home/ansible -m -s /bin/bash ansible
sudo passwd ansible

L’ensemble des commandes exécutées par la suite sur SRV-ANSIBLE sont faites avec cet utilisateur ansible. L’ensemble des fichiers de configurations de la solution Ansible seront stockés dans la home directory de cet utilisateur ansible.

su - ansible

Création de l'inventaire

  • Un fichier inventory est créé afin de répertorier les RNAT sur lequel le playbook sera joué. La variable ansible_user définit quel utilisateur est utilisé pour la connexion ssh aux RNAT.

  • Pour éviter que ce fichier d'inventaire soit lu par d'autres utilisateurs du système, ses droits sont modifiés :
chmod 0600 inventory

Génération et copie des clefs SSH

  • Afin d'éviter de saisir les mots de passe SSH sur les RNAT lors de l'exécution du playbook, une clef SSH est générée sur SRV-ANSIBLE :
ssh-keygen
  • La clef peut être laissée à son emplacement par défaut. Aucune passphrase ne sera définie.

  • Pour copier la clef SSH publique sur les 3 RNAT, il est nécessaire d'autoriser root à se connecter en SSH par mot de passe. Décommenter et modifier l'option PermitRootLogin dans le fichier /etc/ssh/sshd_config des 3 RNAT pour avoir PermitRootLogin yes. Relancer le service sshd.service après la modification sur les 3 RNAT :
sudo systemctl restart sshd.service
  • La clef SSH publique peut être copiée sur les 3 RNAT. A partir de SRV-ANSIBLE :
ssh-copy-id root@rnat-11 && ssh-copy-id root@rnat-12 && ssh-copy-id root@rnat-13

  • Une fois la clef publique SSH de SRV-ANSIBLE copiée sur les 3 RNAT, autoriser la connexion SSH en tant que root sur les 3 RNAT uniquement par clef SSH.
  • Modifier l'option PermitRootLogin dans le fichier /etc/ssh/sshd_config des 3 RNAT pour avoir PermitRootLogin prohibit-password.
  • Relancer le service sshd.service après la modification sur les 3 RNAT :
sudo systemctl restart sshd.service
  • Vérifier que la connexion SSH de SRV-ANSIBLE vers les RNAT fonctionne correctement sans demande de mot de passe :
ssh root@rnat-11
ssh root@rnat-12
ssh root@rnat-13

Vérification de la communication entre le SRV-ANSIBLE et les 3 RNAT

A partir de maintenant, toutes les commandes seront exécutées à partir de SRV-ANSIBLE.

  • Une des 1ères choses à vérifier à ce stade est la bonne communication entre SRV-ANSIBLE et les 3 RNAT. Ansible regorge d'énormément de module. Dans le cas présent, l'utilisation du module ping est parfaitement indiqué :
ansible -i inventory -m ping routeurs

  • -i <le fichier d'inventaire>

  • -m <le module à utiliser>

  • Le dernier argument routeurs correspond au type de serveur, définit dans l’inventaire, sur lequel exécuter le module.

  • RNAT-11 et RNAT-13 répondent correctement. RNAT-12 est en erreur.

Cela est dû au fait que le serveur Ansible requiert d'avoir Python version 2.7 qui n'est pas installé par défaut sur le serveur Ubuntu.

  • A partir de RNAT-12 :
sudo apt-get install python

On remarque qu'en spécifiant uniquement le paquet python, c'est python2.7 qui est installé.

  • Une fois cela fait, revérifier la bonne communication entre SRV-ANSIBLE et les 3 RNAT :
ansible -i inventory -m ping routeurs

Création de l'arborescence où seront stockée les configurations des RNAT

  • La configuration IP des RNAT va être stockée sur SRV-ANSIBLE dans un dossier ~/conf_routeurs et chaque RNAT aura son dossier. Ces dossiers sont à protéger des autres utilisateurs du système :
mkdir -p conf_routeurs/{rnat-11,rnat-12,rnat-13} && chmod -R 0700 conf_routeurs/

Création des fichiers de configuration pour RNAT-11

  • RNAT-11 étant sous Debian 10, la configuration IP est stockée dans le fichier /etc/network/interfaces et le routage dans le fichier /etc/sysctl.conf.

  • Création du fichier de configuration IP pour RNAT-11 :

vi conf_routeurs/rnat-11/interfaces
# Interface loopback
auto lo
iface lo inet loopback

# Interface LAN 10.0.0.0 /16
auto ens32
iface ens32 inet static
        address 10.0.0.11
        netmask 255.255.0.0
        gateway 10.0.0.254

# Interface LAN 192.168.11.0 /24
auto ens34
iface ens34 inet static
        address 192.168.11.254
        netmask 255.255.255.0
  • Création du fichier permettant le routage IPv4 pour RNAT-11 :
vi conf_routeurs/rnat-11/sysctl.conf
# Activation du routage IPv4
net.ipv4.ip_forward=1

Création des fichiers de configuration pour RNAT-12

  • RNAT-12 étant sous Ubuntu Server 20.04, la configuration IP est stockée dans le dossier /etc/netplan/ avec un fichier yaml pour chaque interface et le routage dans le fichier /etc/sysctl.conf.

  • Création des fichiers de configuration IP pour RNAT-12 :

vi conf_routeurs/rnat-12/00-lan_10.0.0.0.yaml
# Configuration IP pour le LAN 10.0.0.0 /16
network:
  ethernets:
    ens32:
      dhcp4: false
      addresses: [10.0.0.12/16]
      gateway4: 10.0.0.254
      nameservers:
        addresses: [192.168.1.1]
  version: 2
vi conf_routeurs/rnat-12/01-lan_192.168.12.0.yaml
# Configuration IP pour le LAN 192.168.12.0 /24
network:
  ethernets:
    ens35:
      dhcp4: false
      addresses: [192.168.12.254/24]
  version: 2
  • Création du fichier permettant le routage IPv4 pour RNAT-12 :
vi conf_routeurs/rnat-12/sysctl.conf
# Activation du routage IPv4
net.ipv4.ip_forward=1

Création des fichiers de configuration pour RNAT-13

  • RNAT-13 étant sous CentOS 7, la configuration IP est stockée dans le dossier /etc/sysconfig/network-scripts/ avec un fichier de type ifcfg-ensXX pour chaque interface et le routage dans le fichier /etc/sysctl.conf.

  • Création des fichiers de configuration IP pour RNAT-13 :

vi conf_routeurs/rnat-13/ifcfg-ens33
# Interface LAN 10.0.0.0 /16
DEVICE=ens33
BOOTPROTO=none
ONBOOT=yes
PREFIX=16
IPADDR=10.0.0.13
NETMASK=255.255.0.0
GATEWAY=10.0.0.254
DNS1=192.168.1.1
vi conf_routeurs/rnat-13/ifcfg-ens32
# Interface LAN 192.168.13.0 /24
DEVICE=ens32
BOOTPROTO=none
ONBOOT=yes
PREFIX=24
IPADDR=192.168.13.254
NETMASK=255.255.255.0
  • Création du fichier permettant le routage IPv4 pour RNAT-13 :
vi conf_routeurs/rnat-13/sysctl.conf
# Activation du routage IPv4
net.ipv4.ip_forward=1

Création du playbook pour l’installation des RNAT

  • Les modules copy, shell, service, apt, et yum vont être utilisés dans le playbook.

Au lancement du playbook, un Gathering Facts est exécuté pour récupérer toutes les informations nécessaires concernant les RNAT. Grâce à cela, un filtrage par nom d'hôte et par type de distribution est appliqué sur chaque action du playbook.

  • Création du playbook pour l'installation et la configuration des 3 RNAT :
vi install_routeurs.yml
---
- hosts: routeurs

  tasks:
  - name: Copie du fichier de la configuration IP pour RNAT-11
    copy:
      src: ~/conf_routeurs/rnat-11/interfaces
      dest: /etc/network/interfaces
      force: yes
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Activation des cartes réseaux pour RNAT-11
    shell: |
      ip l set ens32 up
      ip l set ens34 up
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Redémarrage du service réseau pour RNAT-11
    service:
      name: networking
      state: restarted
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Copie du fichier activant le routage IPv4 pour RNAT-11
    copy:
      src: ~/conf_routeurs/rnat-11/sysctl.conf
      dest: /etc/sysctl.conf
      force: yes
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Activation du routage IPv4 permanent pour RNAT-11
    shell: |
      sysctl -p
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Création du SNAT pour RNAT-11
    shell: |
      iptables -t nat -A POSTROUTING -o ens32 -j SNAT --to 10.0.0.11
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Mise en persistence du SNAT pour RNAT-11
    apt:
      name: iptables-persistent
      state: present
    when: ansible_hostname == "rnat-11" and ansible_distribution == "Debian"

  - name: Suppression des configurations IP existantes pour RNAT-12
    shell: |
      warn: false
      rm /etc/netplan/*.yaml
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Copie du fichier de la configuration IP du LAN 10.0.0.0 /16 pour RNAT-12
    copy:
      src: ~/conf_routeurs/rnat-12/00-lan_10.0.0.0.yaml
      dest: /etc/netplan/00-lan_10.0.0.0.yaml
      force: yes
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Copie du fichier de la configuration IP du LAN 192.168.12.0 /24 pour RNAT-12
    copy:
      src: ~/conf_routeurs/rnat-12/01-lan_192.168.12.0.yaml
      dest: /etc/netplan/01-lan_192.168.12.0.yaml
      force: yes
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Activation des cartes réseaux pour RNAT-12
    shell: |
      ip l set ens32 up
      ip l set ens35 up
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Application de la configuration IP pour RNAT-12
    shell: |
      netplan apply
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Copie du fichier activant le routage IPv4 pour RNAT-12
    copy:
      src: ~/conf_routeurs/rnat-12/sysctl.conf
      dest: /etc/sysctl.conf
      force: yes
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Activation du routage IPv4 permanent pour RNAT-12
    shell: |
      sysctl -p
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Création du SNAT pour RNAT-12
    shell: |
      iptables -t nat -A POSTROUTING -o ens32 -j SNAT --to 10.0.0.12
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Mise en persistence du SNAT pour RNAT-12
    apt:
      name: iptables-persistent
      state: present
    when: ansible_hostname == "rnat-12" and ansible_distribution == "Ubuntu"

  - name: Copie du fichier de la configuration IP du LAN 10.0.0.0 /16 pour RNAT-13
    copy:
      src: ~/conf_routeurs/rnat-13/ifcfg-ens33
      dest: /etc/sysconfig/network-scripts/ifcfg-ens33
      force: yes
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Copie du fichier de la configuration IP du LAN 192.168.13.0 /24 pour RNAT-13
    copy:
      src: ~/conf_routeurs/rnat-13/ifcfg-ens32
      dest: /etc/sysconfig/network-scripts/ifcfg-ens32
      force: yes
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Activation des cartes réseaux pour RNAT-13
    shell: |
      ip l set ens33 up
      ip l set ens32 up
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Redémarrage du service réseau pour RNAT-13
    service:
      name: network
      state: restarted
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Copie du fichier activant le routage IPv4 pour RNAT-13
    copy:
      src: ~/conf_routeurs/rnat-13/sysctl.conf
      dest: /etc/sysctl.conf
      force: yes
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Activation du routage IPv4 permanent pour RNAT-13
    shell: |
      echo 1 > /proc/sys/net/ipv4/ip_forward
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Suppression de firewalld pour RNAT-13
    yum:
      name: firewalld
      state: absent
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Installation des services iptables pour RNAT-13
    yum:
      name: iptables-services
      state: present
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Démarrage des services iptables pour RNAT-13
    service:
      name: iptables
      state: started
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Purge des règles iptables existantes pour RNAT-13
    shell: |
      iptables -F
      iptables -X
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Mise en place des nouvelles règles iptables pour RNAT-13
    shell: |
      iptables -t nat -A POSTROUTING -o ens33 -j SNAT --to 10.0.0.13
      iptables -t filter -A FORWARD -i ens32 -o ens33 -j ACCEPT
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Sauvegarde des règles iptables pour RNAT-13
    shell: |
      warn: false
      service iptables save
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

  - name: Chargement des services iptables au démarrage pour RNAT-13
    shell: |
      chkconfig iptables on
    when: ansible_hostname == "rnat-13" and ansible_distribution == "CentOS"

Le playbook est format YAML ce qui signifie que l’indentation doit se faire avec des espaces et non avec des tabulations.

Exécution du playbook pour le déploiement des RNAT

  • Le playbook d'installation des 3 RNAT est exécuté par la commande :
ansible-playbook -i inventory install_routeurs.yml
  • Un résumé des actions réalisées est affiché à la fin de l'exécution du playbook :

Vérification de l’installation des 3 RNAT

  • A l'aide d'un client sur chaque LAN, le routage est bien actif avec les bonnes règles dans iptables afin de pouvoir communiquer avec l’extérieur.
Les commentaires sont fermés.