Un seul hôte public pour le VPN et le web : comment répartir les rôles
Une seule IP publique peut terminer des tunnels, servir HTTPS et atteindre deux réseaux locaux privés. Décidez d’abord qui possède l’adresse, chaque port et la politique de transfert.
Une seule machine peut répondre aux trois besoins à la fois : terminer des tunnels, répondre en HTTPS et transférer entre deux réseaux locaux privés. Savoir si c’est raisonnable se ramène à trois points que vous pouvez régler sur papier : qui possède l’adresse publique, qui possède chaque couple de port et de protocole, et quel processus est autorisé à transférer des paquets. Si ces points sont bons, l’hôte partagé n’a rien de remarquable. S’ils sont faux, vous passerez un week-end sur un service qui démarre proprement et ne répond jamais.
Ce qui suit est une procédure de décision, pas une fiche de construction. Chaque étape se termine par la vérification qui prouve que le rôle que vous venez d’ajouter est bien isolé.
Choisissez le propriétaire de l’adresse avant les ports
Un point de terminaison de tunnel et un serveur web peuvent partager un noyau ; partager une adresse, un port et un protocole en même temps est ce qui échoue. WireGuard prend généralement UDP 51820, OpenVPN prend UDP 1194 ou TCP 443, et un serveur web prend TCP 443. Le couple qui fait mal, c’est OpenVPN sur TCP 443 à côté de HTTPS, parce que les deux veulent la même socket et le noyau la donne à celui qui s’est lié en premier. Seul un démultiplexeur en amont, comme sslh ou un proxy conscient de TLS, les laisse partager ce port, et il ajoute un composant dont la panne ressemble exactement à un problème de pare-feu.
Regardez les propriétaires avant de changer quoi que ce soit : ss -lntup affiche l’adresse locale, le port et le processus de chaque socket en écoute. Deux lignes montrant 0.0.0.0:443 signifient que le second service ne s’est jamais lié, aussi joyeux fût son script init. Le pontage déplace aussi le propriétaire. Quand eth0 rejoint br0, l’IP passe à br0 et chaque règle de pare-feu nommant eth0 cesse de correspondre, donc liez les services sur le pont et confirmez avec ip -br addr.
La même règle de propriété explique une surprise qui apparaît avec les machines virtuelles. Un serveur de tunnel qui tourne dans un invité du même réseau local garde l’adresse de l’invité, donc les connexions visant l’adresse de l’hôte restent sur l’hôte et le tunnel de l’invité ne les voit jamais, quoi qu’en dise le profil client.
Routez entre les deux réseaux locaux ou faites du NAT d’un côté
Deux réseaux locaux qui ne se voient pas peuvent chacun joindre l’hôte public, qui transfère ensuite entre les tunnels. Cette conception routée exige trois choses en place : le transfert activé, une route vers chaque préfixe distant et une politique de transfert qui laisse passer le transit. sysctl -w net.ipv4.ip_forward=1 couvre la première, ip route add 10.20.0.0/24 dev wg1 la deuxième, et une ligne nftables comme nft add rule inet filter forward iifname "wg0" oifname "wg1" accept la troisième.
Le NAT source est plus facile à ajouter et plus difficile à déboguer. Le masquage réécrit l’adresse du client, donc le côté distant voit le concentrateur plutôt que l’hôte réel, et ses règles d’accès et ses journaux cessent d’être utiles pour l’attribution. Quand les deux réseaux sont à vous, routez. Quand un côté appartient à un tiers qui n’ajoutera pas de route de retour, le NAT est l’option qui part cette semaine. Dans tous les cas, écrivez le plan d’adressage, car deux /24 qui se chevauchent ne peuvent être routés par aucune configuration.
Rien dans le fait de servir de sortie Internet à un portable n’empêche la même machine de terminer des tunnels entrants. Seules les adresses qui se chevauchent l’empêchent, et c’est pourquoi le plan d’adressage est le document qui compte.
Testez la séparation avec deux rôles arrêtés
Le test utile est une soustraction : arrêtez deux rôles et confirmez que le troisième répond encore. Une requête web doit aboutir avec le service de tunnel arrêté, et une poignée de main de tunnel doit aboutir avec le serveur web arrêté. Si les deux ne fonctionnent que lorsque tout tourne, vous avez une dépendance accidentelle, comme une table de pare-feu partagée, une route parasite ou un nom pointant vers la mauvaise adresse.
Trois commandes rendent ce test concret. curl -sk --resolve example.test:443:203.0.113.10 https://example.test/ prouve que l’écouteur local répond sans DNS externe, wg show sur le client prouve que la poignée de main a abouti, et tcpdump -ni any port 51820 sur le concentrateur sépare un problème de routage d’un problème de clé. Une poignée de main qui n’apparaît jamais dans la capture est morte avant l’hôte : pare-feu du fournisseur, mauvaise adresse publique ou règle NAT en chemin.
Répétez la soustraction pour les réseaux locaux transférés. Avec un pair déconnecté, un ping à travers le concentrateur doit échouer ; une fois reconnecté, le ping doit revenir sans toucher à une règle. Un ping qui ne revient qu’après un redémarrage du tunnel pointe la politique plutôt que la joignabilité, ce qui est une autre correction.
Gardez le jeu de règles lisible pendant que vous soustrayez des rôles. nft list ruleset doit montrer une règle d’acceptation par direction réellement nécessaire, et une chaîne de transfert qui accepte tout n’est pas une séparation, c’est une démonstration qui marche.
Lignes d’accès IPv6 uniquement et services IPv4
Certaines lignes d’accès ne donnent que la joignabilité IPv6, et les services doivent quand même être publiés en IPv4. Le tunnel lui-même passe par la famille qui transporte encore du trafic, tandis que le service publié se trouve sur une adresse à l’intérieur du tunnel. Cela inverse l’hypothèse habituelle et casse discrètement la supervision : une règle de pare-feu ou un contrôle de disponibilité écrit pour le chemin IPv4 surveille désormais une interface qui ne porte rien.
Testez chaque famille séparément avec curl -4 et curl -6, car une requête réussie ne dit rien du chemin que vous n’avez pas essayé. La propriété des ports ne change pas d’une famille à l’autre, mais l’écouteur, lui, change : ss -lntup liste les sockets IPv4 et IPv6 sur des lignes séparées, et 0.0.0.0:443 ne couvre pas [::]:443 sauf si le processus a demandé une socket double pile.
Un service qui répond sur une famille et refuse sur l’autre est généralement un problème d’écouteur, pas de routage. Avant de déclarer la conception terminée, confirmez que chaque rôle possède sa propre adresse ou son propre port, que le transfert est activé et autorisé, et que chaque rôle répond encore avec les deux autres arrêtés.