NOPE LinkedIn

Catégories:
Lab

Authentification LAN 802.1X avec FreeRADIUS, OpenLDAP et MFA Duo Security

Important
Article en cours de rédaction
Je reprends tout un tas d’articles et de LABs en projets et mis en standby. Principalement des LABs autour de l’authentification, Radius, etc…

Authentification LAN 802.1X avec FreeRADIUS, OpenLDAP et MFA Duo Security

Introduction

Cet article détaille la configuration d’une authentification réseau filaire ou sans-fil robuste basée sur le standard 802.1X. Nous utiliserons FreeRADIUS comme serveur RADIUS, OpenLDAP comme annuaire centralisé pour les utilisateurs et les informations d’identification, et nous ajouterons une couche de sécurité supplémentaire avec l’authentification multifacteur (MFA) fournie par Duo Security.

L’objectif est de permettre aux utilisateurs de se connecter au réseau en utilisant leurs identifiants LDAP habituels, avec une validation supplémentaire via l’application Duo Mobile (Push, code) ou d’autres méthodes supportées par Duo.

Nous aborderons la configuration de FreeRADIUS pour interroger OpenLDAP, puis l’intégration de Duo Security via son Authentication Proxy, que nous déploierons à l’aide de Docker pour plus de flexibilité.

Architecture Cible :

  1. Client 802.1X (PC, portable) tente de se connecter au réseau.
  2. Commutateur/Point d’accès (NAS - Network Access Server) intercepte la demande et la relaie au serveur RADIUS (ici, le Duo Authentication Proxy).
  3. Duo Authentication Proxy reçoit la requête RADIUS.
    • Il effectue l’authentification primaire en relayant la demande à FreeRADIUS.
  4. FreeRADIUS reçoit la demande du Duo Proxy.
    • Il interroge OpenLDAP pour valider l’identité et les informations d’autorisation de l’utilisateur (via le module rlm_ldap).
    • FreeRADIUS répond au Duo Proxy (succès/échec de l’authentification primaire).
  5. Duo Authentication Proxy (si l’authentification primaire réussit) :
    • Il contacte l’API Duo Security Cloud pour lancer l’authentification secondaire (MFA).
    • Il gère l’interaction MFA avec l’utilisateur (Push, code, etc.).
    • Il renvoie la réponse finale (Access-Accept / Access-Reject) au Commutateur/Point d’accès.
  6. Commutateur/Point d’accès autorise ou refuse l’accès au réseau au client.

Prérequis

  • Un serveur OpenLDAP fonctionnel avec des utilisateurs définis.
  • Un serveur avec FreeRADIUS (version 3.x recommandée) installé.
  • Un compte Duo Security (avec une intégration de type “RADIUS Application” configurée pour obtenir une Integration key, Secret key, et API hostname).
  • Docker et Docker Compose installés sur la machine hébergeant le Duo Authentication Proxy (peut être la même que FreeRADIUS ou une machine distincte).
  • Des certificats TLS valides pour sécuriser les communications EAP (PEAP, EAP-TTLS) et la connexion LDAP.

Partie 1 : Configuration de FreeRADIUS et OpenLDAP

Cette section reprend les étapes classiques d’intégration FreeRADIUS/OpenLDAP. Assurez-vous que ces étapes sont fonctionnelles avant d’ajouter Duo.

