snippet: tester les vhost avec curl et un header Host pour bypasser les DNS

Tags :Snippets
Publié le 1/12/2025

 On peut se connecter à un serveur via son IP (ou via un autre nom de domaine, si ce serveur gère plusieurs domaines) et lui passer un Host en headers. Ça permet de tester les réponses d’un serveur avant que ses DNS ne soient configurés1.

(Note : 87.98.135.245 c’est l’IP actuelle de notre proxy. Peut-être que ça aura changé quand vous lirez cette note !)

$ curl -v http://87.98.135.245 -H "Host: yama-corp.com"

*   Trying 87.98.135.245:80...
* Connected to 87.98.135.245 (87.98.135.245) port 80
* using HTTP/1.x
> GET / HTTP/1.1
> Host: yama-corp.com
> User-Agent: curl/8.14.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 308 Permanent Redirect
< Location: https://yama-corp.com/
< Server: Caddy
[...]

Ici, le serveur réponds avec une redirection vers le Host en HTTPS.

Je ne peux pas faire la même chose avec https://87.98.135.245, parce que Caddy n’a pas de certificat pour cette IP (ZeroSSL et Let’s Encrypt ne proposent pas de certs sur les IPs — c’est en général assez rare sur le web). Si on essaye, on aura une erreur SSL.

Par contre, on peut utiliser la même méthode pour ouvrir la connexion en HTTPS vers un certain domaine, mais demander au serveur un autre Host :

$ curl -v "https://yama-cms.com" -H "Host: yama-corp.com"

* Host yama-cms.com:443 was resolved.
* IPv6: (none)
* IPv4: 87.98.135.245
*   Trying 87.98.135.245:443...
* ALPN: curl offers h2,http/1.1
[...]
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=yama-cms.com
*  start date: Nov 15 17:28:06 2025 GMT
*  expire date: Feb 13 17:28:05 2026 GMT
*  subjectAltName: host "yama-cms.com" matched cert's "yama-cms.com"
*  issuer: C=US; O=Let's Encrypt; CN=E7
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to yama-cms.com (87.98.135.245) port 443
[...]

> GET / HTTP/2
> Host: yama-corp.com
> User-Agent: curl/8.14.1
> Accept: */*
> 

< HTTP/2 200 
< Server: Caddy
< content-type: text/html; charset=utf-8
[...]
<
<html class="dark" [...] <link rel="canonical" href="https://yama-corp.com/"><title>Chroniques tech sans concessions, parfois impertinentes ! | Yama Corp.</title>[...]

Ici, on peut voir que curl fait le handshake et vérifie le cert pour yama-cms.com, mais fait ensuite la requête HTTP avec un header Host: yama-corp.com.

(Pour plus d’infos sur comment lire les requêtes HTTP, on a ce super article dont je suis assez fier.)

On peut aussi faire la même chose en étant connecté en local : curl -v http://127.0.0.1 ..., ce qui permet de débugger certains containers plus facilement.

Ça dépend sûrement de comment le serveur vient résoudre ses « virtual hosts », mais en tout cas Caddy se comporte comme ça.

Footnotes

  1. Dans notre cas, on utilise la fonction « TLS-on-demand » de Caddy, ce qui permet de déférer l’obtention du certificat au moment de la première requête sur ce vhost (ce qui veut en général dire que la configuration DNS est faite et propagée).

Nos derniers articles