Client VPN Wireguard avec un routeur Turris

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 ».

Une réflexion sur « Client VPN Wireguard avec un routeur Turris »

  1. 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’

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *