IPSec
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.
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> /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
|
| updown | Lancement du script qui attribut qui place le tunnel dans une table dédiée à IPSEC.
|
| 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.
- 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"
- nft add rule inet filter forward iifname "${IFACE}" ip protocol udp udp dport @IPSec_udp counter accept
- 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
- IPv6
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.
