Catégorie : DNS

19 juillet 2026 /

Dans l’article précédent, nous avons monté une pile Docker gluetun + Transmission sur un NAS Synology : les torrents passent par le VPN, et l’interface web répond en HTTP sur le port 9091. Ça fonctionne, mais en HTTP clair — acceptable sur le réseau local, rédhibitoire dès qu’on veut y accéder depuis l’extérieur.

Ce second article ajoute la couche qui manque : un accès HTTPS avec un vrai certificat Let’s Encrypt, valable aussi bien en local que depuis Internet, du type https://nas.example.com:9092. Le tout sans jamais exposer le port 80 du NAS, grâce à la validation DNS.

Vue d’ensemble

Quatre briques :

  1. Un nom DNS qui pointe vers votre IP publique (ici nas.example.com, zone hébergée chez OVH) ;
  2. Un certificat Let’s Encrypt obtenu par acme.sh en validation DNS-01 via l’API OVH, et importé automatiquement dans DSM ;
  3. Le reverse proxy intégré à DSM (nginx), qui termine le HTTPS sur le port 9092 et retransmet en clair vers Transmission sur localhost:9091 ;
  4. Une redirection de port sur la box pour l’accès externe.
Internet ──► box (9092) ──► NAS:9092 ── nginx DSM (HTTPS, certificat) ──► localhost:9091 ──► Transmission

Transmission lui-même ne sait rien de tout ça : il continue d’écouter en HTTP sur 9091. C’est le reverse proxy qui porte le chiffrement — et le même mécanisme resservira pour n’importe quel autre service web du NAS.

Pourquoi la validation DNS-01 plutôt que HTTP-01 ?

Pour délivrer un certificat, Let’s Encrypt doit vérifier que vous contrôlez le nom demandé. Deux méthodes :

  • HTTP-01 : Let’s Encrypt vient chercher un fichier sur http://nas.example.com/.well-known/... → il faut exposer le port 80 du NAS sur Internet. Souvent impossible (le port 80 de la box est déjà pris ou translaté vers autre chose) et jamais souhaitable ;
  • DNS-01 : acme.sh dépose un enregistrement TXT temporaire dans la zone DNS via l’API du registrar, Let’s Encrypt le lit, le certificat est délivré. Aucun port à ouvrir, et ça permet même les certificats wildcard.

DNS-01 est donc la bonne méthode dès que votre registrar a une API — c’est le cas d’OVH, et acme.sh sait parler à des dizaines d’autres (Cloudflare, Gandi, etc.).

1. Le nom DNS

Dans la zone OVH, créez un enregistrement A pointant vers votre IP publique :

nas.example.com.    A    203.0.113.10

Si votre IP publique est dynamique, utilisez le DynHost d’OVH (ou le client DDNS de DSM) pour maintenir l’enregistrement à jour. Vérifiez avant de continuer :

nslookup nas.example.com    # doit renvoyer votre IP publique

2. Installer acme.sh sur le NAS

acme.sh est un client ACME en pur shell, sans dépendance — parfait pour un Synology. Un point important : installez-le sur un volume de données (/volume1), pas dans /root. Le home de root vit sur la partition système, reconstruite lors des grosses mises à jour DSM ; un volume de données, lui, survit à tout.

cd /volume1/docker        # ou tout autre dossier de /volume1
wget -O acme.sh.tar.gz https://github.com/acmesh-official/acme.sh/archive/master.tar.gz
tar xzf acme.sh.tar.gz && cd acme.sh-master
./acme.sh --install --home /volume1/docker/acme.sh --nocron

Le --nocron est volontaire : le cron d’acme.sh a besoin d’un environnement particulier sur Synology, on le créera à la main à l’étape 5.

⚠️ Piège Synology : /tmp est monté noexec. Si un script refuse de s’exécuter depuis /tmp avec « Permission denied », lancez-le via sh script.sh ou depuis /volume1.

3. Le jeton API OVH

Rendez-vous sur https://eu.api.ovh.com/createToken/ et créez un jeton avec uniquement les droits nécessaires à la gestion de zone :