Note
Les chemins peuvent varier légèrement selon votre distribution Linux. Cet exemple utilise les chemins standards de Debian/Ubuntu pour FreeRADIUS 3.x)

  1. Configurer le module LDAP (rlm_ldap)

    Modifiez le fichier /etc/freeradius/3.0/mods-available/ldap :

    Fichier ini
        ldap {
            server = 'ldap.votre-domaine.lan' # Ou adresse IP
            # identity = 'cn=admin,dc=votre-domaine,dc=lan' # DN de connexion si nécessaire
            # password = 'votre_mot_de_passe_admin_ldap'   # Mot de passe si nécessaire
            basedn = 'ou=people,dc=votre-domaine,dc=lan' # Base de recherche des utilisateurs
            filter = '(uid=%{%{Stripped-User-Name}:-%{User-Name}})' # Filtre pour trouver l'utilisateur
    
            # TLS Configuration - FORTEMENT RECOMMANDÉ
            tls {
                start_tls = yes # Utilisez 'yes' pour StartTLS (port 389), 'no' pour LDAPS (port 636) si ldap { ... server = "ldaps://..." }
                ca_file = /etc/freeradius/3.0/certs/ca.pem    # Chemin vers le certificat de l'autorité de certification
                # certificate_file = /etc/freeradius/3.0/certs/client.pem # Certificat client si requis par LDAP
                # private_key_file = /etc/freeradius/3.0/certs/client.key # Clé privée client
                # require_cert = "demand" # Vérifie le certificat du serveur LDAP
            }
    
            # Attributs RADIUS à récupérer depuis LDAP si nécessaire
            # dictionary_mapping = ${confdir}/ldap.attrmap
    
            # Attribut contenant le mot de passe (souvent userPassword)
            password_attribute = userPassword
        }
    
    Activez le module :

    sudo ln -s /etc/freeradius/3.0/mods-available/ldap /etc/freeradius/3.0/mods-enabled/
    
  2. Configurer les Clients RADIUS (NAS) Modifiez /etc/freeradius/3.0/clients.conf pour déclarer vos commutateurs ou points d’accès :

    Fichier ini
        client mon_switch {
            ipaddr = 192.168.1.10 # IP du switch
            secret = mon_secret_radius # Secret partagé
            nas_type = other
        }
    
        client mon_ap {
            ipaddr = 192.168.1.11 # IP du point d'accès
            secret = un_autre_secret # Secret partagé
            nas_type = other
        }
    

  3. Configurer l’authentification EAP Modifiez /etc/freeradius/3.0/mods-available/eap :

    • Assurez-vous que default_eap_type est défini sur un type sécurisé comme peap ou ttls.
    • Configurez les sections peap et/ou ttls.
    • Spécifiez les chemins vers vos certificats serveur (clé privée, certificat, CA) dans la section tls-config tls-common. Ces certificats sont présentés aux clients lors de la négociation EAP.
      Fichier ini
          eap {
              default_eap_type = peap
              timer_expire = 60
              ignore_unknown_eap_types = no
              cisco_accounting_username_bug = no
      
              # Types EAP supportés
              peap {
                  # Utiliser la config TLS par défaut
                  tls_config = tls-common
                  # Phase 2 d'authentification (souvent MSCHAPv2)
                  default_eap_type = mschapv2
                  virtual_server = "inner-tunnel" # Référence au serveur virtuel pour la phase 2
              }
      
              ttls {
                  tls_config = tls-common
                  default_eap_type = mschapv2 # Ou PAP pour TTLS/PAP
                  virtual_server = "inner-tunnel"
              }
      
              # Configuration TLS commune
              tls-config tls-common {
                  private_key_file = ${certdir}/server.key # Votre clé privée serveur
                  certificate_file = ${certdir}/server.pem # Votre certificat serveur
                  ca_file = ${cadir}/ca.pem              # L'autorité de certification
                  # dh_file = ${certdir}/dh                # Paramètres Diffie-Hellman
                  check_crl = yes                       # Vérifier les listes de révocation
                  # ... autres options TLS ...
              }
              # ... autres configurations EAP ...
          }
      
  4. Modifier les Sites Virtuels (default et inner-tunnel)

    Modifiez /etc/freeradius/3.0/sites-available/default et /etc/freeradius/3.0/sites-available/inner-tunnel.

    • Dans default, section authorize, décommentez ou ajoutez ldap pour récupérer les infos utilisateur et eap pour gérer l’EAP.
    • Dans default, section authenticate, configurez Auth-Type EAP { eap }.
    • Dans inner-tunnel, section authorize, décommentez ou ajoutez ldap.
    • Dans inner-tunnel, section authenticate, décommentez Auth-Type LDAP { ldap }.

    Exemple simplifié (sites-available/default):

    Fichier ini
        server default {
            # ...
            authorize {
                # ...
                filter_username
                preprocess
                # Charger les infos depuis LDAP
                ldap
                # Initialiser EAP
                eap {
                    ok = return
                    updated = return
                }
                # ... autres modules ...
                # expiration
                # logintime
                # pap # Si vous supportez PAP directement (non-EAP)
            }
    
            authenticate {
                # Gérer l'authentification EAP
                Auth-Type EAP {
                    eap
                }
                # Gérer l'authentification PAP (si supporté)
                # Auth-Type PAP {
                #    pap # Ou ldap si PAP est validé directement contre LDAP
                # }
                # ... autres types d'authentification ...
            }
            # ... sections preacct, accounting, session, post-auth ...
        }
    
    Exemple simplifié (sites-available/inner-tunnel):
    Fichier ini
        server inner-tunnel {
            # ...
            authorize {
                # ...
                # Nécessaire pour récupérer les détails utilisateur dans le tunnel
                ldap
                # Authentification interne (ex: MSCHAPv2)
                mschap
                # ...
            }
    
            authenticate {
                # Valider les identifiants via LDAP
                Auth-Type LDAP {
                    ldap
                }
                # Gérer l'authentification interne (MS-CHAP, PAP dans TTLS, etc.)
                # Auth-Type MS-CHAP {
                #    mschap
                # }
                # Auth-Type PAP {
                #    pap # Valide le mot de passe via le module PAP (souvent après LDAP)
                # }
                # ...
            }
            # ...
        }
    

    Activez les sites (si ce n’est pas déjà fait) :

    sudo ln -s /etc/freeradius/3.0/sites-available/default /etc/freeradius/3.0/sites-enabled/
    sudo ln -s /etc/freeradius/3.0/sites-available/inner-tunnel /etc/freeradius/3.0/sites-enabled/
    
  5. Redémarrer FreeRADIUS et Tester

    sudo systemctl restart freeradius.service
    # Tester en mode debug pour voir les logs détaillés
    sudo freeradius -X
    

    Utilisez radtest ou eapol_test pour vérifier que l’authentification EAP contre LDAP fonctionne.

