Relayd : Gestion des entêtes pour httpd

Article publié, le et modifié le
5 minute(s) de lecture

Cet article contient 979 mots.
Source brute de l'article : MD

Description

OpenBSD intègre par défaut dans le système de base, depuis 5.7 :

  • un serveur web, nommé httpd - que j’ai présenté plus ou moins succinctement ici

  • un serveur relay, nommé relayd

  • Site web : https://bsd.plumbing/

  • OpenBSD : 6.6, 6.7


Le problème est que le serveur httpd n’est pas capable de gérer les entêtes HTTP (en anglais : header ), et que l’auteur ne le veut pas.

Nous passons donc le relais au serveur relayd qui lui est capable de les gérer - par contre, il le fait de manière globale, çad non spécifique à un domaine en particulier -

Configuration

Étant donné que relayd est en frontal d’httpd, nous allons modifier la configuration des deux fichiers de configuration relatifs.

  • relayd va recevoir tout le traffic à destination des ports web, 80, voire 443, si TLS et le rediriger en local sur les ports correspondant. Bien sûr, il est possible d’agir sur chacune des piles réseaux des protocoles IPv4 et IPv6.
  • quant à lui, httpd ne fera qu’interroger la boucle locale sur les ports redirigés.

Ne pas oublier de redémarrer les services correspondants après modifier de la configuration !

httpd

  • Le fichier de configuration est /etc/httpd.conf, par défaut.

Dans le contexte server, il y a deux, trois modifications importantes à faire :

  • l’option d’écoute listen on doit écouter localhost - cf : listen on
  • l’option de journalisation log est à modifier pour que le style soit paramétré sur forwarder - cf : style
Info

Seule l’entête HSTS est géré différement :

httpd: HSTS

L’entête HSTS se modifie, non pas en déclarant une entête, comme pour les autres, mais en utilisant tout simplement l’option hsts (cf : hsts).

Elle se gère bien sûr dans le contexte de protocole HTTPS , via TLS .

Pour l’instant, nous n’aborderons pas ce sujet ; d’autant que je fais les présentations dans mon article de présentation d'httpd .

httpd: exemple

Code : httpd

server "domain.tld" {

    listen on 127.0.0.1 port 80
    listen on ::1 port 80 

    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2        
    }

    location "/" {
        directory index index.html
    } 

    log {
        access "domain.tld/access.log"
        error  "domain.tld/errors.log"
        style forwarded
    }

    root "/htdocs/domain.tld/www"
}

httpd: log

Voici un exemple de log :

domain.tld 127.0.0.1 - - [06/May/2020:04:08:51 +0200] "GET / HTTP/1.1" 200 0 "" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" 66.249.79.202 -
domain.tld 127.0.0.1 - - [06/May/2020:09:48:36 +0200] "GET /robots.txt HTTP/1.1" 200 0 "" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" 5.196.87.174 -
domain.tld 127.0.0.1 - - [06/May/2020:10:29:29 +0200] "GET / HTTP/1.1" 200 0 "" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" 54.36.148.31 -

Nous remarquons bien que l’adresse IP du client est précisé en fin de ligne.
C’est ce que permet le paramètre de style de journal forwarder.

relayd

  • Le fichier de configuration est /etc/relayd.conf, par défaut.

Dans les faits :

  • Nous déclarons un protocole http en lui donnant un nom - le nom importe peu, mais est réutilisé plus tard, dans le contexte des déclarations de relais.
  • les filtres de correspondance match pour créer les réponses d’entêtes header.
    • les deux premières déclarations sont nécessaires pour capturer les valeurs serveurs suivantes afin de les rediriger correctement :
      • $SERVER_ADDR:$SERVER_PORT pour l’option X-Forwarded-By,
      • $REMOTE_ADDR pour l’option X-Forwarded-For.
  • puis nous relaierons en paramétrant, dans les déclarations relay correspondantes :
    • l’option d’écoute listen, sur l’adresse IP public et le port www et,
    • nous ciblons le protocole http nommé afin que les règles sur les entêtes soient appliquées dans chacun des contextes de relais, et,
    • redirigerons à l’aide de l’option forward vers l’interface de bouclage local, et le port désiré, correspondant à celui sur lequel écoute httpd.

relayd: Httpoxy

Certains des plus attentifs remarqueront dans l’exemple ci-dessous la déclaration de l’entête suivante :

match request header remove "Proxy"

Celle-ci est utile pour lutter contre la faille Httpoxy qui affecte les applications CGI, PHP, dans le contexte d’une connexion HTTP .

C’est reconnue comme étant la meilleure façon de bloquer cette faille.
L’autre angle de protection efficace est de fournir des connexions HTTPS , qui apparemment ne sont pas assujetties à cette faille.

relayd: exemple

Code : relayd

ip4 = "ipv4_public_address"
ip6 = "ipv6_public_address"

http protocol "hw" {
    match request header set "X-Forwarded-By"   value "$SERVER_ADDR:$SERVER_PORT"    
    match request header set "X-Forwarded-For"  value "$REMOTE_ADDR"

    match request header remove "Proxy"

    match response header set "Cache-Control"           value "max-age=1814400"
#   match response header set "Content-Security-Policy" value "default-src 'self'"
    match response header set "Feature-Policy"          value "fullscreen 'self'; accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"
    match response header set "Frame-Options"           value "SAMEORIGIN"
    match response header set "Referrer-Policy"         value "strict-origin"
    match response header set "Server"                  value "OpenBSD Relayd+httpd"
    
    match response header set "X-Content-Type-Options" value "nosniff"
    match response header set "X-Download-Options"     value "noopen"
    match response header set "X-Frame-Options"        value "SAMEORIGIN"
    match response header set "X-Powered-By"           value "!"
    match response header set "X-Robots-Tag"           value "index, nofollow"
    match response header set "X-Xss-Protection"       value "1; mode=block"
    
    tcp { nodelay, sack, socket buffer 65536, backlog 100 }
    
    pass
}

relay "www" {
    listen on $ip4 port 80
    protocol hw
    forward to 127.0.0.1 port 80
}

relay "www6" {
    listen on $ip6 port 80
    protocol hw
    forward to ::1 port 80
}

Documentations

Manpages

Autres documentations