IPSec

De Site à José Mans


Tutoriel

IPSec IKEv2 et L2TP


version 1.1

Créé le 15 Janvier 2026
Mise en ligne 26 Juin 2026.
Mise à jour le 26 Juin 2026.
Auteur

José Mans



Méthode / Organisation

Réglage des services nécessaires en premier, soit l'authentification puis gestion d'un tunnel IKEv2 (MOBIKE) avec deux méthodes VICI et Stoke.

Une fois le tout fonctionnel, ajout des procédures pour gérer IPSec avec L2TP et ainsi assurer la compatibilités de certains dispositifs informatiques.

Sans oublier de sécuriser les accès à L2TP dans le routeur. Ainsi que les règles de base d'un pare-feu. D'où l'usage d'un script qui place tous les tunnels dans une interface XFRM dédié afin de simplifier son utilisateur coté serveur.

On suit les conseils des organisations officielles ANSSI et ITEF en utilisant des algorithmes robustes et non cassables avec un simple GPU.

Nous utiliseront un annuaire LDAP (OpenLdap ou Active Directory) et la base 'files' uniquement pour les essais.

Les tunnels auront une double attribution d'IP, ils fonctionneront en ipv4 et aussi en ipv6 mais sans RA en raison d'une limitation logiciel.

En ipv4, seront utilisés des adresses privées au contraire des ipv6 qui "pourront" être accessibles depuis notre réseau et pour certaines depuis internet, donc pas de privées avec fd00::/8, c'est le pare-feu qui déterminera qui est visible depuis internet ou pas.

Installations serveur

Strongswan peut être paramétré avec deux méthodes différentes. La plus moderne se nomme (VICI) et utilise le fichier swanctl.conf.

La plus ancienne se nomme Stroke (ou légacy) et sa configuration est stockée dans deux fichier strongswan.conf et ipsec.conf.

<!> Pour simplifier les termes "VICI" ou "moderne" seront employer quand il s'agira d'aborder la configuration moderne et recommandée par l'ensemble des acteurs du secteur, soit "swanctl.conf".

"Legacy" ou "Stroke" quand l'ancienne configuration sera concernée, soit celle avec le fichier "strongswan.conf".

Version utilisées

  • strongSwan swanctl 5.9.13
    • version identique pour Stroke
  • FreeRADIUS Version 3.2.5
  • xl2tpd version: xl2tpd-1.3.18
  • pppd version 2.4.9
    • inclus radius

Distribution

Les paquets commun sont :

PAK_COMMON="xl2tpd freeradius freeradius-ldap freeradius-utils ppp"

Ceux pour la version moderne de strongswan (celle retenue) :

VICI="strongswan-swanctl charon-systemd "${PAK_COMMON}

Pour la version Legacy :

STROKE="strongswan strongswan-charon strongswan-starter "${PAK_COMMON}

Selon votre cahier des charges, choisir une commande ou l'autre.

Installation

Faire un choix entre Moderne et Legacy :

Moderne

apt-get install -y $VICI

Legacy

apt-get install -y $STROKE

NetworkManager

Pour les utilisateur de NetworkManager, penser à installer le paquet dédié, "strongswan-nm"

Accès Radius pour Ipsec IKEv1 et xL2TP

Étape utile uniquement si on veut utiliser IPSec/2LTP.

Les dictionnaires livrés avec freeradius ne sont pas acceptés par le plugins pppd-radius, la syntaxe n'est pas la même alors que les attributs le sont ; tenter de comprendre pourquoi est chronophage.

Aussi il faut se procurer le source du plungin, récupérer les deux dictionnaires et la config nécessaire pour que pppd-radius fonctionne sans erreur et warning.

On ne copie que la partie configuration de ppp-radius :

cd /usr/src
git clone https://github.com/ppp-project/ppp
# <!> curl -L https://github.com/ppp-project/ppp/archive/refs/heads/master.zip -o ppp_master.zip && unzip ppp_master.zip "ppp-master/pppd/plugins/radius/etc/*" && cp -a ppp-master/pppd/plugins/radius/etc/ /etc/ppp/radius && rm -rf ppp-master
cp -a ppp/pppd/plugins/radius/etc/ /etc/ppp/radius
rm -rf ppp

Configurations

FreeRadius ¬

Résumé : FreeRadius est un outil de contrôle d'applications qui ont besoin d'identifications diverses avec des annuaires (LDAP, SQL, ...)

FreeRadius est un service essentiel pour le projet. Il permet de centraliser les sources et les demandes d'identifications de l'entreprise, grâce à ses nombreux méthodes (protocoles) d'interopérabilité. Il est compatible AAA ce qui signifie : Authentication, Authorization, Accounting/Auditing.

Il est très souvent utilisé dans lieux publics (Hôtels, Aéroport,...)


Mise en garde avec le module 'files' et 'pap'. Dans tout le document cette méthode est abordée pour des raisons pédagogiques/tests, car elle ne nécessite pas de base LDAP, sql ou autre, les identifiants peuvent être placés dans un fichier texte avec mot de passe en clair , module mods-avaible/authorize.

Même si Ipsec code remarquablement bien les échanges entre le client et serveur, cela constitue une faille de sécurité parce que les mots de passe sont accessibles, en local et sans effort, par un éventuelle bot/humain.

Une fois les essais terminés je recommande fortement de mettre en commentaire toutes les parties qui traitent 'files' et 'pap' dans les section authorize et authentificate de FreeRadius.


Les sources

Base de données qui contient l'ensemble des utilisateurs, leurs droits, ... Elles peuvent être de plusieurs formes :

  • un annuaire LDAP
    • Active Directory
    • openLDAP
  • files, /etc/freeradius/3.0/users
  • SQL
  • fichier contenant des identifiants et mot de passe en clair comme pap-secret, ...
  • unix, /etc/{passwd,shadow}

Les demandes d'identifications

  • Réseau Wifi
  • VPN
  • Lecteur carte à puce
  • Lecteur biométrique
  • NAS
  • switch
  • VoIP,
  • SIP
  • ...

Les modules essentiels

Les premiers échanges vont se faire à l'aide d'un certificats publique signé par une autorité de confiance ; on peut utiliser un certificat auto-signé (non traité ici).

Une fois la liaison ouverte entre client/serveur, vient l'authentification de l'utilisateur au moyen de protocoles comme EAP, MS-Chapv2, ...

Il faut donc activer les modules qui vont être employés pour les échanges.

Accès à l'annuaire

  • Activation des modules :
# eap est linké par défaut... si ce n'est pas le cas faire comme pour ldap ci-dessus.
cd /etc/freeradius/3.0/mods-enabled
ln -s ../mods-available/ldap
  • Backup de la config originale de ldap :
cd /etc/freeradius/3.0/mods-available/
cp -a ldap ldap.origin

Ci-dessous se trouve l'intégralité des procédures permettant de connexion Radius à une base LDAP (openldap ou ad). Si vous utilisez une base LDAP de Microsoft et que vous ne connaissez pas par cœur les objets, class, un tableau de concordance existe dans la documentation Keycloak, aussi il ne sera pas copié ici.

Procédure complète pour que Radius communique avec un annuaire LDAP géré par openLDAP :

<!> Pour un Active Directory, veuillez consulter la table de concordances.

cat - > ldap << "EOF"