Partie 2 : Intégration de Duo Security avec Docker

Nous allons utiliser le Duo Authentication Proxy comme serveur RADIUS principal auquel les NAS se connecteront. Ce proxy gérera l’interaction avec Duo Cloud et relaiera l’authentification primaire à notre serveur FreeRADIUS/LDAP configuré ci-dessus.

  1. Préparer la Configuration du Duo Auth Proxy

    Créez un répertoire pour la configuration et les logs du proxy, par exemple /opt/duoauthproxy/. Créez un fichier authproxy.cfg dans /opt/duoauthproxy/conf/.

    Fichier ini
        # /opt/duoauthproxy/conf/authproxy.cfg
    
        [main]
        # Clés fournies par l'application RADIUS dans votre console Duo Admin
        ikey = VOTRE_IKEY_DUO
        skey = VOTRE_SKEY_DUO
        api_host = VOTRE_API_HOST_DUO
        # Permet les appels même si le certificat Duo n'est pas vérifiable (NON RECOMMANDÉ en production)
        # http_proxy=your_proxy.example.com:8080 # Si vous utilisez un proxy HTTP sortant
        failmode = safe # 'safe': Accès autorisé si Duo indisponible, 'secure': Accès refusé
    
        # Section pour le serveur RADIUS primaire (votre FreeRADIUS/LDAP)
        [radius_server_auto]
        ikey = RKEY_POUR_FREERADIUS # Une clé unique pour cette section (inventez-la)
        skey = SECRET_PARTAGE_FREERADIUS # Doit correspondre au secret défini dans FreeRADIUS pour le proxy Duo
        api_host = api-XXXXXXXX.duosecurity.com # Votre API Host Duo (peut être différent de celui de [main])
        radius_ip_1 = ADRESSE_IP_FREERADIUS # IP de votre serveur FreeRADIUS
        radius_secret_1 = SECRET_PARTAGE_FREERADIUS # Secret que FreeRADIUS attend du proxy Duo
        port = 1812 # Port standard RADIUS Auth
    
        # Section définissant comment le proxy écoute les requêtes RADIUS des NAS
        [radius_client]
        # Cette section utilise les configurations de [main] et [radius_server_auto]
        # Assurez-vous que le port n'est pas déjà utilisé (ex: si FreeRADIUS tourne sur le même hôte)
        # Si FreeRADIUS et Duo Proxy sont sur le même hôte, changez le port d'écoute de l'un des deux.
        # Ici, on suppose que Duo Proxy écoute sur 1812 et FreeRADIUS sur un autre port ou IP.
        port = 1812
        # Interface d'écoute (optionnel, 0.0.0.0 par défaut)
        # interface = 0.0.0.0
        failmode = safe # Ou secure
    
        # Vous pouvez ajouter des sections [ad_client] ou [ldap_client] si vous voulez que
        # le proxy contacte directement AD/LDAP pour la phase 1, mais ici on utilise [radius_server_auto]
        # pour pointer vers notre FreeRADIUS existant.
    

  2. Configurer FreeRADIUS pour accepter le Duo Auth Proxy comme Client

    Ajoutez une entrée pour le Duo Auth Proxy dans /etc/freeradius/3.0/clients.conf sur votre serveur FreeRADIUS :

    client duo_proxy {
        ipaddr = ADRESSE_IP_DUO_PROXY # IP de la machine/conteneur Docker hébergeant le proxy
        secret = SECRET_PARTAGE_FREERADIUS # Le même secret que dans authproxy.cfg [radius_server_auto]
        nas_type = other
    }
    

    Rechargez FreeRADIUS : sudo systemctl reload freeradius.service

  3. Créer le Dockerfile pour Duo Authentication Proxy

    Créez un fichier nommé Dockerfile dans le répertoire /opt/duoauthproxy/ :

    Fichier Dockerfile
        # Utiliser une image Python légère comme base
        FROM python:3.9-slim
    
        LABEL maintainer="Votre Nom <votre.email@example.com>"
        LABEL description="Duo Security Authentication Proxy"
    
        ARG DUO_PROXY_VERSION=latest
        # Vous pouvez fixer une version spécifique, ex: 5.2.0
        # ARG DUO_PROXY_VERSION=5.2.0
    
        # Variables d'environnement pour le chemin d'installation
        ENV DUO_PROXY_DIR /opt/duoauthproxy
    
        # Dépendances système nécessaires pour la compilation et l'exécution
        RUN apt-get update && apt-get install -y --no-install-recommends \
            build-essential \
            libffi-dev \
            libssl-dev \
            python3-dev \
            # Potentiellement d'autres dépendances si vous utilisez des modules spécifiques (ex: ldaps)
            # libsasl2-dev \
            # libldap2-dev \
            && rm -rf /var/lib/apt/lists/*
    
        # Créer le répertoire d'installation et de configuration/logs dans l'image
        RUN mkdir -p ${DUO_PROXY_DIR}/conf ${DUO_PROXY_DIR}/log
    
        # Installer le Duo Authentication Proxy via pip
        # Utiliser l'argument pour spécifier la version
        RUN pip install --no-cache-dir duoauthproxy==${DUO_PROXY_VERSION} \
            || pip install --no-cache-dir duoauthproxy # Fallback si la version n'est pas spécifiée ou 'latest'
    
        # Copier le fichier de configuration local dans l'image
        COPY conf/authproxy.cfg ${DUO_PROXY_DIR}/conf/authproxy.cfg
    
        # Créer un utilisateur non-privilégié pour exécuter le proxy
        RUN useradd --system --home ${DUO_PROXY_DIR} --shell /usr/sbin/nologin duo_proxy
    
        # Ajuster les permissions
        RUN chown -R duo_proxy:duo_proxy ${DUO_PROXY_DIR} \
            && chmod 600 ${DUO_PROXY_DIR}/conf/authproxy.cfg # Sécuriser le fichier de config
    
        # Définir l'utilisateur
        USER duo_proxy
    
        # Définir le répertoire de travail
        WORKDIR ${DUO_PROXY_DIR}
    
        # Exposer le port RADIUS (si vous utilisez [radius_client])
        # Note: Ce port doit être mappé lors du `docker run` ou dans docker-compose.yml
        EXPOSE 1812/udp
    
        # Commande par défaut pour lancer le proxy
        CMD ["/usr/local/bin/authproxy", "--config", "/opt/duoauthproxy/conf/authproxy.cfg"]
        # Alternative pour lancer en mode foreground avec logs sur stdout/stderr (préférable pour Docker)
        # CMD ["/usr/local/bin/authproxy_run"]
    

  4. Créer un fichier docker-compose.yml (Optionnel mais recommandé)

    Créez un fichier docker-compose.yml dans /opt/duoauthproxy/ :

    Fichier docker-compose
        version: '3.7'
        services:
          duoauthproxy:
            build:
              context: .
              # dockerfile: Dockerfile # Par défaut, cherche Dockerfile dans le contexte
              args:
                # Spécifiez la version si vous le souhaitez
                # DUO_PROXY_VERSION: 5.2.0
                DUO_PROXY_VERSION: latest
            container_name: duo_auth_proxy
            hostname: duo-proxy
            volumes:
              # Monter le fichier de configuration pour le modifier sans reconstruire
              - ./conf/authproxy.cfg:/opt/duoauthproxy/conf/authproxy.cfg:ro # Read-only recommandé
              # Monter le répertoire de logs pour persistance
              - ./log:/opt/duoauthproxy/log
            ports:
              # Mapper le port RADIUS de l'hôte vers le conteneur
              - "1812:1812/udp"
              # Mapper d'autres ports si nécessaire (ex: LDAPS 636 si le proxy contacte LDAP directement)
            restart: unless-stopped
            # Optionnel: Définir un réseau spécifique si nécessaire
            # networks:
            #   - proxy_network
    
        # networks:
        #   proxy_network:
        #     driver: bridge
        ```
    

  5. Construire et Lancer le Conteneur

    Depuis le répertoire /opt/duoauthproxy/ :

    # Construire l'image (si vous utilisez docker-compose)
    sudo docker-compose build
    
    # Lancer le conteneur en arrière-plan
    sudo docker-compose up -d
    
    # Afficher les logs
    sudo docker-compose logs -f
    

Partie 3 : Mettre à jour la Configuration des NAS

Vous devez maintenant reconfigurer vos commutateurs et points d’accès (NAS) pour qu’ils envoient les requêtes RADIUS à l’adresse IP du serveur Docker hébergeant le Duo Authentication Proxy, et utilisent le secret partagé défini dans la section [radius_client] implicite de authproxy.cfg (qui est souvent dérivé de [radius_server_auto] ou configuré spécifiquement si vous ajoutez une section secret à [radius_client]).

  • Serveur RADIUS : IP de l’hôte Docker.
  • Port RADIUS : 1812 (ou celui que vous avez mappé).
  • Secret Partagé : Le secret que le NAS utilisera pour parler au Duo Proxy. Important : Par défaut, [radius_client] ne définit pas son propre secret et le comportement peut varier. Il est plus sûr de définir explicitement le secret attendu des NAS, soit en ajoutant secret = VOTRE_SECRET_NAS à [radius_client], soit en faisant correspondre le secret du NAS au radius_secret_1 de [radius_server_auto]. Consultez la documentation Duo pour le comportement exact. Pour plus de clarté, il est souvent préférable d’avoir un secret entre NAS et Proxy, et un autre entre Proxy et FreeRADIUS.

Partie 4 : Test Final

  1. Vérifiez les Logs : Surveillez les logs de FreeRADIUS (/var/log/freeradius/radius.log ou freeradius -X) et les logs du conteneur Duo Proxy (docker-compose logs -f).
  2. Test Client : Essayez de vous connecter au réseau (Wi-Fi ou filaire) avec un client configuré pour 802.1X (PEAP ou TTLS).
  3. Flux Attendu :
    • Le client initie la connexion EAP.
    • Le NAS relaie à Duo Proxy (IP Hôte Docker:1812).
    • Duo Proxy relaie à FreeRADIUS (IP FreeRADIUS:1812 - ou le port où FreeRADIUS écoute réellement).
    • FreeRADIUS valide via LDAP.
    • FreeRADIUS répond au Duo Proxy.
    • Duo Proxy contacte Duo Cloud -> Envoi d’une notification Push (ou attente de code).
    • Utilisateur approuve/saisit le code.
    • Duo Proxy reçoit la confirmation de Duo Cloud.
    • Duo Proxy envoie Access-Accept au NAS.
    • Le NAS autorise l’accès au client.

Conclusion

Vous disposez maintenant d’une solution d’authentification réseau 802.1X renforcée, utilisant votre annuaire OpenLDAP existant et la sécurité additionnelle de l’authentification multifacteur Duo. Le déploiement du Duo Authentication Proxy via Docker simplifie la gestion et l’isolement de ce composant critique. N’oubliez pas de maintenir à jour FreeRADIUS, le Duo Proxy et les dépendances système pour garantir la sécurité et la stabilité de votre infrastructure.