Pourquoi (aujourd'hui) retourner 444 n'est pas toujours utile

Le serveur Web Nginx possède un merveilleux code de réponse 444 qui "ferme" la connexion sans envoyer de données. Cette fonctionnalité est très utile pour filtrer le trafic parasite - si nous sommes sûrs que le client n'est pas valide selon certains critères, il n'est pas nécessaire de le notifier, par exemple, avec la réponse 403e. Il est plus efficace d'arrêter simplement le transfert de données, ce qui, souvent, peut réduire considérablement la charge sur le serveur.

Les recommandations pour l'utilisation de ces réponses se trouvent partout dans les instructions sur le blocage des clics sur les liens des sites populaires et le spam de référence, la protection contre les DDoS, etc.

Et, en général, au fil des ans, ces conseils pourraient être utilisés presque sans regarder, mais ... les navigateurs modernes ne s'arrêtent pas et nous présentent périodiquement de nouvelles surprises.

Programme obligatoire
Serveur:

$ uname -orm FreeBSD 11.1-STABLE amd64 

 $ nginx -v nginx version: nginx/1.15.0 

Client:

 >ver Microsoft Windows [Version 10.0.15063] 

Google Chrome 67.0.3396.99 (version officielle), (64 bits)
Firefox Quantum 61.0 (64 bits)

Je n'ai pris pour expérience que les navigateurs Chrome et Firefox. Non pas parce que les autres sont sans péché, juste le comportement décrit ci-dessous était assez stable dans les deux.

Donc, nous avons un site Web et nous voulons restreindre l'accès à l'emplacement sans aucune condition et sans transmettre de données:

 server { ... location = /code/444 { return 444; } ... } 

En attente:

  • le navigateur enverra une demande;
  • le serveur reçoit une demande, ferme la connexion et écrit une ligne avec le code 444 dans le journal;
  • ne reçoit pas de données, le navigateur affichera une erreur et cessera de communiquer avec le serveur.

Pour plus de clarté, nous affichons nos attentes avec la ligne de log Nginx:

 18.12.12.29 - - [28/Jun/2018:11:50:10 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 

Réalité Chrome:

 18.12.12.29 - - [28/Jun/2018:11:50:10 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 18.12.12.29 - - [28/Jun/2018:11:50:10 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 18.12.12.29 - - [28/Jun/2018:11:50:15 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 18.12.12.29 - - [28/Jun/2018:11:52:04 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 

Chrome a envoyé une demande, n'a pas reçu de réponse, a immédiatement envoyé une autre demande, après quoi il a commencé à vérifier périodiquement la disponibilité du site.

Firefox Reality:

 18.12.12.29 - - [28/Jun/2018:12:34:38 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:38 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:38 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:38 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:38 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:39 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:39 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:39 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:39 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:39 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:39 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:40 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:40 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:40 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:40 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:40 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:41 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:41 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:41 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:34:41 +0000] "GET /code/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 

Firefox a décidé de ne pas être mesquin et a immédiatement envoyé 20 demandes (parfois 10). Mais alors, il ne fait aucun "contrôle".

En même temps, il signale dans le débogueur comme pour une requête:

Cap de spoiler
image

Ainsi, en attendant de recevoir une seule demande du client, en fait, nous recevons 3 à 20 demandes. En plus des appels qui nous sont complètement inutiles, il y a un risque d'alimenter un tel journal, par exemple, vers un script anti-DDoS et de bloquer cette ip. Et cela semblerait la moitié du problème, parce que nous lui avons déjà «donné» 444, c'est-à-dire que nous ne sommes pas désolés pour lui, mais cela peut se produire dans l'autre sens - nous montrerons au client ce que nous n'avions pas prévu du tout.

Modifiez la configuration:

 map $http_referer $code_if { "~*https://habr.com/post/415565/" 1; "http://tison.ru/ref" 1; default 0; } ... server { ... location = /code/444 { return 444; } ... location = /codeif/444 { if ( $code_if = 1 ) { return 444; } add_header "Content-Type" "text/html; charset=UTF-8" always; return 200 "Expected code 444"; } ... } 

Ici, nous avons interdit la livraison de contenu à tous les clients avec un référent "
https://habr.com/post/415565/ "lors du passage à la page tison.ru/codeif/444

En attente:

Connaissant les fonctionnalités déjà décrites ci-dessus, nous supposons que les navigateurs feront plus d'une demande, mais ils ne recevront pas la 200e réponse du serveur.

Sous la forme d'un journal, encore une fois, nous attendons une ou plusieurs lignes du formulaire:

 18.12.12.29 - - [28/Jun/2018:12:52:02 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 

Lors du débogage dans la console, tout fonctionne comme prévu. Le serveur a fermé la connexion et nous n'avons reçu aucun contenu:

 $ curl --referer "https://habr.com/post/415565/" tison.ru/codeif/444 curl: (52) Empty reply from server 

Eh bien, la réalité du navigateur.

Chrome:

 18.12.12.29 - - [28/Jun/2018:12:58:12 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 18.12.12.29 - - [28/Jun/2018:12:58:12 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 18.12.12.29 - - [28/Jun/2018:12:58:13 +0000] "GET /codeif/444 HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 

Firefox:

 18.12.12.29 - - [28/Jun/2018:12:56:29 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:29 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:29 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:29 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:30 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:30 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:30 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:30 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:30 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:30 +0000] "GET /codeif/444 HTTP/1.1" 444 0 "http://tison.ru/ref" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:31 +0000] "GET /codeif/444 HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 18.12.12.29 - - [28/Jun/2018:12:56:31 +0000] "GET /favicon.ico HTTP/1.1" 200 6782 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" 

Après avoir fait plusieurs demandes de demandes «honnêtes», les deux navigateurs ont abandonné le référent et affiché calmement la page bloquée. Firefox, cependant, ne le fait pas toujours. Sur mes tests, ~ dans 15% des demandes, ce qui aide encore plus à l'analyse.

Ce comportement est observé depuis longtemps, mais quand exactement Chrome et Firefox sont passés à ce mode de fonctionnement, je ne peux pas le dire. Mais aussi, et combien de temps ce mode fonctionnera.

Aujourd'hui, l'utilisation de return 444 ne produira pas toujours les résultats escomptés. Eh bien, demain, nous serons heureux de voir plus de développeurs de navigateurs nous faire plaisir.

Source: https://habr.com/ru/post/fr415565/


All Articles