ldap {
    server = "localhost"
    port = 389 # ou 636 pour LDAPS
    identity = "cn=read-only,dc=gyptis,dc=org" # DN de l'utilisateur de liaison
    password = XXXXXXXXX
    base_dn = "dc=gyptis,dc=org"
    user_dn = "LDAP-UserDn"

    user {
        # AD ou=users,$...
        base_dn = "ou=people,${..base_dn}"
        #filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
        filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
    }

    group {
        # AD ou=users,$...
        base_dn = "ou=groups,${..base_dn}"
        filter = '(objectClass=posixGroup)'
        name_attribute = cn
    }

    tls {
        start_tls = yes # ou no si tu utilises LDAPS
        require_cert = "allow" # Correspond à TLS_REQCERT allow
    }

    update {
        # En renseignant NT-Pasword on précise aux modules mschap, pap, ... qu'il existe une version NT-Hash du mdp
        &control:NT-Password := "sambaNTPassword"

        #<!> Toutes les lignes contenant "userPawword" doivent être commentées si Radius interroge une base AD !

        # Pour EAP IkeV2 et désactivé pour ipsec/l2tp car il utilise : control:Cleartext-Password += 'userPassword'
        control:Crypt-Password += 'userPassword'
        # Si ldap stoquait les mdp en claire alors on décommenterait ci-dessous et commenterait ci-dessus la ligne 'control:Crypt-Password' = ....
        #control:Cleartext-Password += 'userPassword'

        # Ici on ajoute dans la liste tous les types de password à traiter
        # Ici on ajoute tous les types de password à traiter par Freeradius
        &control:Password-With-Header += "userPassword"
        &control:Password-With-Header += "sambaNTPassword"

        # Attributs de session

        reply:Session-Timeout := '3600'
        reply:Idle-Timeout := '1800'
    }

    ok
}

EOF
Comportement MSCHAPv2

Dans le cas où ON souhaite utiliser de vieux protocoles comme L2TP avec IPSec, on doit activer le modules mschap :

cd /etc/freeradius/3.0/mods-enabled
ln -s ../mods-available/mschap
cd /etc/freeradius/3.0/mods-available/
mv mschap mschap.origin
cat - > ldap << "EOF"
mschap {

    # Désactive l'usage de ntlm_auth (winbind)

    #use_ntlm_auth = no

    # Active la vérification directe du hash NT
    #nt_hash = yes

    use_mppe = yes # certain vieux système exigent mppe...
    require_encryption = yes
    require_strong = yes

    # Disable pour ppp-radius, sinon enable :

    # Enable si vous utilisez winbind, voir https://networkradius.com/doc/current/raddb/mods-available/mschap.html
    # Permet à FreeRADIUS de récupérer le hash NT depuis LDAP
    # et de le comparer avec la réponse MSCHAPv2 du client
    #passchange {
    #     # Optionnel : pour permettre les changements de mot de passe
    #}
    # Désactive les hacks spécifiques à NT-Domain
    # comme DOMAIN\User, User-Name = User

    with_ntdomain_hack = yes

}
EOF

Service principale

La configuration suivante décrit le fonctionnement par défaut de Radius, il est donc primordial de l'activer et de bien préciser ce qui est attendu.

Ce fichier se nomme "default" et se trouve dans le dossier sites-enabled/ !

Sauvegarde du fichier par défaut.

cd /etc/freeradius/3.0/sites-available/
cp -a default default.origin
# Avant toute personnalisation, on enlève le paramètre par défaut de 'ldap', 'pap' et 'chap' dans la section qui gère la récupération des identifiants du client et de l'annuaire puis on détermine l'ordre précis, en les replaçant plus bas, de ce qui doit se passer pendant cette phase 
sed -i -E '/^authorize[[:space:]]*\{/,/^}[[:space:]]*$/ { s/(.*(-ldap|pap|chap).*)/###\1 }' default
vi/nano default

Principe

La priorité est d'utiliser la base LDAP pour comparer les identifiants de l'utilisateur envoyés par le client et s'ils sont inconnus de LDAP la recherche doit s'effectuer dans les fichiers de mot de passe de /etc/freeradius/3.0/users (files) en clair et d'autres sources comme sql...

<!> Utiliser un mots de passe en clair n'est absolument pas conseillé...

L'ordre est donc important (...) car si radius rencontre un update/Auth-Type (dans authorize) avant la fin de récolte des autres méthodes, ces dernières seront ignorées.

'files', 'pap' - Base utilisateur /etc/freeradius/3.0/users

Comme décrit plus haut, l'usage de 'files' et 'pap' est vivement déconseillé. Cependant si n'avez pas de base openLDAP, AD ou équivalent ou vous souhaitez juste effectué des essais, cette section vous concerne.

Le fichier /etc/freeradius/3.0/users peut être utilisé comme annuaire utilisateur. Il faut simplement ajouter en début de fichier l'utilisateur de test.

En fin de fichier, il sera ignoré par les autres procédures présentes (DEFAULT ... ... et ...)

Example :

  • Nom_Utilisateur Cleartext-Password := "son_password_en_clair"

Récolte des identifiants

Récolte de la base LDAP et du client qui souhaite ouvrir un tunnel. Le formatage, filtrage de certains caractères sont effectués dans cette section.

Nous voulons ici : filtrer les champ du client avant tout (filter_username, preprocess, ...) et avec le résultat effectuer la recherche dans la base LDAP et, en cas d'échec, utiliser d'autres bases comme files/sql...

...

Section "authorize"

Un extrait de cette section :

authorize {
    filter_username

    preprocess

    # Nous souhaitons garder l'ip du demandeur, ici c'est "charon", afin de l'exploiter ultérieurement pour des stats.
    update control {
        &FreeRADIUS-Client-Shortname := "%{&request:NAS-IP-Address}"
    }

    ldap

    # <!> Ne pas confondre 'userPassword' du module ldap ci-dessus et la variable 'User-Password' envoyée par le client...

    # Si vos MDP sont enregistrés en clair dans votre base LDAP laissez cette partie. Sinon supprimez là, car elle ne sera jamais utilisée.
    # Idem si l'utilisateur existe que dans 'files' mais pas dans LDAP ; désactivez cette section.

    # Si mdp en clair (FreeRadius v2.xxx) dans User-Password, alors ldap sait gérer :
    if ((ok || updated) && User-Password && !control:Auth-Type) {
        update control {
        # On court-circuite les autres modules en laissant ldap gérer la validité du mdp :
        # On devrait désactiver : &Auth-Type := ldap
        # car ordonne à ldap de vérifier et valider ID/pwd.
        # Or si on a du 'files' en demande, la procédure ci-dessous cour-circuite l'authentification avec le module 'files'.
        &Auth-Type := ldap
        }
        ok
    }

    chap
    mschap
    digest
    suffix

    eap {
        ok = return
    }

    files
    -sql
    expiration
    logintime

    # Désactivez pap si vous avez une base ldap ET n'utilisez pas 'files'
    pap
    Autz-Type New-TLS-Connection {
        ok
    }

}

...

Explications

pap

Le mot de passe est transmis en claire par le client au serveur depuis la variable User-Password. C'est pourquoi le module est désactivé.

On peut remarquer dans le fichier 'default' d'origine la partie :

