Aller au contenu principal

Exposer les Services du Homelab

Nous avons bien avancé dans la création d'un homelab avec la mise en place d'une machine de rebond dotée de deux cartes réseau, ainsi qu'un serveur Proxmox sur le second réseau. Cette configuration me permet d'explorer de nouvelles possibilités en termes d'administration et de déploiement de services. Aujourd'hui, je vais me concentrer sur un aspect particulièrement intéressant et utile : exposer des services situés sur le second réseau, y compris le portail Proxmox, de manière sécurisée.

En effet, comment garantir un accès facile et sécurisé aux ressources du homelab, tout en maintenant une séparation nette entre le réseau domestique et l'environnement du lab ? Je vous rassure je ne vais pas exposer l'interface de proxmox sur internet !

Quelles solutions ?

La séparation des réseaux est une pratique de sécurité informatique qui consiste à diviser un réseau physique en plusieurs sous-réseaux logiques, isolant ainsi les différents types de trafic et les différents services. Dans mon homelab, cette séparation est incarnée par la présence de deux réseaux distincts : le réseau domestique et le réseau dédié au lab. Cette architecture minimise les risques de propagation des attaques et facilite la mise en place de politiques de sécurité différenciées.

Quelles solutions devons-nous mettre en place pour accéder aux services déployés dans le second réseau ?

Pour des accès temporaires, nous pouvons utiliser les tunnels SSH, pour des accès sur le long terme, nous pouvons mettre en place un reverse proxy.

Les tunnels SSH

SSH, ou Secure Shell, est un protocole permettant d'établir une communication sécurisée sur un réseau non sécurisé. L'utilisation de tunnels SSH pour relier deux réseaux permet de créer une connexion chiffrée entre un client et un serveur, assurant ainsi la confidentialité et l'intégrité des données échangées. Dans le contexte de mon homelab, j'utilise des tunnels SSH pour accéder de manière temporaire, mais sécurisée aux services du second réseau, notamment le portail Proxmox.

Le rôle de Traefik comme reverse proxy

Traefik est un reverse proxy moderne et un load balancer qui simplifie l'exposition et la gestion des services web. Il joue un rôle crucial dans la sécurisation de l'accès aux services en offrant des fonctionnalités telles que la gestion automatique des certificats SSL, les redirections HTTP vers HTTPS et la protection contre les attaques courantes sur le web. En déployant Traefik à l'entrée de mon homelab, je peux exposer de manière sécurisée le portail Proxmox et d'autres services, tout en bénéficiant d'une configuration simplifiée et d'une gestion centralisée.

Les certificats SSL (Secure Sockets Layer) sont essentiels pour sécuriser les communications entre les navigateurs web et les serveurs, en fournissant un moyen de chiffrer le trafic. L'utilisation de certificats SSL valide l'identité du serveur et assure que les données transmises restent confidentielles et intègres.

Mise en place de tunnels SSH

La création d'un tunnel SSH commence par l'ouverture d'une connexion chiffrée entre ma machine cliente et la machine de rebond qui possède deux cartes réseau. Cela crée un canal sécurisé à travers lequel le trafic peut transiter vers le second réseau. Voici la commande type qui permet d'établir un tel tunnel SSH :

ssh -L localPort:remoteAddress:remotePort user@SSHServerAddress

Dans cette commande, localPort est le port sur ma machine locale où je souhaite accéder au service distant, remoteAddress est l'adresse du service dans le second réseau (par exemple, l'interface web de Proxmox), remotePort est le port sur lequel le service distant écoute, et SSHServerAddress est l'adresse de la machine de rebond. Ce qui donne dans le cadre du homelab :

ssh -L 8006:192.168.20.10:8006 rebond.robert.local

Une fois le tunnel SSH établi, je peux accéder au portail Proxmox en ouvrant un navigateur web et en naviguant vers localhost:8006. Cette méthode me permet de gérer mes machines virtuelles et conteneurs Proxmox de manière sécurisée, même si je suis en dehors de mon réseau domestique.

En outre, pour rendre l'accès encore plus pratique et sécurisé, j'ajoute cette configuration dans mon fichier ~/.ssh/config pour simplifier la commande de connexion. Voici un exemple :

Host rebond.robert.local
  User bob
  IdentityFile /home/bob/.ssh/id_rsa.pub
  LocalForward 8006 192.168.20.10:8006

Avec cet alias, je peux me connecter en utilisant simplement ssh rebond.robert.local, simplifiant ainsi grandement le processus d'établissement du tunnel.

Mise en place de Traefik

Pour exposer des services de manières permanentes, nous allons installer Traefik, documenté ici, sur la machine de rebond.

Pour automatiser et standardiser son installation et sa configuration, j'ai choisi d'utiliser Ansible. Voici le contenu du role Ansible que j'ai utilisé :

- name: Create group
  become: true
  ansible.builtin.group:
    name: traefik
    state: present
- name: Create traefik user
  become: true
  ansible.builtin.user:
    name: traefik
    state: present
- name: Create folder
  become: true
  ansible.builtin.file:
    path: "{{ item }}"
    state: directory
    owner: traefik
    group: traefik
    mode: "0750"
  loop:
    - /opt/traefik/bin
    - /etc/traefik/
    - /etc/traefik/dynamic