GET     /domain/zone/*
PUT     /domain/zone/*
POST    /domain/zone/*
DELETE  /domain/zone/*

Principe du moindre privilège : ce jeton ne peut toucher qu’aux zones DNS, pas au reste de votre compte OVH. Vous obtenez trois valeurs (application key, application secret, consumer key) à exporter avant la première émission :

export OVH_END_POINT=ovh-eu
export OVH_AK=votre_application_key
export OVH_AS=votre_application_secret
export OVH_CK=votre_consumer_key

acme.sh les enregistre dans sa configuration (account.conf) au premier usage — les exports ne servent qu’une fois. Ne mettez jamais ces valeurs dans un script versionné.

4. Émettre le certificat et l’importer dans DSM

Émission (validation DNS-01 chez OVH, CA Let’s Encrypt) :

/volume1/docker/acme.sh/acme.sh --home /volume1/docker/acme.sh \
  --issue --dns dns_ovh \
  -d nas.example.com \
  --server letsencrypt

Deux à trois minutes plus tard (le temps de la propagation du TXT), le certificat est dans /volume1/docker/acme.sh/nas.example.com_ecc/. Reste à l’importer dans DSM — et c’est là qu’acme.sh brille : son hook de déploiement synology_dsm utilise l’API locale de DSM pour installer le certificat proprement, comme si vous l’aviez fait dans l’interface :

export SYNO_USE_TEMP_ADMIN=1
export SYNO_CREATE=1
export PATH=/usr/syno/sbin:/usr/syno/bin:$PATH
/volume1/docker/acme.sh/acme.sh --home /volume1/docker/acme.sh \
  --deploy -d nas.example.com \
  --deploy-hook synology_dsm

Trois subtilités qui font tout marcher :

  • SYNO_USE_TEMP_ADMIN=1 : le hook crée un compte administrateur temporaire le temps du déploiement, puis le supprime. Pas besoin de stocker votre mot de passe DSM dans un fichier ;
  • SYNO_CREATE=1 : indispensable au premier déploiement. Par défaut, le hook cherche un certificat existant à remplacer dans DSM ; s’il n’y en a pas encore, il échoue avec Unable to find certificate: and $SYNO_CREATE is not set. Cette variable l’autorise à créer l’entrée ;
  • le PATH doit inclure /usr/syno/sbin et /usr/syno/bin : le hook s’appuie sur les commandes Synology (synouser…) qui n’y sont pas par défaut sous sudo. Sans ça, échec silencieux.

Le certificat apparaît alors dans DSM → Panneau de configuration → Sécurité → Certificat.

5. Le renouvellement automatique

Un certificat Let’s Encrypt dure 90 jours ; acme.sh renouvelle à 60 jours, à condition d’être lancé régulièrement. Ajoutez cette ligne dans /etc/crontab du NAS (en root) — avec l’environnement complet, cron étant encore plus pauvre en PATH qu’un shell sudo :

0  3  *  *  *  root  PATH=/usr/syno/sbin:/usr/syno/bin:/usr/bin:/bin HOME=/volume1/docker/acme.sh SYNO_USE_TEMP_ADMIN=1 /volume1/docker/acme.sh/acme.sh --home /volume1/docker/acme.sh --cron

Tous les jours à 3 h, acme.sh vérifie l’échéance ; le jour venu, il renouvelle en DNS-01 et redéploie dans DSM via le hook, sans aucune intervention. Testez le circuit complet une fois :

/volume1/docker/acme.sh/acme.sh --home /volume1/docker/acme.sh --cron --force

6. Le reverse proxy DSM

DSM embarque nginx et une interface pour le piloter : Panneau de configuration → Portail de connexion → Avancé → Proxy inversé. Créez une règle :

Source (ce que voit le client) Destination (le service réel)
Protocole HTTPS HTTP
Nom d’hôte nas.example.com localhost
Port 9092 9091

À la création de la règle, DSM lui associe automatiquement le certificat par défaut du NAS (souvent l’auto-signé Synology) — d’où le cadenas barré si vous testez tout de suite. Associez donc le bon certificat à la règle : Sécurité → Certificat → Paramètres, et en face du service nas.example.com:9092, sélectionnez le certificat fraîchement importé.

⚠️ Résistez au bouton « Définir comme certificat par défaut » : il réassigne d’un coup tous les services de DSM au même certificat, y compris ceux qui ne doivent pas changer (QuickConnect utilise le sien, par exemple), et peut laisser nginx dans un état incohérent — vécu : connexions Secure SignIn mobiles cassées jusqu’à re-toucher une liaison de certificat pour forcer DSM à régénérer sa configuration. Assignez service par service, c’est deux clics de plus et zéro mauvaise surprise.

7. Le cas particulier d’un service derrière gluetun

Si le service cible est dans un conteneur attaché à gluetun (notre Transmission, donc), le reverse proxy renverra une erreur 502 avec la configuration gluetun par défaut : son pare-feu bloque les flux venant de l’hôte en dehors du tunnel. La solution est dans le compose du premier article :

- FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24,172.18.0.0/16

Cette ligne autorise gluetun à répondre au réseau local (et au réseau Docker du projet) hors tunnel — uniquement ces destinations-là, le reste du trafic continue de passer par le VPN.

8. L’accès externe

Dernière brique : sur la box/routeur, redirigez le port 9092 (TCP) vers l’IP du NAS, port 9092. Et c’est tout — surtout, ne redirigez pas le 9091 : le seul chemin depuis Internet doit être celui qui passe par le HTTPS du reverse proxy.

Résultat : https://nas.example.com:9092 fonctionne du canapé comme de l’autre bout du monde, avec un cadenas valide, l’authentification de Transmission par-dessus, et un renouvellement de certificat entièrement automatique.

Récapitulatif des pièges

Piège Symptôme Solution
HTTP-01 derrière une box Validation impossible, port 80 pris/translaté Validation DNS-01 via l’API du registrar
acme.sh dans /root Installation perdue après grosse mise à jour DSM Installer sur /volume1
/tmp monté noexec « Permission denied » sur un script pourtant exécutable Lancer via sh script.sh ou depuis /volume1
PATH sans /usr/syno/sbin Le hook synology_dsm échoue (sudo et cron) Préfixer PATH dans la commande et le crontab
Mot de passe DSM dans la conf Secret stocké en clair SYNO_USE_TEMP_ADMIN=1 (admin temporaire jetable)
Premier déploiement du certificat Unable to find certificate SYNO_CREATE=1 (le hook ne crée pas d’entrée par défaut)
« Définir comme certificat par défaut » Tous les services réassignés, état nginx incohérent Assigner le certificat service par service
Service derrière gluetun Reverse proxy en erreur 502 FIREWALL_OUTBOUND_SUBNETS dans le compose
Port 9091 redirigé sur la box Interface accessible en HTTP clair depuis Internet N’exposer que le 9092 (HTTPS)

Conclusion

Avec le premier article, les torrents passaient par le VPN. Avec celui-ci, l’interface est servie en HTTPS avec un certificat valide, renouvelé tout seul, accessible de l’extérieur sans exposer un seul octet en clair. Le schéma reverse proxy + certificat est réutilisable à l’identique pour tous les services web du NAS : une règle de proxy inversé et une liaison de certificat par service, et c’est tout le NAS qui parle proprement HTTPS.

14 novembre 2016 /

Le Domain Name System (ou DNS, système de noms de domaine) est un service permettant de traduire un nom de domaine en informations de plusieurs types qui y sont associées, notamment en adresses IP de la machine portant ce nom.

BIND (pour Berkeley Internet Name Daemon, ou parfois Berkeley Internet Name Domain) est le serveur DNS le plus utilisé sur Internet, spécialement sur les systèmes de type UNIX et est devenu de facto un standard. La première version de BIND a été conçue par quatre étudiants diplômés de l’Université de Californie (Berkeley) sur la base du système d’exploitation BSD 4.3

Nous allons installer Bind sur un serveur CentOS 6.5 (configuration également testée sur un CentOS7 avec succès) nommé dns, ayant pour adresse IP 10.148.14.36 et pour domaine starmate.fr.

Installation:

yum -y install bind bind-utils

On modifie la configuration DNS du système pour que les requêtes DNS se fassent désormais vers le DNS local, pour cela on modifie le paramètre « nameserver » du fichier resolv.conf:

vi /etc/resolv.conf

search starmate.fr
nameserver 127.0.0.1
nameserver 10.148.14.36

On va maintenant configurer la zone.
La mise en place d’une zone, aussi appelé nom de domaine, se fait par la création d’un fichier dans /var/named/.
Ce fichier contiendra l’ensemble des enregistrements DNS du domaine. Ce sont ces informations qui seront envoyées lors d’une requête DNS. Ils donnent notamment les adresses IP de plusieurs services, les IP des sous-domaines, machines, le TTL, etc…

Pour une zone starmate.fr :

vi /var/named/starmate.fr.db

Et on mets ça dedans:

$TTL 604800
@ IN SOA dns.starmate.fr. root.starmate.fr. (
2 ; Serial
3600 ; Refresh [1h]
600 ; Retry [10m]
86400 ; Expire [1j]
600 ) ; Negative Cache TTL [1h]
;
@ IN NS dns.starmate.fr.
dns.starmate.fr. IN A 10.148.14.36

On créer la configuration de la zone inversé:

vi /var/named/10.148.14.zone.db

Et on y met ca:

$TTL 604800
@ IN SOA dns.starmate.fr. root.starmate.fr. (
2 ; Serial
3600 ; Refresh [1h]
600 ; Retry [10m]
86400 ; Expire [1j]
600 ) ; Negative Cache TTL [1h]
;
@               IN      NS      dns.starmate.fr.
36              IN      PTR     dns.starmate.fr.

il faut maintenant inclure cette zone dans la liste des domaines de bind

On va commencer par sauvegarder le fichier de configuration initial:

cp -p /etc/named.conf /etc/named.conf.sav

On va vider le fichier:

> /etc/named.conf

Maintenant le fichier est sauvegardé et vidé de son contenu, on y ajoute ça:

vi /etc/named.conf

options
{
directory "/var/named"; // "Working" directory
dump-file "data/cache_dump.db";
statistics-file "data/named_stats.txt";
memstatistics-file "data/named_mem_stats.txt";

listen-on port 53 { any; };
//listen-on port 53 { 127.0.0.1; };

listen-on-v6 port 53 { any; };
//listen-on-v6 port 53 { ::1; };

allow-query { any; };
allow-query-cache { any; };

recursion yes;

};

logging
{
channel default_debug {
file "data/named.run";
severity dynamic;
};
};

view "internal"
{
match-clients { localnets; };
recursion yes;

zone "." IN {
type hint;
file "/var/named/named.ca";
};

include "/etc/named.rfc1912.zones";

zone "starmate.fr" {
type master;
file "starmate.fr.db";
};

zone "14.148.10.in-addr.arpa" {
type master;
file "10.148.14.zone.db";
};
};

On vérifie que l’on a pas fait d’erreur de syntaxe:

named-checkzone starmate.fr /var/named/starmate.fr.db
named-checkzone starmate.fr /var/named/10.148.14.zone.db

Si pas d’erreur, on redémarre le service:

service named restart

Pour CentOS6, voici les règles iptables pour ouvrir le port DNS qu’il faut ajouter dans /etc/sysconfig/iptables :

vi /etc/sysconfig/iptables

-A INPUT -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 53 -j ACCEPT

Ou via la commande iptables directement:

iptables -t filter -A OUTPUT -p tcp –dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -p udp –dport 53 -j ACCEPT
iptables -t filter -A INPUT -p tcp –dport 53 -j ACCEPT
iptables -t filter -A INPUT -p udp –dport 53 -j ACCEPT

Pour CentOS7, le mieux est de passer par la commande firewall-cmd:

firewall-cmd --permanent --add-port=53/tcp
firewall-cmd --permanent --add-port=53/udp
firewall-cmd --reload

Vérification de la résolution depuis un autre poste:

dig @10.148.14.36 dns.starmate.fr +short

10.148.14.36

Dig nous a bien retourné l’adresse IP correspondante au nom dns, « dns.starmate.fr »

Vérification de la résolution inversée depuis un autre poste:

dig @10.148.14.36 -x 10.148.14.36 +short

dns.starmate.fr.

Dig nous a bien retourné le nom DNS de la machine ayant l’adresse IP, « 10.148.14.36 »