J’ai voulu faire passer tout mon trafic Internet (entrant et sortant) par un VPN.
Pour avoir de l’IPv6 (mon FAI ne me fournit que de l’IPv4), pour passer par un FAI favorable à la neutralité du net, et pour pouvoir changer de mode d’accès à Internet sans impact sur mon auto-hébergement (typiquement, utiliser le WiFi d’un voisin ou d’un téléphone 4G, si ma box est en panne, sans changer d’adresses IP).
Il est probable que tout ce qui suit soit aussi applicable à n’importe quel appareil basé sur OpenWRT.
Je me suis abonné à une offre VPN chez un FAI associatif local : Illyse, que je souhaite utiliser par-dessus l’accès internet fibre de mon FAI.
Protocole OpenVPN
J’ai commencé avec OpenVPN puisque c’est un protocole stable et très bien intégré dans les interfaces graphiques de Turris. J’ai documenté la manière dont je l’ai fait sur https://doc.illyse.net/projects/publicdocs/wiki/Vpn_doc_user#Turris-OS-ou-OpenWRT.
Par contre, le protocole OpenVPN est gourmand en ressources : je n’arrive à obtenir qu’environ 30 à 40 Mbps (en download et en upload). Le Turris Mox ne permet pas de faire mieux. Et, même si l’appareil était plus puissant, je finirais par être limité par les ressources du serveur OpenVPN d’Illyse que j’appelle (maximum autour de 140Mbps d’après un test rapide).
Donc, sur les conseils d’Illyse, j’ai laissé tombé OpenVPN, pour passer plutôt sur Wireguard.
Protocole Wireguard
Il est bien plus rapide, même si on reste limité par la puissance du CPU du routeur : sur mon Turris Mox, j’obtiens environ 220Mbps en download et 180Mbps en upload.
C’est un peu moins bien intégré dans les interfaces graphiques de Turris : ce n’est pas dans reForis, mais existe dans LuCI.
Configuration avec LuCI
Il faut d’abord installer le package luci-app-wireguard, puis rebooter le routeur.
Ensuite générer un couple clé privée / clé publique (soit en se connectant en SSH sur le Turris, soit sur un autre appareil comme un PC qui aurait le package wireguard-tools) :
wg genkey | tee wgclient.key | wg pubkey > wgclient.pub
Cela génère deux fichiers :
- wgclient.key, qui contient la clé privée
- wgclient.pub, qui contient la clé publique, et qu’il faut envoyer à votre fournisseur de VPN Wireguard, pour qu’il configure leur serveur avec
Dans l’IHM LuCI, créer une nouvelle interface de type « Wireguard VPN », en utilisant les infos de https://faq.illyse.net/VPN/wireguard/ et/ou celles spécifiques à votre VPN :
- Clé privée : celle que vous avez générée (contenu du fichier wgclient.key)
- Adresses IP : il faut y mettre 2 adresses IP : l’IPv4 et l’IPv6 qui vous sont attribuées par le fournisseur de VPN. Chez Illyse, ça se trouve dans votre compte, sur https://coin.illyse.org
- MTU : mettre la valeur fournie (actuellement 1400 chez Illyse)
- Zone du pare-feu : wan
- Description et hôte du point terminal : nom d’hôte du serveur VPN (vpn-wg.illyse.org chez Illyse)
- Clé publique : la clé publique du serveur donnée par le fournisseur de VPN. Attention, il ne s’agit pas du contenu de wgclient.pub
- IP autorisées : pour simplifier, on peut lui dire d’accepter toutes les adresses IP, en renseignant 2 valeurs : 0.0.0.0/0 (pour les adresses IPv4) et ::/0 (pout les adresses IPv6)
- Route IP autorisées : cocher la case si vous voulez que le trafic soit par défaut routé dans le VPN (c’est en général ce qu’on veut)
- Port du point de terminal : celui sur lequel se connecter sur le serveur VPN (443 chez Illyse)
- Laisser toutes les autres valeurs par défaut
Une fois l’interface créée, vous pouvez cliquer sur « Enregistrer et appliquer » dans la liste des interfaces, puis vérifier que le VPN se connecte dans le menu « Etat de wireguard » (sous « Etat »).
Si votre fournisseur de VPN vous propose un sous-réseau IPv6 (c’est le cas chez Illyse), il faut le renseigner dans le champ « préfixe ULA », dans l’onglet « Options globales de réseau » de l’écran des interfaces. Après application, les prochaines machines connectées en DHCP au réseau local se verront attribuer une adresse IPv6 dans ce sous-réseau (pour les machines déjà allumées, un redémarrage du réseau ou un reboot sera nécessaire)
Fichiers de configuration UCI correspondant
La configuration du paragraphe ci-dessus se traduit par des sections dans les fichiers /etc/config/network et /etc/config/firewall.
Voici un extrait de fichier /etc/config/network qui correspond :
config interface 'illyse_wg'
option proto 'wireguard'
option private_key 'xxxxxxxxxxxxxxxxxxxxxxxxx'
list addresses 'xxx.xxx.xxx.xxx/32'
list addresses 'xxxx:xxxx:xxxx:xxxx::x/128'
option mtu '1400'
config wireguard_illyse_wg
option description 'vpn-wg.illyse.org'
option endpoint_host 'vpn-wg.illyse.org'
option public_key 'V4jKEBhgAWeIneh4eJTLIus4XekmV3qfAifs6Ha5YjI='
option route_allowed_ips '1'
list allowed_ips '0.0.0.0/0'
list allowed_ips '::/0'
option endpoint_port '443'
config globals 'globals'
option ula_prefix 'xxxx:xxxx:xxxx:xxxx::/56'
Et un extrait de /etc/config/firewall :
config zone
option name 'wan'
(...)
list network 'wan'
list network 'wan6'
list network 'illyse_wg'
Si vous modifiez ces fichiers à la main, il faut ensuite redémarrer les services correspondant pour que les changements soient pris en compte :
service network restart
service firewall restart
Configuration avec Ansible
Comme je le disais dans un article précédent, on peut facilement générer les fichiers de configuration avec Ansible.
Voici un extrait de playbook Ansible qui correspond aux exemples ci-dessus :
- name: Configure Wireguard client 1
uci:
command: section
config: network
type: interface
name: illyse_wg
value:
proto: 'wireguard'
private_key: 'xxxxxxxxxxxxxxxxxxxxxxxxx'
addresses: ['xxx.xxx.xxx.xxx/32','xxxx:xxxx:xxxx:xxxx::x/128']
mtu: '1400'
notify: uci commit
- name: Configure Wireguard client 2
uci:
command: section
config: network
type: wireguard_illyse_wg
find_by:
description: 'vpn-wg.illyse.org'
value:
endpoint_host: 'vpn-wg.illyse.org'
public_key: 'V4jKEBhgAWeIneh4eJTLIus4XekmV3qfAifs6Ha5YjI='
route_allowed_ips: '1'
allowed_ips: ['0.0.0.0/0','::/0']
endpoint_port: '443'
notify: uci commit
- name: Configure IPv6 addresses on the local network
uci:
command: section
config: network
type: globals
name: globals
value:
ula_prefix: 'xxxx:xxxx:xxxx:xxxx::/56'
notify: uci commit
- name: Configure Wireguard interface in wan zone
uci:
command: section
config: firewall
type: zone
find_by:
name: 'wan'
value:
network: 'wan wan6 illyse_wg'
notify: uci commit
handlers:
- name: uci commit
uci:
command: commit
Possibilité de bypasser ponctuellement le VPN
Si tout le trafic sortant passe par le VPN, on peut avoir besoin de temps en temps de l’éviter. Pour avoir toute la bande passante disponible par exemple, ou simplement pour diagnostiquer un éventuel problème.
Puisque c’est pour du ponctuel, mon objectif était de permettre ça par un simple changement d’adresse IP de la machine sur laquelle on a le besoin.
J’ai fini par trouver une manière relativement simple de faire ça, avec une « VPN Routing Policy ».
Il faut d’abord installer le package vpn-routing-policy (via l’interface web, ou en ligne de commande opkg).
Ensuite, un nouveau menu « VPN Routing Policy » apparaît dans LuCI : il faut y ajouter une « Stratégie » :
- Nom : comme vous voulez, j’ai choisi « direct_connection »
- Adresses locales / appareils : l’IP ou la plage d’IP concernée. J’ai mis par exemple 192.168.1.50
- Interface : WAN
Ensuite on peut cliquer sur « Enregistrer et appliquer », puis (en haut) activer et démarrer le service.
Sur l’appareil du réseau local concerné, il suffit ensuite de définir l’adresse IP statique 192.168.1.50 (au lieu d’utiliser le DHCP). C’est facile à faire sur les appareils Linux qui utilisent Network Manager (il suffit de créer un nouveau profil de connexion filaire avec cette IPv4, un sous-réseau 255.255.255.0 et une passerelle 192.168.1.1). Ça devrait fonctionner aussi sur n’importe quel autre système d’exploitation.
Ainsi, en basculant d’un profil de connexion à un autre sur l’appareil, on peut choisir d’utiliser le VPN ou non.
Dans le profil de connexion créé, je conseille de spécifier de désactiver l’IPv6. Si ce n’est pas fait, la machine conserverait l’IPv6 (routable) du VPN, alors que le flux IPv4 ne passerait plus par le VPN. On se retrouverait dans ce cas dans une situation bancale à éviter.
Extrait du fichier /etc/config/vpn-routing-policy correspondant à mon exemple :
config policy
option name 'direct_connection'
option src_addr '192.168.1.50'
option interface 'wan'
qui peut être généré via Ansible :
- name: Configure routing without Wireguard for some specific static IPs
uci:
command: section
config: vpn-policy-routing
type: policy
find_by:
name: 'direct_connection'
value:
src_addr: 192.168.1.50
interface: wan
notify: uci commit
- name: Activate vpn-policy-routing service
service:
name: vpn-policy-routing
state: started
enabled: yes
Désactivation complète du VPN
Si on veut que tout le trafic sortant ne passe plus par le VPN (sans le déconfigurer complètement), une solution est d’ajouter une autre règle de « VPN Routing Policy », qui matche toutes les adresses IPv4 locales (ex : 192.168.1.0/24), et qui sort sur l’interface WAN. Ca suffit pour l’IPv4.
Pour l’IPv6, il faut supprimer le préfixe ULA IPv6 dans l’onglet « options globales de réseau » de la page des interfaces réseau, puis reconfigurer l’interface réseau de chaque appareil du réseau local (pour qu’il ne considère plus avoir une IPv6). Sur les appareils basés sur systemd, il suffit de faire « sudo systemctl restart systemd-networkd ».
Il est aussi possible de faire dépendre le préfixe IPv6 routé directement de l’interface wireguard, avec « ip6prefix ».
L’option ne semble pas présente dans LuCI, mais dans les fichiers de conf c’est pris en compte.
Ainsi si on désactive temporairement l’interface wireguard, le préfixe v6 est aussi retiré sans besoin d’action supplémentaire.
config interface ‘illyse_wg’
[…]
list addresses ‘xxx.xxx.xxx.xxx/32’
list addresses ‘xxxx:xxxx:xxxx:xxxx ::x/128’
list ip6prefix ‘2a0x:xxxx:xxxx:xxxx::/56’