- name: Download Traefik binaire
  become: true
  ansible.builtin.unarchive:
    remote_src: true
    src: "https://github.com/traefik/traefik/releases/download/v{{ traefik_version }}/traefik_v{{ traefik_version }}_linux_amd64.tar.gz"
    dest: /opt/traefik/bin/
    mode: "0755"
    owner: traefik
    group: traefik
- name: Install Traefik Configuration
  become: true
  ansible.builtin.template:
    src: traefik.yml.j2
    dest: /etc/traefik/traefik.yml
    owner: traefik
    group: traefik
    mode: "0644"
- name: Create Traefik Service
  become: true
  ansible.builtin.template:
    src: traefik.service.j2
    dest: /etc/systemd/system/trafik.service
    owner: traefik
    group: traefik
    mode: "0644"
  notify: Restart Traefik
- name: Reload systemd
  become: true
  ansible.builtin.systemd:
    daemon_reload: true
- name: Start Traefik Service
  become: true
  ansible.builtin.service:
    name: traefik.service
    state: started
    enabled: true
- name: Copy certificats
  become: true
  ansible.builtin.copy:
    src: "{{ item.name }}"
    dest: "{{ item.dest }}"
    owner: traefik
    group: traefik
    mode: "06400"
  loop:
    - { name: "traefik.crt", dest: "/etc/traefik/traefik.crt" }
    - { name: "traefik.key", dest: "/etc/traefik/traefik.key" }
- name: Copy Dynamic Certificats Declarations
  become: true
  ansible.builtin.template:
    src: certificats.yml.j2
    dest: /etc/traefik/dynamic/certificats.yml
    owner: traefik
    group: traefik
    mode: "0640"
- name: Create dynamic config files
  become: true
  ansible.builtin.copy:
    content: "{{ item.0.content | to_yaml }}"
    dest: "/etc/traefik/dynamic/{{ item.0.filename }}"
    owner: traefik
    group: traefik
    mode: "0640"
  loop:
    - "{{ traefik_dynamics }}"

Les premières étapes consistent à :

  • Créer un groupe et un utilisateur traefik
  • Créer les répertoires nécessaires
  • Télécharger le binaire de Traefik directement depuis sa page de releases sur GitHub.
  • Créer la configuration statique de Traefik
  • Déposer la configuration de la partie SSL et les certificats
  • Créer le service Traefik
  • Créer une configuration dynamique

Ce rôle est en cours de développement et demande à être industrialisé en ajoutant pas mal de variables, des tests...

Mon template pour la configuration principale de Traefik définit les paramètres de base, tels que l'activation du dashboard, les ports d'écoute et la configuration des logs :

---
global:
  sendAnonymousUsage: false
  checkNewVersion: false

api:
  dashboard: true

log:
  filePath: "/var/log/traefik.log"
  format: common
  level: "{{ traefik_log_level }}"

providers:
  file:
    directory: "/etc/traefik/dynamic"
    watch: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

Pour assurer que Traefik démarre avec le système, je crée un fichier de service systemd en utilisant un template Ansible. Ce fichier définit comment le service doit être lancé, incluant le chemin vers le binaire de Traefik et les options de démarrage :

# traefik.service.j2
[Unit]
Description=traefik service
After=network-online.target

[Service]
Type=simple
User=root
Group=root
Restart=on-failure
TimeoutStopSec=300
ExecStart=/opt/traefik/bin/traefik --configFile=/etc/traefik/traefik.yml

[Install]
WantedBy=multi-user.target

Pour la partie de la configuration dynamique, j'ai créé deux fichiers :

  1. un fichier certificats.yml qui est déposé par le rôle, ainsi que les certificats :
tls:
  certificates:
    - certFile: /etc/traefik/traefik.crt
      keyFile: /etc/traefik/traefik.key
      stores:
        - default
  1. Une configuration d'un service exposé qui lui est créé à partir d'une variable nommée traefik_dynamics qui est déclaré au niveau de l'invocation du rôle, donc dans le playbook suivant.
---
- name: Install Traefik
  hosts: localhost
  connection: local
  roles:
    - role: traefik
      vars:
        traefik_version: 2.11.0
        traefik_log_level: "debug"
        traefik_dynamics:
          - filename: "proxmox.yml"
            content:
              http:
                middlewares:
                  test-ipallow:
                    ipAllowList:
                      sourceRange:
                        - "127.0.0.1/32"
                        - "192.168.1.0/24"
                        - "10.8.0.0/24"
                routers:
                  my-secure-router:
                    rule: "Host(`proxmox1.robert.local`)"
                    entryPoints:
                      - "websecure"
                    service: proxmox
                    tls: {}
                    middlewares:
                      - test-ipallow
                services:
                  proxmox:
                    loadBalancer:
                      servers:
                        - url: https://proxmox1.robert.local:8006

Dans cette configuration, je demande à exposer l'interface du serveur proxmox1 provisionné précédemment. Pour renfoncer la configuration, je limite les accès aux IP interne et à celle de mon VPN. Proxmox n'est pas exposé sur internet !

Plus loin

Il est clair que le rôle Traefik est incomplet, mais il évoluera durant les prochaines semaines. Par la suite, lorsque je déploierai un middleware, j'exposerai les UI en déposant dans la configuration dynamique de Traefik le petit fichier yaml qui va bien avec Terraform ou Ansible.

Conclusion

Voilà qui conclue ce guide. Dans le prochain guide, nous verrons comment construire des images de VM pour Proxmox avec Packer et Ansible.