VPN and Egress FR - Kheopsian/Hydranos GitHub Wiki
S'applique à Hydranos 4.4.
Pour vous si vous voulez faire passer le trafic d'Hydranos par un VPN ou un proxy : ce que chacun des cinq modes de l'onglet Réseau (Network) envoie où, ce que bloque le kill switch (coupe-circuit), quel chemin prennent les requêtes propres au démon, et les configurations qui fonctionnent (tout le processus dans le VPN, un tunnel ou une interface par moteur, un proxy). Les tunnels qu'Hydranos monte lui-même ont leur propre page : WireGuard géré.
-
Les cinq modes de l'onglet Réseau sont réels. Direct, WireGuard, managed by Hydranos, Gluetun, Proxy SOCKS5 (SOCKS5 proxy) et Proxy SOCKS5 + relais PROXY-v2 (SOCKS5 + PROXY-v2 relay) changent chacun ce que font les moteurs. Le mode est stocké dans
[network] mode(voir Réseau). -
Tout ce qu'envoie un moteur suit sa propre sortie. Sous Linux,
bind_interfaceépingle chaque socket du moteur : écoute, uTP, connexions sortantes vers les pairs, annonces HTTP et UDP, DHT, LSD, webseeds, scrapes. Chaque moteur se connecte avec son propre rattachement et son propre peer id. Derrière un proxy SOCKS5, les pairs, les annonces et les webseeds passent par le proxy, et ce que l'UDP ne peut pas transporter est désactivé. - Un kill switch suit le mode. Il est désarmé en mode Direct et armé dans les quatre autres. Armé, il tient hors du réseau un moteur sans tunnel, sans interface et sans proxy, sauf si vous le marquez direct délibérément.
-
Les requêtes propres au démon ont leur propre route. Les listes de trackers, les listes du filtre IP, la vérification de mise à jour, les webhooks et les URL
.torrentsuivent ce que dit[daemon] egress. Par défaut, c'est la sortie qu'implique le mode ; quand le kill switch est armé et que cette sortie manque, elles sont refusées plutôt qu'envoyées par la route par défaut. - Certains trafics ne sont jamais couverts : le trafic local, les paquets chiffrés de WireGuard lui-même, les noms de trackers résolus par l'hôte pour une interface qu'Hydranos n'a pas créée, et les pairs entrants sur le port de l'hôte derrière un proxy SOCKS5. La liste figure sous Ce qui reste en dehors.
| Mode (carte) | Ce qui transporte le trafic d'un moteur | Kill switch par défaut | Port entrant |
|---|---|---|---|
| Direct | Son bind_interface (Linux), ou la route par défaut de l'hôte s'il est vide |
Désarmé |
listen_port ; routeur domestique via NAT-PMP/UPnP (auto_port_forward) |
| WireGuard, managed by Hydranos | Un tunnel wg-<engine> qu'Hydranos monte à partir d'un .conf du fournisseur (Linux, NET_ADMIN). Détails : WireGuard géré
|
Armé | NAT-PMP à travers le tunnel, ou un port saisi à la main, selon le fournisseur |
| Gluetun | L'espace de noms réseau de gluetun (la route par défaut du conteneur est le tunnel) | Armé | Lu sur le serveur de contrôle de gluetun et suivi |
| Proxy SOCKS5 | Le proxy : connexions sortantes vers les pairs, annonces HTTP, magnets et webseeds (socks5h://, noms résolus par le proxy). DHT, LSD, trackers UDP et uTP sortant désactivés |
Armé | Aucun via le proxy : les pairs entrants atteignent le port d'écoute de l'hôte lui-même, s'il est joignable |
| Proxy SOCKS5 + relais PROXY-v2 | Comme SOCKS5, plus une écoute pour un relais qui transmet les pairs entrants avec un en-tête PROXY-v2 | Armé | Le port du relais |
Enregistrer un mode retire les clés des autres modes de [race], [hoard] et du bloc de chaque moteur supplémentaire. Champs, ports et règle de redémarrage : Réseau.
Un mode par instance. [network] mode contient une seule valeur pour tout le processus : une instance ne peut pas mettre un moteur derrière gluetun et un autre dans un tunnel WireGuard géré. En mode WireGuard, la Sortie (Way out) de chaque moteur est un .conf, Direct (interface par défaut) (Direct (default interface)) ou Non affecté (bloqué par le kill switch) (Not assigned (blocked by the kill switch)) ; un moteur ne peut être épinglé que sur une interface qui existe dans l'espace de noms réseau propre d'Hydranos, jamais dans celui d'un autre conteneur. Pour mélanger gluetun avec du WireGuard géré ou des moteurs directs, faites tourner une deuxième instance dans gluetun (Configuration 1 ci-dessous) et déclarez-la comme nœud (Topologies de déploiement). Le WireGuard géré dans l'espace de noms de gluetun n'est pas testé : là, Direct désigne le tunnel de gluetun, et les tunnels gérés tourneraient à l'intérieur.
bind_interface = "wg0" dans la section d'un moteur fait appliquer par Hydranos SO_BINDTODEVICE (Linux uniquement) aux sockets de ce moteur. Le journal indique [engine] every socket is pinned to device wg0. Une socket qui ne peut pas être épinglée n'est pas ouverte. Il n'y a jamais de repli sur la route par défaut : l'écoute refuse de démarrer ("refusing to listen on the default route"), une connexion sortante échoue, et si l'interface est absente au démarrage l'uTP reste désactivé ("uTP disabled rather than leak the default route; restart once the interface is up").
| Trafic | Suit l'interface du moteur ? | Détails |
|---|---|---|
Écoute des pairs, TCP (et [::] avec enable_ipv6 = true) |
✓ | Les réponses sortent par la même interface. |
| Socket uTP (UDP, même port que TCP) | ✓ | Désactivée si elle ne peut pas être épinglée. |
| Connexions sortantes vers les pairs | ✓ celle du moteur | Une file de connexions sortantes par moteur, avec l'interface, le peer id, la socket uTP et les limites de ce moteur. |
| Annonces HTTP/HTTPS, magnets | ✓ | Noms des trackers : le DNS du tunnel pour un tunnel géré, sinon le résolveur de l'hôte (voir DNS). |
| Annonces et scrapes UDP | ✓ | Une socket UDP qui ne peut pas être épinglée n'est pas ouverte. |
| DHT | ✓ | Liée au périphérique. Désactivée derrière un proxy SOCKS5. |
| LSD (découverte de pairs locaux) | ✓ | Multicast sur le périphérique : un moteur dans un tunnel n'atteint donc jamais le réseau local de l'hôte. Désactivée derrière un proxy SOCKS5. |
| Webseeds | ✓ | Épinglés comme les annonces. |
| NAT-PMP/UPnP vers le routeur domestique | ✗ pas de redirection | Aucune redirection domestique pour un moteur épinglé sur une autre interface que celle de la route par défaut, ni pour un moteur dans un tunnel, derrière un proxy ou derrière gluetun. Un tunnel géré interroge plutôt sa propre passerelle. |
| Sonde d'IP de sortie (panneau Réseau de l'en-tête) | ✓ | Toutes les 180 s, api.ipify.org / api6.ipify.org via l'interface du moteur. |
Listes de trackers et du filtre IP, vérification de mise à jour, webhooks, URL .torrent
|
— | La route du démon ([daemon] egress, plus bas). |
| Flux RSS | — | La sortie du moteur auquel ajoute la première règle activée du flux (voir RSS et téléchargements automatiques). |
| Appels aux nœuds déclarés, import qBittorrent, serveur de contrôle gluetun | ✗ local | Jamais par un tunnel ni un proxy. |
Depuis la 4.4, chaque moteur se connecte avec son propre rattachement : deux moteurs sur deux tunnels sont deux sorties distinctes, et un moteur sur la route par défaut ne tire plus hors de leur tunnel les connexions sortantes des autres. Les requêtes propres au démon sont un troisième propriétaire, avec leur propre route.
flowchart LR
subgraph proc["Processus Hydranos"]
RACE["moteur race<br/>écoute, uTP, connexions sortantes,<br/>annonces, DHT, LSD, webseeds"]
HOARD["moteur hoard<br/>écoute, uTP, connexions sortantes,<br/>annonces, DHT, LSD, webseeds"]
DAE["requêtes du démon<br/>listes de trackers et du filtre IP,<br/>vérification de mise à jour, webhooks, URL .torrent"]
LOCAL["appels aux nœuds, import qBittorrent,<br/>serveur de contrôle gluetun"]
end
RACE --> WG0["wg0<br/>bind_interface de race"]
HOARD --> WG1["wg1<br/>bind_interface de hoard"]
DAE --> EG["egress du démon<br/>auto, direct, proxy ou engine:id"]
LOCAL --> LAN["réseau local"]
WG0 --> VPNA["serveur VPN A"]
WG1 --> VPNB["serveur VPN B"]
EG --> SEL["la sortie que donne le réglage,<br/>ou refusé"]
VPNA --> NET["pairs, trackers, nœuds DHT"]
VPNB --> NET
[daemon] kill_switch décide si un moteur sans sortie propre peut utiliser la route par défaut de l'hôte :
[daemon] kill_switch |
Effet |
|---|---|
| absent (par défaut) | Suit le mode : désarmé en Direct, armé dans les quatre autres. |
false |
Désarmé : un moteur sans sortie passe par l'hôte. Il est signalé NON couvert (NOT covered) dans les quatre autres modes, mais comme direct (direct mode: the host's default route) en mode Direct. |
true |
Armé même en mode Direct : rien ne sort sans interface, proxy ou allow_direct. |
allow_direct = true dans la section d'un moteur ([race], [hoard] ou le bloc d'un moteur supplémentaire ; un moteur supplémentaire n'en hérite pas) le marque direct assumé (direct on purpose). En mode WireGuard, le même choix est Direct (interface par défaut) dans la liste Sortie du moteur.
Chaque moteur reçoit un verdict, décidé quand il rejoint le réseau :
flowchart TD
E["moteur au démarrage"] --> M{"le mode est WireGuard ?"}
M -->|oui| T{"tunnel affecté ?"}
T -->|oui| C1["couvert : son tunnel"]
T -->|non| WD{"Direct choisi pour lui ?"}
WD -->|oui| D1["direct assumé"]
WD -->|non| AR
M -->|non| I{"bind_interface défini ?"}
I -->|oui| GI{"mode Gluetun et pas l'interface<br/>de la route par défaut ?"}
GI -->|oui| AR
GI -->|non| C2["couvert : chaque socket épinglée"]
I -->|non| P{"proxy SOCKS5 défini ?"}
P -->|oui| C3["couvert : via le proxy"]
P -->|non| G{"mode Gluetun ?"}
G -->|oui| C4["couvert : pare-feu de gluetun"]
G -->|non| AD{"allow_direct ?"}
AD -->|oui| D2["direct assumé"]
AD -->|non| DM{"mode Direct, désarmé ?"}
DM -->|oui| D3["direct"]
DM -->|non| AR{"kill switch armé ?"}
AR -->|oui| B["BLOQUÉ : tenu hors du réseau"]
AR -->|non| U["NON couvert : sort par l'hôte"]
-
Bloqué veut dire jamais mis sur le réseau : pas d'écoute, pas de connexion sortante, pas d'annonce, pas de DHT, pas de LSD, pas de redirection de port, pas de sonde d'IP de sortie et pas de vérification réseau en son nom. Ses torrents restent chargés. Le journal indique
kill switch: BLOCKED, kept off the network (no listener, no dial, no announce, no DHT, no LSD): …, et/healthrenvoiedegradedavec un avertissement qui nomme le moteur (jamaisunhealthy). -
Décidé au démarrage. Changer le mode,
kill_switchouallow_directde sorte qu'un autre ensemble de moteurs soit bloqué demande un redémarrage ; la réponse à l'enregistrement indiquerestart_required. - Un moteur épinglé est couvert, car une interface absente signifie pas de réseau pour lui, jamais la route par défaut. Il en va de même pour un tunnel géré tombé.
- Le mode Gluetun fait confiance au mode déclaré : Hydranos ne vérifie pas qu'il tourne vraiment dans l'espace de noms de gluetun.
Les verdicts sont donnés trois fois dans les mêmes termes : au démarrage (lignes kill switch: …, une par moteur et une pour le démon), sur GET /api/network/egress (et dans kill_switch de GET /api/network/mode), et dans l'onglet Réseau.
La carte Kill switch et requêtes du démon (Kill switch and the daemon's own requests) s'affiche dans tous les modes, sous les champs du mode. Elle contient :
- la ligne d'état
Kill switch armé(Kill switch armed) ouKill switch désarmé(Kill switch disarmed), avec la raison ; - une ligne par moteur :
<engine>: couvert(covered),direct assumé(direct on purpose),BLOQUÉ(BLOCKED) ouNON couvert(NOT covered), avec sa façon de sortir, ses lacunes, etprend effet au prochain redémarrage(takes effect at the next restart) quand le fichier ne correspond plus au moteur en marche. Une case Direct assumé (Direct on purpose) par moteur écritallow_direct(absente dans les modes WireGuard et Gluetun) ; -
Requêtes externes du démon (External requests of the daemon) et Kill switch (
Suivre le mode réseau(Follow the network mode),Désarmé : fuites acceptées(Disarmed: leaks accepted),Armé, même en mode direct(Armed, even in direct mode)) ; -
Hôte du proxy (Proxy host), Port du proxy (Proxy port), Nom d'utilisateur (Username), Mot de passe (Password), Interface du démon (Daemon interface) (la section
[proxy]et[daemon] bind_interface) ; - un dépliant Ce que le kill switch ne couvre pas (What the kill switch does not cover), et le bouton Enregistrer le trafic du démon (Save daemon traffic).
Tout ce qui n'appartient à aucun moteur passe par un seul client : téléchargements de listes de trackers, listes du filtre IP, vérification de mise à jour (et hydranos-update), webhooks des workflows, URL .torrent récupérées par le serveur MCP, et la sonde d'IP de sortie du processus (/api/public-ip). Sa route est fixée par [daemon] egress :
[daemon] egress |
Route |
|---|---|
vide ou auto (par défaut) |
Suit le mode : SOCKS5/PROXY-v2 : le proxy de race, sinon le premier moteur qui en a un. WireGuard : le tunnel de race, sinon le premier moteur dans un tunnel. Gluetun : direct, dans le réseau de gluetun. Direct : la route par défaut, rattachée à [daemon] bind_interface s'il est défini. Avec le kill switch armé et rien à emprunter, chaque requête est refusée. |
direct |
La route par défaut de l'hôte (ou [daemon] bind_interface). Un choix : jamais refusé. |
proxy |
La section [proxy], en socks5h:// (noms résolus par le proxy). Refusé si socks5_host est vide. |
engine:<id> |
La même sortie que ce moteur : son tunnel, son interface ou son proxy. Refusé si ce moteur est bloqué ou n'est pas sur ce nœud. |
| toute autre valeur | Chaque requête refusée : [daemon] egress = "…" is not auto, direct, proxy or engine:<id>; nothing is sent until it is. |
[daemon]
egress = "proxy" # auto, direct, proxy or engine:<id>
bind_interface = "" # the daemon's requests, or its connection to the proxy
# kill_switch = true # absent: follow the mode
[proxy]
socks5_host = "198.51.100.7"
socks5_port = 1080 # 0 means 1080
socks5_user = ""
socks5_pass = ""-
Appliqué tout de suite. La route change à la requête suivante après un enregistrement, sans redémarrage. Le journal indique
egress: the daemon's own requests now go via …. -
Les refus donnent leur raison dans l'erreur de chaque requête et dans l'onglet Réseau (
Les requêtes propres au démon sont refusées : …(The daemon's own requests are refused: …)). Avec le kill switch armé en mode Direct et rien de défini, la raison commence parkill switch on in direct mode: set [daemon] egress …. - Une interface absente fait refuser la requête plutôt que d'en utiliser une autre.
-
API :
GET /api/network/egressrenvoie le rapport (mode,armed,armed_why, le verdict de chaque moteur, leviadu démon,not_covered).POST /api/network/egressaccepte n'importe lesquels deegress,socks5_host/socks5_port/socks5_user/socks5_pass(un hôte vide retire[proxy]),bind_interface,kill_switch(true,false, ounull/"auto"pour suivre le mode) etallow_direct({"<engine>": true}). Il répond par le nouveau rapport avecrestart_required.
Les mots de passe SOCKS5 valent ******** dans GET /api/network/mode (fields.socks5_pass), GET /api/network/egress (daemon.socks5_pass) et GET /api/settings ; renvoyer le masque garde le mot de passe enregistré.
Bug connu en 4.4 : une URL
announce_proxysemble aussi privée que les mots de passe — elle n'est pas masquée, donc unuser:passqu'elle contient est renvoyé en clair parGET /api/settingsà quiconque détient la clé API — considérez que la clé API donne accès à cet identifiant (Sécurité & accès).
| Qui résout | Où sont résolus les noms des trackers et des hôtes |
|---|---|
Moteur derrière un proxy SOCKS5, ou avec announce_proxy
|
Par le proxy quand l'URL est en socks5h:// (toujours le cas pour le proxy SOCKS5). announce_proxy est utilisé tel qu'écrit : avec socks5:// le nom est résolu ici, avec http:///https:// il est confié au proxy (comportement de la bibliothèque HTTP, non testé). |
| Moteur dans un tunnel WireGuard géré | Par le serveur DNS = de son .conf, à travers le tunnel, jamais par l'hôte. Un .conf sans DNS = se replie sur le résolveur de l'hôte et est signalé comme fuite de noms. |
| Moteur épinglé sur une interface qu'Hydranos n'a pas créée | Par le résolveur de l'hôte (une lacune que signale le kill switch). |
Démon via [proxy]
|
Par le proxy. |
| Démon via une interface sans proxy | Par le DNS du tunnel s'il s'agit d'un tunnel géré, sinon par le résolveur de l'hôte. |
Seuls les noms sortent ainsi : les connexions elles-mêmes suivent toujours l'interface du moteur.
Le kill switch ne couvre jamais ces trafics, quelle que soit la configuration (not_covered dans l'API, et journalisés comme kill switch: outside its scope -- … quand il est armé) :
- Le trafic local reste local : le serveur de contrôle gluetun, les autres nœuds Hydranos, un qBittorrent en cours d'import, et NAT-PMP/UPnP vers le routeur domestique pour un moteur non épinglé.
- Les paquets chiffrés de WireGuard lui-même sortent par la route par défaut : ils sont le tunnel.
- Un moteur épinglé sur une interface qu'Hydranos n'a pas créée résout les noms des trackers avec le résolveur de l'hôte.
- Les requêtes du démon via une interface sans proxy résolvent les noms avec le résolveur de l'hôte, sauf si cette interface est un tunnel géré.
- Un moteur derrière un proxy SOCKS5 accepte toujours les pairs entrants sur le port d'écoute propre de l'hôte.
Bug connu en 4.4 : la carte SOCKS5 semble vous cacher des pairs entrants (« Personne ne peut vous joindre depuis l'extérieur. » (Nobody can connect to you from outside)) — les pairs entrants atteignent toujours le port d'écoute de l'hôte s'il est joignable — fermez ce port sur votre routeur s'il ne doit pas être atteint. La même carte dit aussi que la DHT montre encore votre adresse : ce n'est pas le cas, la DHT est désactivée derrière le proxy.
Utilisez-la quand tout doit passer par le VPN, y compris le trafic qu'Hydranos ne route pas lui-même. Hydranos tourne dans un espace de noms réseau dont la route par défaut est le tunnel, de sorte que chaque flux sort par lui.
Le conteneur Hydranos rejoint l'espace de noms réseau de gluetun avec network_mode: "service:gluetun". Un conteneur dans ce mode n'a pas de ports à lui, donc ses ports sont publiés sur le service gluetun. Choisissez le mode Gluetun dans l'onglet Réseau : Hydranos lit alors le port redirigé de gluetun et le suit, et le kill switch est armé (le pare-feu de gluetun est le kill switch). Champs du modèle Unraid : Unraid behind gluetun sur Installer avec Docker.
flowchart LR
LAN["navigateur, Sonarr, Radarr"] -->|"8199"| GPORTS
subgraph gl["espace de noms réseau du conteneur gluetun"]
GPORTS["port publié 8199"]
CTL["serveur de contrôle gluetun<br/>127.0.0.1:8000"]
HY["conteneur hydranos<br/>moteurs et requêtes du démon"]
TUN["tunnel VPN<br/>route par défaut"]
GPORTS --> HY
HY -->|"GET /v1/portforward"| CTL
HY --> TUN
end
TUN --> NET["pairs, trackers, DHT"]
NET -->|"port redirigé P"| TUN
Le service hydranos est adapté du compose de référence de la page Installer avec Docker (tag figé, délai d'arrêt de 150 s) ; seules les lignes réseau changent. Tout ce qui se trouve sous gluetun: est la configuration propre de gluetun : les noms de variables sont ceux que gluetun documente habituellement, le code d'Hydranos ne les vérifie pas, et ce bloc n'est pas testé par le mainteneur. Consultez la documentation de gluetun pour votre fournisseur et pour les clés d'API de son serveur de contrôle.
services:
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
VPN_SERVICE_PROVIDER: "your-provider"
VPN_TYPE: "wireguard"
WIREGUARD_PRIVATE_KEY: "your-key"
# Provider with port forwarding: gluetun requests the port and opens it;
# Hydranos reads it from the control server (Gluetun mode).
VPN_PORT_FORWARDING: "on"
# Provider with a fixed port you already know: drop the line above
# and open the port yourself instead.
# FIREWALL_VPN_INPUT_PORTS: "47000"
# Your LAN, so Hydranos can reach qBittorrent (import), webhook
# targets and declared nodes there.
FIREWALL_OUTBOUND_SUBNETS: "192.0.2.0/24"
volumes:
- ./gluetun:/gluetun
ports:
# Hydranos's ports are published HERE, not on the hydranos service.
- "8199:8199/tcp" # web UI, REST API, qBittorrent shim, MCP
restart: unless-stopped
hydranos:
image: ghcr.io/kheopsian/hydranos:v4.4.1
container_name: hydranos
network_mode: "service:gluetun" # share gluetun's network namespace
depends_on:
- gluetun
restart: unless-stopped
stop_grace_period: 150s
ulimits:
nofile:
soft: 1048576
hard: 1048576
environment:
PUID: "1000" # Unraid: 99
PGID: "1000" # Unraid: 100
logging:
driver: json-file
options:
max-size: "128m"
max-file: "5"
volumes:
- ./config:/config # Unraid: a pool path, see Install with Docker
- ./data:/dataLes ports de pairs ne sont pas publiés. Les pairs entrants arrivent par le tunnel sur le port redirigé ; publier 16171 ou 16172 sur l'hôte ne les ouvrirait que sur votre réseau local.
Ensuite, dans l'onglet Réseau, choisissez Gluetun et remplissez :
-
Prendre le port d'écoute depuis gluetun (Take the listen port from gluetun) : activé. Hydranos interroge le serveur de contrôle sur
/v1/portforward(puis/v1/openvpn/portforwardeden cas de 404, pour les anciens gluetun), toutes les 10 s tant qu'aucun port n'est connu, puis toutes les 60 s. L'écoute du moteur (TCP et uTP) se déplace sur ce port, et les annonces sont retenues tant que ce n'est pas fait : un tracker ne reçoit jamais un port deviné. Un port qui ne peut pas être lié les garde retenues. -
Serveur de contrôle gluetun (Gluetun control server) : vide signifie
http://127.0.0.1:8000, ce qui est juste quand Hydranos partage le réseau de gluetun. -
Clé d'API gluetun (Gluetun API key) : envoyée en
X-API-Key. Les versions récentes de gluetun refusent les requêtes sans clé ; le rôle de la clé doit autoriserGET /v1/portforward. Un 401/403 est journalisé commegluetun port forward: cannot read the portavecset the gluetun API key, with GET /v1/portforward allowed. - Moteur qui prend le port (Engine that takes the port) : hoard ou race. Un fournisseur redirige un seul port, donc un seul moteur est joignable ; les autres gardent leur propre port d'écoute et ne reçoivent aucun pair entrant.
Enregistrez, puis Appliquer et redémarrer (Apply & restart) (un arrêt propre, vidage de l'état de reprise compris). Remarques :
-
Pas de réponse de gluetun, pas d'annonces. Tant que le serveur de contrôle ne donne pas de port, le moteur qui le suit n'annonce rien. Le port suivi n'est pas écrit dans
default.toml. -
Pas de redirection de port domestique en mode Gluetun (
behind gluetun the port comes from the VPN provider) :auto_port_forwardn'a pas besoin d'être modifié. Si vous gardez plutôt le mode Direct dans gluetun, réglezauto_port_forward = falseet écrivez le port redirigé commelisten_portà la main. -
Les requêtes du démon sortent en direct dans le réseau de gluetun (
egress = auto), qui est le tunnel. -
Sonarr, Radarr, autobrr joignent Hydranos à l'hôte
gluetun, port8199, quand ils partagent un réseau Docker défini par l'utilisateur avec gluetun (un réseau compose en est un). Le nomhydranosne se résout vers rien dans cette configuration. Sur le réseau bridge par défaut de Docker, les noms de conteneurs ne se résolvent pas : utilisez l'adresse de l'hôte Docker et le port 8199. -
Services du réseau local depuis gluetun. Le pare-feu de gluetun bloque le trafic vers votre réseau local sauf si le sous-réseau figure dans
FIREWALL_OUTBOUND_SUBNETS(comportement de gluetun) : sans cela, l'import qBittorrent, les webhooks vers des hôtes du réseau local et les nœuds déclarés sur le réseau local échouent. -
Quand gluetun redémarre ou est recréé, le conteneur Hydranos garde l'ancien espace de noms réseau, mort : plus de réseau ni d'interface web tant que vous ne redémarrez pas aussi Hydranos (
docker restart -t 150 hydranos). Comportement de Docker, non testé par le mainteneur ;depends_onn'ordonne que le premier démarrage. Une reconnexion du tunnel à l'intérieur d'un gluetun en marche conserve l'espace de noms. - Quand le tunnel tombe, que le trafic soit bloqué entre-temps dépend du pare-feu de gluetun. N'épinglez pas de moteur sur une autre interface dans ce mode : le kill switch bloque un moteur épinglé à côté du tunnel de gluetun.
La même règle sans Docker : la route par défaut vue par le processus hydranos doit être le tunnel.
-
Tout l'hôte dans le VPN : un client WireGuard ou OpenVPN qui route tout le trafic (pour WireGuard,
AllowedIPs = 0.0.0.0/0, ::/0). Tout ce qu'envoie l'hôte, Hydranos compris, passe par le tunnel. -
Seulement Hydranos dans le VPN : créez un espace de noms réseau qui contient l'interface du tunnel et l'utilise comme route par défaut, puis démarrez le service à l'intérieur (par exemple avec
NetworkNamespacePath=de systemd dans un fichier drop-in pour l'unité décrite dans Installer sous Linux). Cela se fait avec les outils de votre système, hors d'Hydranos. Gardez le port 8199 joignable depuis l'endroit où vous utilisez l'interface web.
Dans les deux cas, laissez bind_interface vide, gardez le mode Direct et réglez listen_port sur le port redirigé par le fournisseur. Pour garder la route propre de l'hôte tout en mettant les moteurs dans un VPN sans rien construire vous-même, utilisez plutôt le WireGuard géré.
Chaque moteur sort par sa propre sortie, dans un seul processus, tandis que l'hôte garde sa connexion normale. Deux façons :
-
WireGuard géré : donnez à chaque moteur un
.confdu fournisseur ; Hydranos montewg-<engine>, le route dans une table à lui, demande le port entrant et résout les noms à travers le tunnel. Voir WireGuard géré. - Vos propres interfaces, en mode Direct : créez les tunnels hors d'Hydranos, puis épinglez chaque moteur.
Pour la deuxième façon :
-
Créez les tunnels, par exemple avec
wg-quick up wg0etwg-quick up wg1, avecTable = offdans chaque configuration WireGuard pour qu'un tunnel ne prenne pas la route par défaut de l'hôte. -
Épinglez chaque moteur sur son interface, soit dans Config › Paramètres avancés › Réseau (Interface per engine : Race engine interface, Hoard engine interface, et une ligne par moteur supplémentaire), soit dans
default.toml:[race] listen_port = 16171 bind_interface = "wg0" [hoard] listen_port = 16172 bind_interface = "wg1"
Les listes déroulantes ne proposent, et + Add an engine dans l'onglet Nodes n'accepte, que les interfaces dont l'état noyau est exactement
up(sinon le formulaire répondno interface named … is up). Les périphériques de tunnel signalent souventunknownà la place (constaté sur un périphérique tun ; non vérifié sur une interfacewg-quick). Si la vôtre manque dans la liste, écrivezbind_interfaceà la main dansdefault.toml; la liste déroulante conserve une valeur déjà présente dans le fichier. Pour les moteurs supplémentaires, voir Moteurs : race et hoard. -
Redémarrez Hydranos. Vérifiez dans le journal la présence de
every socket is pinned to device …une fois par moteur.
Limites exactes :
- Linux uniquement. Ailleurs, la clé est refusée (plus bas).
-
Le kill switch est désarmé en mode Direct. Un moteur que vous avez laissé sans interface utilise la route par défaut. Réglez
[daemon] kill_switch = truepour bloquer tout moteur sans interface, sans proxy et sansallow_direct. -
L'interface doit exister dans l'espace de noms réseau d'Hydranos. Sous Docker, cela veut dire
network_mode: hostavec les tunnels sur l'hôte, ou des tunnels créés dans le conteneur (ce qui demandeNET_ADMIN) ; un conteneur sur le réseau bridge par défaut ne voit pas lewg0de l'hôte. -
Si l'interface est absente au démarrage, l'écoute de ce moteur ne s'ouvre pas (l'API le signale comme n'écoutant pas), ses connexions sortantes échouent et son uTP reste désactivé jusqu'à ce qu'un redémarrage trouve l'interface. Rien ne sort par la route par défaut. Un
bind_interfacemodifié à la main qui nomme une interface absente n'empêche pas Hydranos de démarrer. - Les noms des trackers sont résolus par le résolveur de l'hôte pour une interface qu'Hydranos n'a pas créée (les connexions utilisent tout de même l'interface).
-
Privilèges.
SO_BINDTODEVICEdemandeCAP_NET_RAWsur les noyaux antérieurs à 5.7. Tourner en root (la valeur par défaut sous Docker) le donne. AvecPUID/PGIDsous Docker ou l'utilisateur systemd du paquet sur un vieux noyau, l'épinglage peut échouer et l'écoute refuse alors de s'ouvrir (non testé).
Deux clés par moteur, dans [race], [hoard] ou le bloc d'un moteur supplémentaire :
| Clé | Effet |
|---|---|
announce_proxy |
Une URL de proxy pour les annonces HTTP, les magnets et les webseeds de ce moteur (socks5h://user:pass@host:port, socks5://, http://, https://). Prime sur le proxy SOCKS5 du moteur. Vide : le proxy SOCKS5 si le moteur en a un, sinon TYPHON_ANNOUNCE_PROXY, sinon direct. |
announce_ip |
Envoyée aux trackers en ip= (BEP 7) dans les annonces HTTP, et dans le champ IPv4 des annonces UDP. Vide : rien n'est envoyé, et le tracker enregistre l'adresse d'où vient l'annonce. |
L'onglet Réseau ne les affiche que dans les modes SOCKS5 (Proxy d'annonce (facultatif) (Announce proxy (optional)), Adresse annoncée aux trackers (facultatif) (Address announced to trackers (optional))), et l'enregistrement de tout autre mode les retire. Écrites à la main en mode Direct, elles sont tout de même lues.
TYPHON_ANNOUNCE_PROXY (une variable d'environnement, voir Configuration : variables d'environnement, CLI et signaux) est désormais un repli : elle s'applique à un moteur qui n'a ni announce_proxy ni proxy SOCKS5. L'onglet Réseau la liste sous Défini dans l'environnement (Set in the environment), et avertit quand elle est définie en dehors des modes SOCKS5.
environment:
TYPHON_ANNOUNCE_PROXY: "socks5h://192.0.2.2:1080"-
Les trackers UDP sont refusés tant que les annonces d'un moteur passent par un proxy. Leur état affiche
UDP trackers do not go through a SOCKS5 proxy (no UDP ASSOCIATE): they will not be announced while this proxy is active. Les torrents dont les seuls trackers sont enudp://ne sont alors pas annoncés du tout. -
Une URL inutilisable fait échouer l'annonce (
announce proxy … is not usable) ; elle ne part jamais en direct à la place. - Non couvert par un proxy d'annonces seul : connexions aux pairs, DHT, LSD. Pour cela, utilisez le mode SOCKS5 ou une interface.
-
bind_interfaceest réservé à Linux. Windows ne peut pas épingler une socket sur une interface par son nom, et macOS ne peut pas épingler les sockets TCP de pairs. Une valeur non vide est refusée avec un 400 parPOST /api/network/modeetPOST /api/engines(bind_interface is Linux-only: this platform cannot pin every socket of an engine to an interface (TCP peers would leave by the default route). Run the VPN client system-wide instead). L'onglet Réseau affiche, sous Interface per engine, Épingler un engine à une interface n'est possible que sous Linux : sur cette plateforme, ses connexions aux pairs partiraient par la route par défaut. Lancez plutôt votre client VPN pour tout le système. (Pinning an engine to an interface is Linux-only…) à la place des champs. Un moteur dont le fichier définit encore la clé démarre hors du réseau (pas d'écoute, de connexion sortante, d'annonce, de DHT, de LSD ni d'uTP), avec une erreur dans le journal. -
Le WireGuard géré est réservé à Linux : la carte est grisée avec
Le WireGuard géré nécessite Linux. Sur ce système, montez le tunnel vous-même et choisissez son interface en mode Direct.(Managed WireGuard needs Linux. On this system, bring the tunnel up yourself and pick its interface in Direct mode.), et l'API répond 409. - Gluetun n'a de sens que dans Docker sous Linux.
-
Les modes SOCKS5 et
[daemon] egress = "proxy"ne dépendent pas de la plateforme (non testé par le mainteneur sous Windows). -
Un VPN pour tout le système est la façon de mettre un moteur Windows dans un VPN (la règle de la configuration 1 : la route par défaut est le tunnel). Le kill switch ne voit pas un VPN système : s'il est armé, marquez les moteurs
allow_direct(ou laissez le kill switch désarmé). - La redirection de port automatique n'y essaie que l'UPnP (TCP et UDP) ; NAT-PMP demande Linux. Aucune version macOS n'est publiée. Plus d'informations sur Installer sous Windows.
Bug connu en 4.4 : Interface du démon (Daemon interface) semble utilisable sous Windows — l'onglet Réseau et
POST /api/network/egressacceptent[daemon] bind_interface— mais chaque requête du démon (listes, vérification de mise à jour, webhooks, URL.torrent) est alors refusée avec[daemon] bind_interface … cannot be applied on this platform— laissez Interface du démon vide et utilisez[proxy]. Sous macOS, elle est appliquée.
Le panneau Réseau de l'en-tête montre ce que voit la sonde de chaque moteur à travers son interface (ou rien pour un moteur bloqué), et la ligne du processus est la route du démon. Le bouton Vérifier ce qui se passe vraiment (Check what actually happens) de l'onglet Réseau mesure, pour chaque moteur local, le chemin des annonces et le chemin des pairs par la sortie qu'ils prennent réellement, ainsi que les requêtes du démon. Un chemin qui ressort avec l'adresse de la route par défaut alors qu'une autre sortie est configurée est un fail avec LEAK: ….
Bug connu en 4.4 : Vérifier ce qui se passe vraiment semble être un test de fuite dans tous les modes — avec le kill switch armé (tous les modes sauf Direct par défaut), la route par défaut n'est pas mesurée, donc chaque ligne épinglée ou passant par un proxy est un
warn(« a leak cannot be ruled out ») et aucunLEAKne peut être trouvé — vérifiez depuis l'extérieur comme ci-dessous.
Adresse de sortie d'une route (hôte Linux) :
curl -s https://api.ipify.org; echo # default route
curl -s --interface wg0 https://api.ipify.org; echo # through wg0Dans la configuration gluetun. L'image Hydranos ne contient pas curl, mais elle a ip, et son API indique l'adresse de sortie du démon :
docker inspect -f '{{.HostConfig.NetworkMode}}' hydranos # container:<id of gluetun>
docker exec hydranos ip route # default route via the tunnel
curl -s -H "X-Api-Key: YOUR_API_KEY" "http://127.0.0.1:8199/api/public-ip?refresh=1"
docker run --rm --network container:gluetun curlimages/curl -s https://api.ipify.org
docker run --rm --network container:gluetun curlimages/curl -6 -s -m 10 https://api6.ipify.org/api/public-ip répond {"ip": …, "ip_v6": …} pour la route du démon : les deux doivent être des adresses VPN ou vides. Il garde la dernière adresse trouvée quand une recherche échoue, donc après une coupure du tunnel il peut afficher une ancienne valeur. La dernière ligne vérifie l'IPv6 : une erreur ou une adresse VPN convient, votre adresse IPv6 personnelle est une fuite (un moteur annonce en IPv6 dès qu'une route existe, sauf avec enable_ipv6 = false, voir Réseau). GET /api/network/engines?refresh=1 donne la même chose par moteur, et GET /api/port-forward indique par moteur si des pairs entrants sont réellement arrivés.
Surveillez votre interface physique pendant qu'Hydranos tourne (remplacez eth0 par votre interface réseau local, en général br0 sous Unraid, où vous êtes déjà root et pouvez omettre sudo, et 203.0.113.5 par l'adresse de votre serveur VPN). Avec chaque moteur couvert, seuls les paquets du tunnel lui-même, le trafic local et les requêtes DNS pour les interfaces qu'Hydranos n'a pas créées doivent apparaître :
sudo tcpdump -ni eth0 'not host 203.0.113.5 and not port 22'
sudo tcpdump -ni eth0 host tracker.example.org # then click Reannounce on one torrentDemandez au tracker. La plupart des trackers affichent, sur votre profil ou dans la liste des pairs d'un torrent, l'adresse et le port annoncés par votre client. C'est ce qui compte pour les annonces : l'adresse du VPN, et le port redirigé pour le moteur qui l'a. Pour tester l'entrant, pointez n'importe quel testeur de port externe sur cette adresse et ce port pendant qu'Hydranos tourne.
Si quelque chose sort par où il ne faut pas, voir Dépannage ; la liste complète des lacunes est sur Limites connues de la 4.4. Pour choisir entre une instance, plus de moteurs ou plusieurs machines, voir Topologies de déploiement.