#
# If you're using Active Directory and PAP, then uncomment
# the following lines, and the "Auth-Type LDAP" section below.
#
# This will let you do PAP authentication to AD.
#
# if ((ok || updated) && User-Password && !control:Auth-Type) {
#     update control {
#         &Auth-Type := ldap
#     }
# }

Comme survolé plus haut, cette méthode désactive les suivantes en cas de réussite avec la procédure "&Auth-Type := ldap". Si on décommente cette partie c'est LDAP qui va déterminer, via son client, si l'identification de l'utilisateur sera ou pas valide. Dans le cas d'un échec, les modules qui suivent seront totalement ignorés. Et comme dis plus haut, nous voulons une base utilisateur avec le modules 'ldap' et  'files'. Si c'est votre cas, laissez la en commentaire ;)

Comparaison et validation

Une fois les informations clientes et celles de la base utilisateur de l'entreprise récoltées, la partie suivante est chargée de comparer les informations et valider le cas échéant.

Section "authenticate"

à placer après la section authorize {}

authenticate {

    Auth-Type LDAP {
        ldap
    }

    Auth-Type MS-CHAP {
        mschap
    }

	digest
    eap

    Auth-Type eap {
        eap {
            handled = 1
        }
        if (handled && (Response-Packet-Type == Access-Challenge)) {
            attr_filter.access_challenge.post-auth
            handled # override the "updated" code from attr_filter
        }
    }
}

Mettre toutes les autres méthodes après celles citées ci-dessus, car on veut que l'identification passe par ldap, si échec, 'files', ou autre.

Identification d'accès à Radius

On détermine ici comment l'accès au service Radius peut se faire. A la fois, quels identifiants (via Attributs) présenter à Radius pour qu'il accepte de rechercher, valider et du réseau autorisé à effectuer les demandes (localhost, local, ...).

Le service Radius est installé sur le même serveur qui gère IPSec (via Strongswan) et les échanges se feront exclusivement par localhost, car la communication se fait en clair pour l'ensemble des données hormis le mot de passe (du client vpn) qui est sous forme de hash ; donc un sniffeur sur le réseau local peut le récupérer et tenter une recherche brute de force en offline.

Cependant et toujours dans le cas pédagogique, les lignes suivantes traitent la possibilité d'interaction avec le réseau local.

Donc si le service Radius est déporté du serveur Ipsec, penser à créer un tunnel sécurisé entre les deux services et ne placer que l'ip sécurisée dans la partie "local_network" ci-dessous.

cd /etc/freeradius/3.0/
echo Sauvegarde client.conf
mv clients.conf clients.conf.origin

cat - > clients.conf << "EOF"

# Identification à partir de localhost.
# Paramètres pour toutes les demandes faite depuis le réseau localhost

client localhost {
    ipaddr = 127.0.0.1
    proto = *
    secret = XXXXX # MdP d'accès à Radius (PWD_RADIUS_ACCESS)

    nas_type = other

    limit {
        max_connections = 16
        lifetime = 0
        idle_timeout = 30
    }
}

# Réponse en IPv6 à toute la planète ( mauvaise idée ! )

#client localhost_ipv6 {

    #ipv6addr = ::1
    #secret = XXXXXX
#}

# Identification à partir de réseau local d'entreprise.

client local_network {
    ipaddr = 192.168.0.233
    netmask = 16
    secret = XXXXXX # le PWD_RADIUS_ACCESS
    require_message_authenticator = no
    nastype = other
}
EOF

Lancement de FreeRadius

chmod freerad:freerad -R /etc/freeradius/3.0
systemctl restart freeradius

Contrôle de fonctionnement (Tester)

FreeRadius possède un mode verbose utile pour débugger ou voir ce qui se passe pendant toutes les phases : identification, échange avec client, consultations d'annuaire...

Il est recommandé d'utiliser les options de debuggage maximale et de lancer le service en console et donc en stoppant le service :

systemctl stop freeradius

Lancer Radius avec options debuggage.

freeradius -X -x
Tester tous les protocoles d'identifications

Remplacer :

  • PWD_RADIUS_ACCESS
    • le mot de passe d'accès au service Radius
  • USERNAME
    • Le nom d'utilisateur a identifier, le même que celui envoyé par le client.
  • PWD_USER_REQUEST
    • Son mot de passe, en clair.

Script de vérification de protocoles contenu dans la variable PROT_ID :

PROTO_ID="pap chap mschap eap-md5"
for proto in $PROTO_ID; do echo -n PROTO: $proto ; radtest -t $proto USERNAME PWD_USER_REQUEST localhost 0 PWD_RADIUS_ACCESS -- 1&gt; /dev/null ; if [ "$?" == "0" ]; then echo ' is valid' ; fi ; done

Strongswan ֎

Cet outil implémente la gestion IPSec et certificats (X509). C'est avec lui que la gestion des tunnels IKEv2 et IKEv1 va pouvoir s'effectuer.

Pour gérer les tunnels nous avons créé une nouvelle interface de type "xfrm" qui sera dérivée de l'interface physique qui réceptionne les demandes IPSEC.

Résumé fonctionnement

  • chargement des modules
  • méthodes d'identifications
  • comportement global...

/etc/strongswan.conf (VICI ou STROKE)

