Afficher/cacher Sommaire
OpenVPN Grifon 2017-01-22T11.52.04
OpenVPN
Pour la faire simple, c’est globalement le bordel. On a commencé à fournir des VPNs alors que l’on avait pas encore de plan d’adressage, du coup on a des /32 hors du /27 de VPN qui se baladent. C’est pour cela que l’on a de l’[[reseau:bgp:ibgp|iBGP]] vers [[machines:grifon:nominoe]].
Nous remarquerons que ça ne dérange pas du tout OpenVPN d’avoir des IPs en dehors de son /27.
Configuration serveur
J’ai impunément piqué l’idée d’ARN de factoriser les confs, c’est quand même vachement plus pratique quand je dois faire des modifications. Ainsi, on a trois fichier : common.ovpn qui contient la conf en commun, tcp.conf pour la partie TCP et upd.conf pour la partie UDP.
common.ovpn
# Serveur
mode server
port 1194
tun-ipv6
local 89.234.186.3 # Adresse d'écoute pour les connexions entrantes
# Contournement des soucis de fragmentation
mssfix 1300
# On utilise la meilleure méthode de chiffrement
cipher aes-256-cbc
# Certificats
ca /etc/ssl/grifon/vpn.grifon.fr.CA-OPENVPN.crt
cert /etc/ssl/grifon/vpn.grifon.fr.OPENVPN.crt
key /etc/ssl/grifon/vpn.grifon.fr.OPENVPN.key
dh dh4096.pem
# Clé partagée (0 pour serveur, 1 pour client ; oui, même fichier côté client
# et côté serveur)
tls-auth ta.key 0
# Réseau
push "dhcp-option DNS 89.234.186.1" # Serveur DNS
push "dhcp-option DNS 2a00:5884::1" # Serveur DNS
keepalive 10 120
# Scripts pour ajouter les bonnes routes sur judicael
client-connect /etc/openvpn/client-connect # Utilisé pour IPv4
client-disconnect /etc/openvpn/client-disconnect # Utilisé pour IPv4
#
# server implique push topology et tls-server
#
topology subnet
server 89.234.186.64 255.255.255.224
push "explicit-exit-notify" # Pour pas que le serveur attende un timeout
# Configuration IPv6
push "tun-ipv6"
ifconfig-ipv6 2a00:5884::4/64 2a00:5884::4
push "route-ipv6 2a00:5884:8300::4/64 2a00:5884::4"
# Securité
user openvpn # Le serveur ne tourne pas en tant que root
group openvpn
persist-key
persist-tun
comp-lzo # On compresse
client-config-dir /etc/openvpn/ccd # Chaque client a ses IP spécifiées ici
# Auth
auth-user-pass-verify "/etc/openvpn/auth.pl /etc/openvpn/passwd" via-env
script-security 3
client-cert-not-required
username-as-common-name
ccd-exclusive # Si le client n'a pas de fichier dans /etc/openvpn/ccd, on refuse la connexion
# Log
verb 3
mute 20
status /etc/openvpn/openvpn-status.log # Liste des clients connectés
#log-append /var/log/openvpn.log # Logs
# routage
up "/etc/openvpn/up.sh"
tcp.conf
# COMMON CONFIGURATION
config /etc/openvpn/common.ovpn
proto tcp-server
dev tun-tcp0
daemon ovpn-server-tcp
learn-address /etc/openvpn/setup-address-tcp.sh # Utilisé pour IPv6
udp.conf
# COMMON CONFIGURATION
config /etc/openvpn/common.ovpn
proto udp
dev tun-udp0
daemon ovpn-server-udp
learn-address /etc/openvpn/setup-address.sh # Utilisé pour IPv6
fragment 1300
Fichiers maisons utilisés par OpenVPN
Tous les fichiers qui suivent doivent être exécutables.
auth.pl
Ce fichier nécessite ‘‘libapache-htpasswd-perl’’ sous Debian ou ‘‘dev-perl/Authen-Htpasswd’’ sous gentoo.
Son but est de vérifier le mot de passer envoyé par le client par rapport au contenu de ‘‘/etc/openvpn/passwd’’.
#!/usr/bin/env perl
use Apache::Htpasswd;
my $username = $ENV{'username'};
my $password = $ENV{'password'};
if ($username eq "") { print 'Empty username'; exit(1); }
# Get password file
my $filename = $ARGV[0];
if (! -e $filename) { print 'File doesn\'t exist.'; exit(1); }
# Check username/password
$file = new Apache::Htpasswd({passwdFile => $filename, ReadOnly => 1});
if ($file->htCheckPassword($username, $password) eq 1) { exit(0); }
# User not found
print 'User not found.'; exit(1);
client-connect
Ce fichier ajoute la route /32 pour les clients en dehors du /27 du plan d’adressage
#!/bin/sh
set -e
[ -z "$ifconfig_pool_remote_ip" ] || sudo /bin/ip route add $ifconfig_pool_remote_ip/32 dev $dev proto static
client-disconnect
Comme avant sauf que l’on enlève la route (en même temps, vu le nom du fichier…)
#!/bin/sh
set -e
[ -z "$ifconfig_pool_remote_ip" ] || sudo /bin/ip route del $ifconfig_pool_remote_ip/32 dev $dev proto static || true
setup-address.sh
Là c’est la version du future (donc IPv6), qui fait les deux en même temps.
#!/bin/bash
action="$1"
addr="$2"
grep -qE "^2a00:.*" <<< "$addr"
if [ $? -eq 0 ]
then
case "$action" in
add )
sudo /bin/ip route add $addr dev tun0 proto static metric 1024
;;
delete)
sudo /bin/ip route del $addr dev tun0 proto static metric 1024 || true
;;
esac
fi
Redirection des ports
Pour que le VPN puisse être joint depuis tous les ports, nous devons les rediriger vers le 1194. En effet, OpenVPN ne sait pas écouter sur plusieurs ports, et ce serait un peu lourd d’avoir un processus par port. Nous utilisons pour cela le module NAT d’iptables.
Nous avons aussi un daemon L2TP et IPsec qui tourne, nous ne voulons pas rediriger le trafic à destination de ces ports OpenVPN, donc nous mettons juste un -j ACCEPT avant la règle de NAT. Absolument tous les ports TCP sont redirigés, il n’est donc pas possible de se connecter en SSH au serveur VPN en IPv4.
iptables -t nat -A PREROUTING -d 89.234.186.3/32 -p udp -m udp --dport 500 -j ACCEPT
iptables -t nat -A PREROUTING -d 89.234.186.3/32 -p udp -m udp --dport 1701 -j ACCEPT
iptables -t nat -A PREROUTING -d 89.234.186.3/32 -p udp -m udp --dport 4500 -j ACCEPT
iptables -t nat -A PREROUTING -d 89.234.186.3/32 -p udp -m udp --dport 1:65535 -j DNAT --to-destination 89.234.186.3:1194
iptables -t nat -A PREROUTING -d 89.234.186.3/32 -p tcp -m tcp --dport 1:65535 -j DNAT --to-destination 89.234.186.3:1194
Gestion des logs
Par défaut, openvpn écrit ses logs dans ‘‘/var/log/daemons.log’’. Nous voulons un fichier séparé car ils sont très vite très gros avec tous les bots qui tentent de se connecter au VPN en TCP en croyant tomber sur un serveur mail/web/whateverd. J’ai donc écrit un fichier de conf rsyslog :
if $programname startswith 'ovpn-server-' then {
-/var/log/openvpn.log
}
Configuration client
Mot de passe
Si un client veut un mot de passe particulier, il peut donner la sortie de htpasswd -n $username
Fichier de conf client
Je ne copie pas ici la clé partagée (ta.key) parce que ça n’aurait aucun sens. Elle est envoyée à l’adhérent lors de la création de son compte.
# OpenVPN chez Grifon
# Informations de connexion
client
dev tun
proto udp
#proto tcp-client
port 1194
remote 89.234.186.3 1194
remote-random
resolv-retry infinite
remote-cert-tls server
route-delay 2
nobind
persist-key
# Configuration pour contourner les soucis de fragmentation
fragment 1300
mssfix 1300
# Chiffrement le plus élevé
cipher aes-256-cbc
# Clé partagée (à ne pas distribuer)
tls-auth ta.key 1
comp-lzo
redirect-gateway def1 bypass-dhcp # À commenter pour ne pas utiliser le VPN comme connexion IPv4 par défaut
route-ipv6 2000::/3 # À commenter pour ne pas utiliser le VPN comme connexion IPv6 par défaut
# Auth
auth-user-pass
# CA
<ca>
-----BEGIN CERTIFICATE-----
MIIGdDCCBFygAwIBAgIJAKk3963Ys0HlMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
VQQGEwJGUjERMA8GA1UECBMIQnJldGFnbmUxFzAVBgNVBAcTDkNlc3NvbiBTZXZp
Z25lMQ8wDQYDVQQKEwZHUklGT04xDDAKBgNVBAsTA1ZQTjEWMBQGA1UEAxMNdnBu
LmdyaWZvbi5mcjEQMA4GA1UEKRMHT3BlblZQTjAeFw0xNTExMDkyMDA0MzFaFw0y
NTExMDYyMDA0MzFaMIGCMQswCQYDVQQGEwJGUjERMA8GA1UECBMIQnJldGFnbmUx
FzAVBgNVBAcTDkNlc3NvbiBTZXZpZ25lMQ8wDQYDVQQKEwZHUklGT04xDDAKBgNV
BAsTA1ZQTjEWMBQGA1UEAxMNdnBuLmdyaWZvbi5mcjEQMA4GA1UEKRMHT3BlblZQ
TjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKl+DCOmB7u/mphT9Pbj
91F5KviclWxw1gT1GglbHizfNFomJ9i4xBWO7hBP7x+HtgAnOb9/KSjFRADq9gMo
ay+NULkMH/+sDr8AdNGOD1wZU0bpkmqGWRgLZpTHc9uMP0RTmpFFYecFAPJeY6U2
uRuIPZSkbYRZxnlSbKMidV/w4e1PVv30hpr0x7Y6Ded3lr+RUbWYpSGeNn89bM8y
xZjUCxPaX73mKfLg4gaXVwKOn/50KESKhaE/BHdkKIE9WKpL48ireIYf4TFQuWTs
FQW3KNlGc10Wql6FE+uxoeK7vv3/Hnf6bYW/IrCj3Fv82ZVBSja6Zrhul4g6PeHN
Vx6ccnj3ZoofIw3j3UauX14iABIjo5GWAI79TbDR+JzKSp6fnV0P3wJevg3WXr3B
5bpUmnC2B88GS1irKk7DgA6lIqu+GNck1RHsJf6+heVvGdXFvyFb27OKEA3E/A9O
/IXCDykmPdXe0m89dcGMDbQPRm6xNdZB7zd22XqHsDjQxVbocFgVhdrIVBU4e60G
vJteANqKPf8ZcjWOdVnJ6cNtJPXy4n9aYQBZuQLZ+PvLFgWiGv8S+mSQdaaD09yq
GBSUAZrJhRcRzNuwjo6QZwmiFBsjb15PRRbU7W52r6LZCBzuanPqilRyVpQOp6bE
I4bQ6VY3CdEdGBvJTmqqx/NBAgMBAAGjgeowgecwHQYDVR0OBBYEFFcYN1/t1Ad2
JBC13HUULwzxx6xmMIG3BgNVHSMEga8wgayAFFcYN1/t1Ad2JBC13HUULwzxx6xm
oYGIpIGFMIGCMQswCQYDVQQGEwJGUjERMA8GA1UECBMIQnJldGFnbmUxFzAVBgNV
BAcTDkNlc3NvbiBTZXZpZ25lMQ8wDQYDVQQKEwZHUklGT04xDDAKBgNVBAsTA1ZQ
TjEWMBQGA1UEAxMNdnBuLmdyaWZvbi5mcjEQMA4GA1UEKRMHT3BlblZQToIJAKk3
963Ys0HlMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBACKBlt74LoNg
+PC1hvvTofrOtaVZVN4qyp7JRVQB3FNvFYWaFtYikIVRu+GM/7PmsECh5c2ZSU2J
U5w9sERzn3lh4ixTwArcJyt2rqIVKoX9lCiLcrCin1G/w6t+mXKIbKdrihG2bYYK
dCKmC0Ua5r8yfdhjvgIWeJ2t6UI+31SWeZSxY5O7t6DTtaABx21KuCAEgxsAjNyk
Q94KKWP2dqwGDCtCf4cBnSszzV/k0wy8JUgRCu1ybAj2H5n6O6JLbLY3/DE2cq4T
wiWwq2w0gE8d2aEhqLAM4Dnl8hj8hJzaCj1zbda+DzrdBJJTwk8dX51gXxVAfgw9
3keZeI7UKEpCbb3hIeVK3r5E1DsVvgE6yfSzlfGBlY1nyA0G8/Q6+2k3WJjdY5lm
cZ3LerCNeXZfVELpwlMdj0q+/m2HnZKxIqKScEjZSwxt+go9sdvoz2EZVjtp3iB8
YziO3VvnrrOsKBy8RLAKXpm+x5CP4uX48Qv1sqDaEvSZzuh704QJMfUekoeDHR3L
M3mqrq2nDUJuKwtOb1pGJgDkMeKSj7IZNQQgVSDx2F/frDArhyEv+b/+VLnd9IUp
QK/w37xqNHPIj02Mrr9D2cHcKRLnubd1YuWcazNqvnSKXXeJoNvpj9L6pYtWoHMg
2kSONme/cdZptUNl2KZzs+xYBeyUPSRE
-----END CERTIFICATE-----
</ca>
Particularité pour les clients hors du /27
OpenVPN ajoute les routes IPv4 ‘‘0.0.0.0/1 via 89.234.186.65 dev tun0’’ et ‘‘128.0.0.0/1 via 89.234.186.65 dev tun0’’, sauf que dans le cas du /32, 89.234.186.65 n’est pas directement joignable. Il faut donc ruser avec un up.sh :
#!/bin/sh
dev=$1
ip route add 89.234.186.65/32 dev $dev
Ajouter un VPN
alarig@judicael:~$ ovpn-add -h
Usage:
-h, --help Affiche ce message d’aide
-u, --user Identifiant de connexion au VPN
-i, --id Numéro servant à la génération des IPs
-m, --email Adresse mail à qui envoyer les informations de connexion
Exemple :
ovpn-add -u toto -i 42 -m toto@super.bzh
Ce qui configurera les adresses ip:
- 89.234.186.42
- 2a00:5884:8342::/48
Si vous êtes curieux, voici le script :
#!/bin/sh
usage() {
printf "Usage:\n"
printf "\t-h, --help Affiche ce message d’aide\n"
printf "\t-u, --user Identifiant de connexion au VPN\n"
printf "\t-i, --id Numéro servant à la génération des IPs\n"
printf "\t-m, --email Adresse mail à qui envoyer les informations de
connexion\n"
}
OPTS=$(getopt -o u:,i:,m:,h -l user:,id:,email:,help -- "$@")
if [ $? != 0 ]; then
exit 1
fi
if [ $1 ]; then
if [ $1 = '-h' ] || [ $1 = '--help' ]; then
usage
exit 0
elif [ $# -lt 6 ]; then
echo "Paramètre manquant"
usage
exit 1
fi
else
echo "Paramètre manquant"
usage
exit 1
fi
eval set -- "$OPTS"
while :; do
case "$1" in
-h | --help) usage;
exit 0;;
-u | --user) user="$2";
shift 2;;
-m | --email) EMAIL="$2";
shift 2;;
-i | --id) IPid="$2";
shift 2;;
--) shift; break;;
esac
done
mailregex=$(echo $EMAIL | egrep '[^.]+@[^.]+\.[^.]+')
if [ ${#mailregex} != ${#EMAIL} ]; then
echo "Adresse mail invalide"
exit 1
fi
ipv6="2a00:5884:$((8300+$IPid))"
ipv4="89.234.186.$IPid"
password="$(head -c 12 /dev/urandom | base64)"
echo "1 - Génération du mot de passe" >&2
htpasswd -nb $user $password | grep -v "^$" >> /etc/openvpn/passwd
echo "2 - Génération de la configuration" >&2
echo "# IPv4
ifconfig-push $ipv4 255.255.255.224
# IPv6
ifconfig-ipv6-push $ipv6::1/112
iroute-ipv6 $ipv6::/48
route-ipv6 $ipv6::/48 $ipv6::1" > /etc/openvpn/ccd/$user
echo "3 - Envoi du mail" >&2
SUBJECT=$(perl -wse "use utf8; use Encode qw(encode); print encode(\"MIME-Q\",\
\"Votre VPN vient d’être créé\");")
echo "From: Adminsys grifon <adminsys@grifon.fr>
To: $EMAIL
Content-Type: text/plain; charset=UTF-8
Subject: $SUBJECT
Bonjour,
Votre VPN vient d’être créé.
Vous avez l’IPv4 $ipv4 et le subnet IPv6 $ipv6::/48.
Votre identifiant est $user et votre mot de passe est $password
Si vous souhaitez utiliser un mot de passe que nous ne connaissons pas, vous
pouvez nous envoyer la sortie de 'htpasswd -n $user'.
Vous trouverez ci-dessous un exemple de configuration côté client ainsi que la
clé pré-partagée
##### DÉBUT DU FICHIER DE CONFIGURATION #####
$(cat /etc/openvpn/client.conf.template)
##### FIN DU FICHIER DE CONFIGURATION #####
##### DÉBUT DE LA CLÉ PRÉ-PARTAGÉE #####
$(cat /etc/openvpn/ta.key)
##### FIN DE LA CLÉ-PARTAGÉE #####
Cette clé partagée est là pour éviter les attaques par force brute, merci de ne
pas la diffuser.
Cordialement,
--
Les adminsys de grifon" | /usr/sbin/sendmail -f adminsys@grifon.fr -t
SUBJECT=$(perl -wse "use utf8; use Encode qw(encode); print encode(\"MIME-Q\",\
\"Création du VPN de $user\");")
echo "From: Adminsys grifon <adminsys@grifon.fr>
To: adminsys@grifon.fr
Content-Type: text/plain; charset=UTF-8
Subject: $SUBJECT
IPv4 : $ipv4
IPv6 : $ipv6::/48
" | /usr/sbin/sendmail -f adminsys@grifon.fr -t