charon {
    load_modular = yes

    plugins {
        include strongswan.d/charon/*.conf

        kernel-netlink {

            # gestion des tunnels dans une table XFRM séparées de la table principale (de rule 0)
            install_routes_xfrmi = yes

            # Réduction du "Max Segment Size" pour l'établissement de connexion.
            mss = 1360
        }

        attr {
			load = yes
		}

		# Pour eap-mschapv2 et eap-radius.
		# Je préfère placer leurs configurations ici et laissé les paramètres
		# par défaut se chargé depuis charon/*.conf.
		# Ceci afin de réduire la complexité pour la maintenance et sauvegarde.
		# Et n'avoir qu'un fichier à éditer/modifier.

		eap-radius {
			# Aide : https://docs.strongswan.org/docs/latest/plugins/eap-radius.html
			load = yes
			accounting = yes # Radius initie EAP-Start si égal à 'yes' pour gérer l'ip et d'autres params via RADIUS
			
			eap_start = yes # tous les serveurs ne le supportent pas. no dans la plus part des cas.
			class_group = yes # permet d'avoir plusieurs serveurs RADIUS, 'preference=99' donne l'ordre des priorités

			servers {
				primary {
					# Autorisation d'accès à Radius
					address = 127.0.0.1
					secret = XXXXXX
					auth_port = 1812
					acct_port = 1813
					nas_identifier = "gyptis-vpn" # Identité visible dans les logs de Radius
				}
			}
			#preference=99 # si serveur RADIUS secondaire.
		}

		eap-mschapv2 {
			load = yes
		}
    } # plugins

    # Paramètres réseau
    install_routes = no # yes, pour utiliser une table de route distincte (rule 220 défaut), on utilise XFRM, donc no
    install_virtual_ip = yes # car pas de dhcpd actif
}

include strongswan.d/*.conf

Strongswan peut gérer les nouveaux tunnels dans une table distinct avec l'option "install_routes=yes" et ainsi utiliser la table N° 220 ; voir la liste dans /etc/iproute2/rt_tables.

Or nous avons plusieurs types de tunnel ce qui imposent d'utiliser une autre table de routage pour celui qui concerne cette configuration. En revanche avec IPSec/L2TP la gestion du routage est gérée sur la table par défaut (rule 0) donc rien ne sera fait pour cette version.

De plus XFRM est utilisé pour la sécurisation des tunnels, chaque nouveau tunnel (IKEv2) sera géré dans une table spécifique. Ici rule 100.

Configuration du tunnel

Pour comprendre un minimum ce qui est traités dans la configuration ci-dessous, le tableau ci-après montre les principaux éléments à adapter selon la charte du réseau où sera déployé strongswan.

Table des directives essentielles

connections { ... } Section référençant tous les types de tunnels utilisés.
local_addrs IP du service par laquelle est reçus les demandes des clients.

Si le serveur est NAT-D par un routeur, mettre l'ip indiquée par le routeur.

%any indique de servir depuis toutes les sources

remote_addrs ensemble d'IPS étant autorisés à échanger avec le service.

Pour répondre aux requêtes d'internet, %any convient le mieux.

Pour restreindre l'accès à IPsec une plage ip (IP/CIDR) peut être employée, voire séparée de virgule avec d'autres plages...

local_ts et remote_ts sont géré dans la partie CHILD_SA. Placer la plage IP autorisée à passer au travers du tunnel.
local_ts Filtrage sur le réseau LAN
remote_ts Filtrage sur le réseau VPN
pools attribution d'une plage IP pour les clients.

dhcp est autorisé, mais nécessite un ajout dans stronswan.conf, voir Annexe -> dhcpc

proposals C'est la partie la plus sensible d'un Tunnel IPSec.

Algorithme autorisés à être utilisés.

Il est possible d'élargie les possibilités dans une seule ligne.

Si on veut travailler avec ECP384 et permettre l'usage d'ECP512, on ajoute simplement dans cette ordre :  proposals = aes256gcm16-prfsha384-ecp512-ecp384, ...

Si un client propose un autre choix que ceux proposés, le serveur refusera. voir la section "Sécurité" de https://applireseau.com/glpi/front/ticket.form.php?id=450

    • Partie, type de tunnel, méthodes accordées de sécurisation des échanges du (et dans) le tunnel, configuration réseau des tunnels
updown Lancement du script qui attribut qui place le tunnel dans une table dédiée à IPSEC.


updown = /etc/strongswan.d/route-script.sh

if_id_in = 100

if_id_out = 100

/etc/swanctl/swanctl.conf (VICI)

connections {
    ikev2 {
        version = 2
        local_addrs = %any
        remote_addrs = %any
        send_cert = always
        proposals = aes256gcm16-prfsha384-ecp384,aes256gcm16-prfsha384-curve25519,aes256-sha384-prfsha384-modp2048
        fragmentation = yes
        encap = yes # = forceencaps=yes
        dpd_delay = 300s
        dpd_timeout = 120s
        rekey_time = 0 # rekey=no
        reauth_time = 0 # reauth=no
        unique = no # uniqueids=no

        # Choix topologie résau, ipv4 locale, ipv6 réel
        pools = ipv4-dummy, ipv6-real
        #ou pools = dhcp, mais préparation à effectué dans charon
        local {
            auth = pubkey
            id = applireseau.com
            certs = applireseau.pem # ← à placer dans /etc/swanctl/x509/
        }
        remote {
            auth = eap-radius
            eap_id = %any # correspond à eap_identity=%identity côté serveur
        }
        children {
            ikev2 {
                local_ts = 0.0.0.0/0, ::/0
                esp_proposals = aes256gcm16-ecp384,aes256gcm16-curve25519,aes256-sha256-modp2048,aes256gcm16
                life_time = 24h # lifetime du %default
                # keyingtries=%forever → automatique avec rekey_time=0
                # Utilisation d'une nouvealle table spécique à notre tunnel IKEv2
                # Nommée xfrm32 de valeur 100 (''REF20260301'')
                updown = /etc/strongswan.d/route-script.sh
                if_id_in = 100
                if_id_out = 100
            }
        }
    }

    # placement futur config IPSec/L2TP 
}

pools {
    ipv4-dummy {
        addrs = 10.0.0.3/24
        dns = 8.8.8.8
    }

    vpn-to-any {
        # Notation avec /prefix
        addrs = 2001:41d0:303:3338::100/112
        dns = 2001:4860:4860::8844
    }

    ipv6-real {
        # Notation avec interval
        addrs = 2001:41d0:303:3338::100-2001:41d0:303:3338::1ff
    }
}

secrets {
    # Clé privée du certificat Let's Encrypt (obligatoire pour auth=pubkey)
    private-ikev2 {
        file = /etc/letsencrypt/live/applireseau.com/privkey.pem
        # secret = "sa_passphrase" # décommenter seulement si la clé, du certificats SSL, est chiffrée
    }

    # PSK pour L2TP (PSK remplace un certificat privé ou publique.)
    ike-l2tp {
        # Clé pré-partagée avec les clients
        secret = "YYYYYYY"
     }

    # On peut utiliser plusieurs clés pour L2TP
    # secrets.ike-.secret
    ike-other {
        secret = "Autre PSK client"
    }
}

authorities {
    letsencrypt {
        cacert = letsencrypt_r12.pem
    }
}

# Include config snippets
include conf.d/*.conf


Certificats SSL

Pour les tunnels IKEv2 il est fortement recommandé d'employer des certificats publiques. ici est utilisé ceux fournit par Let's encrypt.

La méthode VICI offre la possibilité, sans interruption de service, de mettre à jour les certificats utilisés par le serveur, c'est pourquoi des liens symboliques sont utilisés comme ci-dessous et pointant vers la dernière version (live) du certificat Let'Encrypt.

Un simple "swanctl --load-all" (ou swanctl --load-creds) dans le script qui gère leurs renouvellement (ex: certbot) et pas besoin de revenir sur cette partie de la configuration...

Mise en place des certificats.

La gestion des certificats de strongswan impose de les déclarer dans ses dossiers de /etc/swanctl/*.

Il n'est pas permis de placer un chemin absolu dans la configuration des variables "certs et cacert"...


Dans un shell

    • SSL_CN=domain
    • # Let'encrypt
    • ln -s /etc/letsencrypt/live/${SSL_CN}/chain.pem /etc/swanctl/x509ca/letsencrypt_r12.pem
    • ln -s /etc/letsencrypt/live/${SSL_CN}/fullchain.pem /etc/swanctl/x509/${SSL_CN}.pem
    • ln -s /etc/letsencrypt/live/${SSL_CN}/privkey.pem /etc/swanctl/private/${SSL_CN}.key
    • # Inutile pour des liens symboliques, mais si on veut placer des copies des certificats penser :
    • chmod 600 /etc/swanctl/{x509a,x509,private}/*

Mise en route

Version VICI

Démarrer les services au démarrage du serveur :

    • systemctl enable strongswan

Lancer les services de tunnel dès que la configuration est finalisée

    • systemctl start xl2tpd strongswan

<!> Si xl2tpd est utilisé, faire la même chose avec "xl2tp.service"

Version Stroke

Démarrer les services au démarrage du serveur :

    • systemctl enable strongswan-starter xl2tpd

Lancer les services de tunnel dès que la configuration est finalisée

    • systemctl start strongswan-starter x2ltpd

Pour les phases d'essais, lancement de strongswan en foreground. Ceci afin d'avoir l'ensemble des informations de connexion sur un même tty. Okay, y a screen / tmux, mais c pas le sujet :D

    • ipsec start --nofork

États / Status des connexions

    • ipsec statusall

Upgrade à chaud seulement avec VICI

Une fois strongswan opérationnel s'il on a apporté des modifications, il n'est pas nécessaire d'interrompre le service avec un "system restart", la commande ci-dessous recharge à chaud les fichiers de configuration.

    1. swanctl --load-all

Si une erreur se produit, le service n'est pas interrompu et continue son exécution avec les anciens réglages.

En cas d'erreur

"swanctl --load-all" affichera simplement les éventuelles erreur détectées comme le montre cette exemple :

J'ai volontairement ajouté "xx" sur la ligne auth = pubkey de la section ikev2 et voici ce qu'indique la commande :

sudo swanctl --load-all

no files found matching '/etc/swanctl/conf.d/*.conf'

loaded certificate from '/etc/swanctl/x509/domain.pem'

loaded certificate from '/etc/swanctl/x509ca/letsencrypt_r12.pem'

loaded RSA key from '/etc/swanctl/private/domain.key'

loaded ike secret 'sec_l2tp'

loaded authority 'letsencrypt'

successfully loaded 1 authorities, 0 unloaded

loaded pool 'ipv4-dummy'

loaded pool 'vpn-to-any'

loaded pool 'ipv6-pool-vpn'

successfully loaded 3 pools, 0 unloaded

loading connection 'ikev2' failed: unknown option: xxauth, config discarded

loaded connection 'l2tp'

loaded 1 of 2 connections, 1 failed to load, 0 unloaded

Rappel : l'erreur est indiqué mais le service continue de fonctionner avec les anciens paramètres.


XFRM

XFRM est une implémentation du Kernel Linux depuis ~2004. Elle permet de transformer les paquets IP pour l'IPSEC (cryptage, authentification, compression) et d'autres comme certaines fonctionnalités mobile pour l'ipv6...

Les commandes de base :

  • ip -d link show type xfrm
  • ip -d xfrm state
  • ip -d xfrm policy
  • ip -d xfrm monitor

Ce script permet de gérer tous les tunnels IKEv2 dans une unique table autre que celle par défaut (N°220) et de séparer les tunnels de l'interface où il sont créés. Ce qui permet, en autre, d'appliquer des règles de pare-feu différentes du réseau principal (non documenté ici).

/etc/strongswan.d/route-script.sh

#!/bin/bash

umask 0077


# Mode debug

umask 0077

IP=$(echo ${PLUTO_PEER_CLIENT} | sed 's/\//_mask_/g')

OUT="/tmp/vpn.${PLUTO_XAUTH_ID}__${PLUTO_VERB}__${IP}"

exec &>> >(stdbuf -oL -eL tee -a ${OUT})


set -e


echo ---- START ----

date

IFIDNUM=100

IFID="if_id ${IFIDNUM}"

TABLE="table ${IFIDNUM}"

# Si interface v4 et v6 différente, Remplacer ${PLUTO_INTERFACE} par son 'device' que

# si le réseau V6 est géré sur une autre interface que le V4.

# PLUTO_INTERFACE contient l'interface d'où a été initié le tunnel, ex :

#    Si IPSEc initié sur "eth0", Si ipv4 passe par "eth0", ipv6 par "br0" et

#    PLUTO_INTERFACE=eth0 alors :

#         IF_V6 doit-être égal à br0 et non à eth0

IF_V4=${PLUTO_INTERFACE}

IF_V6=${PLUTO_INTERFACE}


DEV=${PLUTO_INTERFACE}

TUN=xfrm100

IF_V4="${TUN}"

IF_V6=${IF_V4}


TUNNEL_NAME="$PLUTO_CONNECTION"

LOCAL="$PLUTO_ME"

REMOTE="$PLUTO_PEER"

# L'IP virtuelle assignée au client est dans PLUTO_PEER_SOURCEIP

# (ou PLUTO_PEER_SOURCEIP4 / PLUTO_PEER_SOURCEIP6 si disponible)

SOURCEIP4="${PLUTO_PEER_CLIENT:-}"

SOURCEIP6="${PLUTO_PEER_CLIENT:-}"

#call ip link set ${TUN} up

# /sys/class/net/xfrm32 || /sys/devices/virtual/net/xfrm32/

[ -d /sys/class/net/${TUN} ] || \

{

echo Interface ${TUN} do not exist, Currently being created :

ip rule add table ${IFIDNUM}

ip -6 rule add table ${IFIDNUM}

ip link add ${TUN} type xfrm dev ${DEV} ${IFID}

ip link set ${TUN} up

ip addr add 192.168.12.3/24 dev ${TUN}

ip -6 r a default via ${GATEWAYv6} table ${IFIDNUM}

for ipv in ipv4 ipv6; do

sysctl net.${ipv}.conf.${TUN}.disable_policy=1

done

sysctl net.ipv4.conf.${TUN}.rp_filter=0

sysctl -w net.ipv4.conf.${DEV}.rp_filter=0

# Règles de pare-feu éventuelles :

}


case "$PLUTO_VERB" in

up-client)

if [ -n "$SOURCEIP4" ]; then

ip route add \"${SOURCEIP4}\" dev \"$IF_V4\" ${TABLE}

ip rule add from \"${SOURCEIP4}\" ${TABLE}

ip rule add to \"${SOURCEIP4}\" ${TABLE}

fi

;;

up-client-v6)

if [ -n "$SOURCEIP6" ]; then

ip -6 route add \"${SOURCEIP6}\" dev \"$IF_V6\" ${TABLE}

ip -6 rule add from \"${SOURCEIP6}\" ${TABLE}

ip -6 rule add to \"${SOURCEIP6}\" ${TABLE}

fi

;;

down-client)

if [ -n "$SOURCEIP4" ]; then

ip rule del from \"${SOURCEIP4}\" ${TABLE}

ip rule del to \"${SOURCEIP4}\" ${TABLE}

ip route del \"${SOURCEIP4}\" dev \"$IF_V4\" ${TABLE}

#2>/dev/null || true

fi

;;

down-client-v6)

if [ -n "$SOURCEIP6" ]; then

ip -6 route del \"${SOURCEIP6}\" dev \"$IF_V6\" ${TABLE}

ip -6 rule del from \"${SOURCEIP6}\" ${TABLE}

ip -6 rule del to \"${SOURCEIP6}\" ${TABLE}

fi

;;

esac

    • chmod 750 /etc/strongswan.d/route-script.sh


Pare feu - Firewall

Ce n'est pas le sujet de ce document, aussi, les exemples seront courts.

Autorisation de "laisser" passer UDP sur les ports 500 (isakmp), 4500 (ipsec-nat-t) et 1701 (l2f).

Voici un extrait de notre script qui gère le pare-feu :

  • CHAIN=INPUT | input | chaîne personnalisée
  • IFACE="eno1"

Règles pour le serveur :

Commandes nft

Création d'un alias pour le tunnel

  • nft add set inet filter IPSec_udp { type inet_service ; elements = { 500,4500, 1701 } }

Chaîne personnalisées

  • nft add inet filter input iifname "${IFACE}" counter jump ${CHAIN}
    • la règle ci-dessus est valable que si vous avez des chaînes personnalisées. Si non :

Direct dans en entrée du pare-feu

  • nft add rule inet filter ${CHAIN} udp dport @IPSec_udp counter accept

Commandes iptables

  • iptables -A ${CHAIN} -p UDP --dport 500 -j ACCEPT
  • iptables -A ${CHAIN} -p UDP --dport 4500 -j ACCEPT
  • iptables -A ${CHAIN} -p UDP --dport 1701 -j ACCEPT

Règles pour un routeur de VM

IF_VM="br0"

IP_DST="192.168.0.9" # L'ip où doivent aller les paquets du tunnel

Référencement des ports concernés (alias).

  • nft add set inet filter IPSec_udp { type inet_service ; elements = { 500,4500, 1701 } }
  • nft add set ip nat IPSec_udp { type inet_service ; elements = { 500,4500, 1701 } }


Seulement si les paquets doivent passer par l'ipv6 :

    • nft add set ip6 filter IPSec_udp { type inet_service ; elements = { 500,4500,1701 } }

Pour le FORWARD / DNAT

  • Autorisation de transfert de l'interface reliée à Internet à celle qui correspond à votre VM ou réseau secondaire local :
    • nft add rule inet filter forward iifname "${IFACE}" ip protocol udp udp dport @IPSec_udp counter accept
      • Si "secondaire" ajouter : oifname "nom interface autre réseau"
  • Translation d'adresses
    • nft add rule ip nat prerouting iifname "${IFACE}" ip protocol udp udp dport @IPSec_udp counter dnat to ${IP_DST}

Commande iptables

  • FORWARD && DNAT
    • /sbin/iptables -I FORWARD -i "${IFACE} -p UDP  --dport 500 -j ACCEPT
    • /sbin/iptables -t nat -I PREROUTING -j DNAT -i "${IFACE} -p UDP --dport 500 --to-destination ${IP_DST}
    • Idem pour les pour 4500 et 1701 (en udp)
    • IPv6
      • Remplacer iptables par ip6tables sans oublier de préciser une IPv6 dans IP_DST

Port destination

Avec nft ou iptables, il est recommandé de préciser l'interface de sortie pour l'autorisation du FORWARD

Pour nft ajouter oifname "device NAME"

Pour iptables : -o "device NAME"

"device NAME" est le nom de l'interface où doivent passer les paquets dans la chaîne FORWARD. Ici c'est xfrm100.


Restreindre l'usage des tunnels sans authentification système

Si vous utilisez IPSec/L2TP , pourquoi imposer ces règles pour les clients windows ?

Pour éviter toute utilisation du tunnel L2TP sans authentification ESP il est vivement recommandé d'empêcher cet usage.

En effet, si un client, et surtout sous windows, prévu pour se connecter en Ipsec/L2TP est mal configuré, la première partie négociée peut être ignorée et passer à la second partie, se connecter en L2TP.

L2TP est un protocole déclassé, sans Ipsec on ouvre la porte à n'importe qui...

Afin d'empêcher cela il est préférable d'interdire l'accès au service L2TP si et seulement si l'identification IPsec n'a pas été validée par le kernel.

Commande nft

  • nft add inet filter input udp dport 1701 meta ipsec exists accept counter
  • nft add inet filter input udp dport 1701 drop counter


commande iptables

  • /usr/sbin/iptables -A INPUT -p udp --dport 1701 -m policy --dir in --pol ipsec -j ACCEPT
  • /usr/sbin/iptables -A INPUT -p udp --dport 1701 -j DROP


Annexe

Service xl2tpd

L2TP Layer 2 Tunneling Protocol (RFC2661) est un protocole qui permet une liaison de couche 2 (ISO) entre deux point.

Xl2tpd permet de gérer cette liaison à travers un tunnel sécurisé IPSEC en utilisant l'UDP.

La liaison de niveau 2 est établie avec le protocole PPP, ce qui explique l'usage du daemon pppd.

Pour mettre en place un tunnel IPsec/L2TP il est nécessaire de coupler ppp à strongswan via xL2tpd.

De plus, par rapport à IKEv2, L2TP n'a pas de gestion unifiée pour le polls, car c'est xl2tpd qui gère l'attribution des IPs via pppd.

Il n'y pas grand chose à connaître dans les sections suivantes. A part l'importance primordiale de bien choisir les algorithmes d'échange pour les deux phases d'IPSec (IKE et ESP). Seul AES256 est utilisable, donc exit GCMAES256 ou de descendre en dessous de 256 comme aes192, aes128 qui réduit considérablement la sécurité et dans tous les cas déconseillé.

De même pour la clef PSK. Ici elle est gérée en phase 1 (IKE) et contrairement au tunnel IKEv2 plus haut, l'identification de l'utilisateur est faite en phase 2 par le démon pppd.

Voici donc une table de ce qui est à modifier dans les quatre configuration ci-dessous.

Les algorithmes a employer en phase 1 swantcl.conf proposals
Les algorithmes a employer en phase 2 esp_proposals
La clé PSK qui remplace un certificat, à choisir le plus complexe possible. connexions.l2tp.local.auth = psk

connexions.l2tp.remote.auth = psk

secrets.ike-l2tp.secret = 'Clé partagée entre client/serveur'

Il s'agit de faire passer L2TP dans un tunnel, donc un transport. mode = transport
local_addrs &

remote_addrs

Même réglage que pour la connexion IKEv2 plus haut.
plage IPs attribuées aux clients xl2tpd.conf ip range = plageIp
On refuse l'emploie de chap/pap local, car c'est Radius qui gère les identifications. refuse chap = yes

refuse pap = yes

require authentication = yes

DNS à utiliser options.xl2tpd ms-dns (3 max)
Si usage d'IPv6 dans le tunnel +ipv6

ipv6cp-accept-local

ipv6cp-accept-remote

Authentification choisie plugin radius.so, radattr.so

radius-config-file

Ajouter les quatre sections suivante pour permettre à strongswan d'initier des tunnels IPsec/L2TP :

/etc/swanctl/swanctl.conf (VICI)

A placer après la section ikev2 { ... }

l2tp {

version = 1 # Version IKEv1

local_addrs = %any

remote_addrs = %any

proposals = aes256-sha384-modp2048,aes256-sha256-modp2048

fragmentation = yes

encap = yes

dpd_delay = 300s

local {

auth = psk

}

remote {

auth = psk

}

children {

l2tp {

mode = transport

local_ts = 0.0.0.0/0[udp/1701]

remote_ts = 0.0.0.0/0[udp/1701]

esp_proposals = aes256-sha256-modp2048,aes256-sha256-none

rekey_time = 1h

life_time = 1h

life_bytes = 250000000

# rekeymargin=3m → géré automatiquement par rand_time

}

}

}

Identification Radius

/etc/ppp/radius/radiusclient.conf

auth_order radius

login_tries 4

login_timeout 60

nologin /etc/nologin

issue /etc/issue

authserver localhost

acctserver localhost

servers /etc/ppp/radius/servers

dictionary /etc/ppp/radius/dictionary

seqfile /var/run/radcli.seq

mapfile /etc/ppp/radius/port-id-map

default_realm

radius_timeout 10

radius_retries 3

nas_identifier PPPRadClient

/etc/ppp/options.xl2tpd

name l2tpd

#noccp

# Contrôle des liaisons lors d'innactivité dans le tunnel.

# Ceci est grandement conseillé quand on a des déconnexions régulières

# lié à des messages qui parlent de "timeout"

# Mais gars aux intervalle tro petit ou trop grand !

#lcp-echo-interval 30

#lcp-echo-failure 4

#connect-delay 5000

idle 1800


# le lien entre xl2tp et pppd s'effectué par un tty

# +crtscts = 100% integrity transfer + Expected latency / Mega high traffic

# -crtscts = CPU at over 99% idle, risk of packet loss

crtscts


# Options pour xl2tpd

# Gestion des échange d'ip locale et au client

#ipcp-accept-local

#ipcp-accept-remote


# options PPP

ms-dns 145.239.143.56

ms-dns 8.8.8.8 # Serveur DNS primaire

ms-dns 8.8.4.4 # Serveur DNS secondaire

mtu 1400

mru 1400

+ipv6

ipv6cp-accept-local

ipv6cp-accept-remote

nodefaultroute

nodefaultroute6

#noreplacedefaultroute

proxyarp # Autorise l'IPsec à fonctionner correctement

####################

# Authentification #

####################

# Si utiliser des secrets locaux (sans RADIUS) :

#require-mschap-v2

#require-mppe-128

#refuse-mschap

#refuse-pap

# MPPE # Les nomppe* n'imposent pas mppe, ni ne refuse si le client demande. # Seul les require-mppe* imposent son utilisation. # On autorise l'usage de MPPE même si l'intérêt est minime, car certains clients l'imposent. #nomppe #nomppe-40 #require-mppe-128 # exige #mppe-stateful #refuse-mppe auth plugin radius.so plugin radattr.so radius-config-file /etc/ppp/radius/radiusclient.conf # Logging

debug

kdebug 32

logfile /var/log/ppp.log

lock

/etc/xl2tpd/xl2tpd.conf

Dernière partie

Gérée en phase2 (ESP)

Attribution des IP aux clients.

Décision de la méthode d'identification

[global]

ipsec saref = yes

[lns default]

ip range = 10.0.0.10-10.0.0.254

local ip = 10.0.0.1

refuse chap = yes

refuse pap = yes

require authentication = yes

name = l2tp ; nom serveur

ppp debug = yes

pppoptfile = /etc/ppp/options.xl2tpd

length bit = yes

Attribut et variables

Cette partie n'est pas importante, elle est utile seulement pour se familiariser avec certains mots-clefs de Radius dans le cas où il faudrait effectuer du débogage.

Radius utilise des mots-clefs servant à stocker les données recueillis du client et des modules pendant toutes les phases d'échanges et de traitements ...

Les tables qui suivent référencent toutes ces données utilisées pour le projet de Tunnel IKEv2 et Ipsec/L2TP.

Donc si on doit débugguer c'est bien de connaitre ces 'attributs'.

Les variables :

  • Cleartext-Password
  • Crypt-Password
  • NT-Password

sont utilisées par les modules d'identifications (mschap, pap, ldap, ...). Elles sont le résultat de leurs recherches pendant la phase authorize. Les données récoltées depuis les annuaires (bases utilisateurs, files, sql, ldap, ...) y sont stockées.

Attribut utilisé dans authorize Modules
Cleartext-Password pap, files
Crypt-Password password
NT-Password ldap

Les attributs :

Les échanges entre le client et le serveur dépendent du protocoles d'identification utilisé. Celon que pap, eap, mschapv2 est utilisé les attributs suivant contiendront les données envoyées par le client concernant l'utilisateur ou des contrôles algorithmique.

Attribut envoyé par client Protocole d'identification
User-Password pap
EAP-Message eap
Message-Authenticator eap
CHAP-Password chap
CHAP-Challenge chap
MS-CHAP-Challenge mschapv2
MS-CHAP2-Response mschapv2

Sécurité

Veuillez appliquer la règle de pare-feu de Pare feu de "Firewall->Restreindre l'usage des tunnels sans authentification système" afin d'éviter des connexions L2TP sans Ipsec.

Version STROKE

Ici se trouve la configuration au format STROKE identique à celle VICI.

Elle est présente uniquement si on a pas le choix ou une super vieille version de strongswan.

/etc/IPsec.conf

config setup

uniqueids=no

charondebug="ike 1, knl 1, cfg 1"


conn %default

# Paramètres généraux

auto=add

type=tunnel

keyexchange=ikev2

fragmentation=yes

forceencaps=yes

dpdaction=clear

dpddelay=300s

dpdtimeout=120s

rekey=no

# Paramètres de sécurité

dpdaction=clear

dpddelay=300s

dpdtimeout=1200s

rekey=no

# Clé de réauthentification

reauth=no

lifetime=24h

margintime=3h

keyingtries=%forever

# IKEv2 + MSCHAPv2 + Radius

conn win10-ikev2

# Paramètres généraux

auto=add

type=tunnel

keyexchange=ikev2

fragmentation=yes

forceencaps=yes


# Configuration serveur

left=%any

leftid=@applireseau.com

leftcert=/etc/letsencrypt/live/applireseau.com/fullchain.pem

leftsendcert=always

# INFO:; leftsubnet -> routes poussées aux clients.

leftsubnet=192.168.0.0/16

leftfirewall=no


# Configuration client

right=%any

rightid=%any

rightauth=eap-radius

rightsourceip=192.168.12.9/24 # CTOK donne IPv4

rightsubnet=%dynamic


# Authentification

leftauth=pubkey

eap_identity=%identity


# Algorithmes cryptographiques (sécurisé et compatible Windows 10)

ike=aes256-sha256-prfsha256-modp1024,aes256gcm16-prfsha384-ecp384,aes256-sha384-modp2048,aes256gcm16-prfsha384-modp1024,aes256-sha256-modp2048!

esp=aes256-sha1-modp2048,aes256gcm16-ecp384,aes256gcm16-modp1024,aes256-sha256-modp2048!


<!> La doc précise que les valeurs de ike et esp, suivante, sont celles configurées par défaut :

      • ike=aes128-aes192-aes256-sha256-sha284-sha512-sha1-aesxcbc-noesn
      • esp=aes128gcm16-aes192gcm16-aes256gcm16-noesn

Si vous avez lu les recommandations, vous savez qu'il faut les changer, ne pas laisser les valeurs par défaut, car pas du tout fiable.

Configuration L2TP/IPsec


conn l2tp

keyexchange=ikev1

authby=secret

type=transport

#rekey=no

#pfs=no


left=192.168.10.5 #%defaultroute # Utilise l'IP publique du client

# Required for original (non-updated) Windows 2000/XP clients.

leftprotoport=17/1701 # UDP (17) port 1701 pour L2TP


leftid=@applireseau.com

leftcert=/etc/letsencrypt/live/applireseau.com/fullchain.pem


right=%any

rightprotoport=17/%any # Le client se connecte à n'importe quel port L2TP


# Pas de PRF en ESP! GCM le gère quand c'est une connexion IKEv1

ike=aes256gcm16-prfsha512-prfsha384-curve25519-ecp521-ecp384-modp4096-modp3072,aes256-sha512-sha384-sha256-ecp521-ecp384-modp4096-modp3072-modp2048!

esp=aes256gcm16-curve25519-ecp521-ecp384-modp4096-modp3072,aes256-sha512-sha384-sha256-ecp521-ecp384-modp4096-modp3072-modp2048-none!


auto=add

forceencaps=yes

dpdaction=clear

dpddelay=30s


keyingtries=3

Partie xl2tpd

Identique à celle du chapitre Strongswan->xl2tp->Identification Radius

Cheminement pour IPsec/L2TP

La configuration reste dans /etc/ppp/radius/, précisée dans les variables :

  • pppoptfile = /etc/ppp/options.xl2tpd
  • radius-config-file /etc/ppp/radius/radiusclient.conf
  • servers /etc/ppp/radius/servers

xl2tpd appel 'pppd' qui appel 'radiusclient'

Table d'appartenances :

Services Fichier Attribution
xl2tpd /etc/xl2tpd/xl2tpd.conf pppoptfile = /etc/ppp/options.xl2tpd
pppd /etc/ppp/options.xl2tpd radius-config-file /etc/ppp/radius/radiusclient.conf
freeradiusclient /etc/ppp/radius/radiusclient.conf servers /etc/ppp/radius/servers

chmod -R 700 /etc/ppp/radius

Termes

IPsec (IKEv1) → Authentification par certificat serveur

L2TP → Authentification utilisateurs via CHAPv2/PAP dans /etc/ppp/chap-secrets

EAP Authentification utilisateur pouvant utiliser plusieurs protocoles.

CHAPv2 utilise le fichier /etc/ppp/chap-secrets pour gérer les identifiants

PAP utilise le fichier /etc/ppp/pap-secrets pour gérer les identifiants

Radius

Certificats

Création de certificats SSL.

https://applireseau.com/glpi/front/ticket.form.php?id=450

Chaque partie doit avoir préchargé les certificats root et de domaine dans /etc/ipsec.d/cacerts/

Root: wget https://letsencrypt.org/certs/isrgrootx1.pem -O /etc/ipsec.d/cacerts/root_letencrypt.pem

<!> Sous windows il est normalement pas nécessaire de l'importer, car il se trouve déjà dans le magasin de l'ordinateur : certlm.msc

magasin de l'utilisateur : certmgr.msc


Certificat applireseau.com : scp -a root@applireseau.com:/etc/letsencrypt/live/applireseau.com/chain.pem /etc/ipsec.d/cacerts/

PSK ou Certificat ?

Avec le couple L2TP/Ipsec l'établissement du tunnel se fait avec un PSK.

L'autre possibilité est d'employer un certificat privé. Seul problème il doit-être installé des deux cotés (client/serveur)


La version L2TP-IPSec avec certificat est abandonnée, car elle demande de mettre à jour les certificats sur tous les postes présent et nouveaux. De plus l'ajout du certificat privé ou public dans "certlm.exe" (local) ou certmgr.exe" (user) n'a pas permit de se connecter. Le client et serveur ne s'échange pas le bon certificat malgré le bon CN des deux cotés ; il est possible que le certificat Let'encrypt ne permette pas l'usage en vpn de ce certificat.


Option strongswan.conf / charon.conf

Liste des options pour ike= et esp= disponible à la section : Authenticated Encryption (AEAD) Algorithms

Autre VPN

Nostr VPN non centralisé et avec principe de P2P

Conversion à swanctl.conf

Quelques exemples de concordances entre strongswan.conf et swanctl.conf.

Tuto du passage à swanctl.conf

  • systemctl stop strongswan-starter
  • systemctl disable strongswan-starter

supprimer tous :

  • les conn dans ipsec.conf
  • les pools dans strongswan.conf

AUDIT

Trafic du tunnel

Dans la section connections.ikev2.remote.children.ikev2 de swanctl.conf

Ajouter

mark_in = 0x20 # ou toute autre valeur

mark_out = 0x20 # ou toute autre valeur

Avec nft / iptables

# Ajoute une règle pour logger les paquets marqués 0x20 (dans la table mangle, par exemple)

sudo iptables -t mangle -A PREROUTING -s 192.168.12.0/24 -m mark --mark 0x20 -j NFLOG --nflog-group 5 --nflog-prefix "MARK20-IN "

sudo iptables -t mangle -A POSTROUTING -s 192.168.12.0/24 -m mark --mark 0x20 -j NFLOG --nflog-group 5 --nflog-prefix "MARK20-OUT "

# Ou avec nftables (recommandé aujourd’hui)

sudo nft add rule mangle prerouting saddr meta mark 0x20 nf log group 5 prefix "MARK20-IN "

sudo nft add rule mangle postrouting meta mark 0x20 nf log group 5 prefix "MARK20-OUT "

Marquer le trafic d'un client

NFTables

  • sudo nft add rule mangle prerouting saddr 192.168.12.0/24 meta mark 0x20 nf log group 5 prefix "MARK20-IN "
  • sudo nft add rule mangle postrouting saddr 192.168.12.0/24 meta mark 0x20 nf log group 5 prefix "MARK20-OUT "

iptables

  • sudo iptables -t mangle -A PREROUTING -s 192.168.12.0/24 -m mark --mark 0x21 -j NFLOG --nflog-group 5 --nflog-prefix "MARK20-IN "
  • sudo iptables -t mangle -A POSTROUTING -s 192.168.12.0/24 -m mark --mark 0x21 -j NFLOG --nflog-group 5 --nflog-prefix "MARK20-OUT "

Suivre le trafic

  • tcpdump -i nflog:5 -n

'files, 'pap' pas si claire

Dans tout le document il est fait mention de "mot de passe en claire" avec l'usage des modules 'files' et 'pap' et de ne pas s'en servir... Ceci afin de sensibiliser l'administrateur des risques d'une tel méthode et surtout le décourager de stocker des mot de passe dans un fichier texte.

Cependant il est possible de stocker des mots de passe cryptés avec les méthodes de chiffrement sha-512 ou yescrypt.

La syntaxe diverge légèrement puisqu'il faut juste utiliser la variable dédiée aux mots de passes qui utilisent ces cryptages. Ici c'est "Crypt-Password". Ex :

salty Crypt-Password := "$y$......" saltysha Crypt-Password := "$6$......"

Pour obtenir une version cryptée on peut appliquer différente méthodes :

Récupération de mot de pass sans le stocker dans l'history :

  • MDP=$(cat -)

Crypter en SSH-512

  • openssl passwd -6 "$MDP"
  • mkpasswd -m sha-512 "$MDP"

Crypter avec yescrypt

  • mkpasswd -m yescrypt "$MDP"

Termes

Résumé par DS :


Strongswan (5.9.13) : Implémentation IKE/IPsec pour Linux. Gère les tunnels chiffrés et l'authentification client-serveur en mode natif IPsec ou L2TP.


IPsec (inclus dans strongswan) : Suite protocole chiffrant tout trafic IP au niveau réseau. Assure confidentialité, intégrité et authentification entre deux hôtes ou réseaux.


xl2tpd (1.3.18) : Daemon L2TP qui transporte les trames PPP sur IP. Crée le tunnel de données utilisateur après l'établissement du tunnel IPsec de contrôle.


pppd (2.4.9) : Daemon PPP qui gère l'authentification (PAP/CHAP/MS-CHAP), l'attribution d'adresses IP et l'encapsulation point à point sur xl2tpd.


FreeRADIUS (3.2.5) : Serveur AAA centralisé (Authentification, Autorisation, Comptabilité) pour PPP, 802.1X ou VPN. Valide les identifiants et applique les politiques réseau.