web-dev-qa-db-fra.com

Pourquoi nginx répond-il à un nom de domaine?

J'ai installé Nginx avec une application Ruby/Sinatra et tout va bien. Cependant, j'essaie maintenant de faire fonctionner une deuxième application à partir du même serveur et j'ai remarqué quelque chose de bizarre. D'abord, voici mon nginx.conf:

pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;

events {
  worker_connections 1024;
  accept_mutex off;
}

http {
  default_type application/octet-stream;
  access_log /tmp/nginx.access.log combined;

  sendfile on;
  tcp_nopush on;
  tcp_nodelay off;

  gzip on;
  gzip_http_version 1.0;
  gzip_proxied any;
  gzip_min_length 500;
  gzip_disable "MSIE [1-6]\.";
  gzip_types text/plain text/xml text/css
             text/comma-separated-values
             text/javascript application/x-javascript
             application/atom+xml;

  upstream app {
    server unix:/var/www/app/tmp/sockets/Unicorn.sock fail_timeout=0;
  }

  server {
    listen 80;
    client_max_body_size 4G;
    server_name FAKE.COM;

    keepalive_timeout 5;

    root /var/www/app/public;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_Host;
      proxy_redirect off;

      if (!-f $request_filename) {
        proxy_pass http://app;
        break;
      }
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /var/www/app/public;
    }
  }
}
                                                          68,0-1        B

Remarquez comment server_name est réglé sur FAKE.COM et pourtant, le serveur répond à tous les hôtes qui le rencontrent via d’autres noms de domaine. Comment puis-je faire en sorte que ce serveur ne réponde qu'aux demandes de FAKE.COM?

131
Martin

Le premier bloc de serveur dans nginx config est la valeur par défaut pour toutes les demandes qui arrivent sur le serveur pour lequel il n'y a pas de bloc de serveur spécifique.

Donc, dans votre configuration, en supposant que votre domaine réel est REAL.COM, lorsqu'un utilisateur le saisira, il sera résolu sur votre serveur et, comme il n'y a pas de bloc serveur pour cette configuration, le bloc serveur pour FAKE.COM, étant le premier bloc de serveur (seul le bloc de serveur dans votre cas), traitera cette demande.

C'est la raison pour laquelle les configurations Nginx appropriées ont un bloc serveur spécifique pour les valeurs par défaut avant d'en suivre d'autres pour des domaines spécifiques.

# Default server
server {
    return 404;
}

server {
    server_name domain_1;
    [...]
}

server {
    server_name domain_2;
    [...]
}

etc

** MODIFIER **

Il semble que certains utilisateurs soient un peu déconcertés par cet exemple et pensent qu'il se limite à un seul fichier de configuration, etc.

Veuillez noter que ce qui précède est un exemple simple à développer pour le PO, selon vos besoins.

Personnellement, j'utilise des fichiers de configuration vhost distincts avec ceci (CentOS/RHEL):

http {
    [...]
    # Default server
    server {
        return 404;
    }
    # Other servers
    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/ contiendra domain_1.conf, domain_2.conf ... domain_n.conf qui sera inclus après le bloc serveur dans le fichier principal nginx.conf qui sera toujours le premier et sera toujours la valeur par défaut à moins qu'il ne soit écrasé la directive default_server ailleurs.

L'ordre alphabétique des noms de fichiers des fichiers de configuration pour les autres serveurs devient sans importance dans ce cas.

De plus, cette disposition offre une grande flexibilité dans la mesure où il est possible de définir plusieurs valeurs par défaut.

Dans mon cas particulier, Apache écoute sur le port 8080 sur l'interface interne uniquement et je proxy PHP et les scripts Perl vers Apache.

Cependant, je lance deux applications distinctes qui renvoient toutes deux des liens avec ": 8080" dans le fichier HTML de sortie attaché car ils détectent qu'Apache ne s'exécute pas sur le port 80 standard et essaient de "m'aider".

Cela pose un problème car les liens deviennent invalides car Apache ne peut pas être atteint à partir de l'interface externe et les liens doivent pointer vers le port 80.

Je résous ce problème en créant un serveur par défaut pour le port 8080 afin de rediriger ces demandes.

http {
    [...]
    # Default server block for undefined domains
    server {
        listen 80;
        return 404;
    }
    # Default server block to redirect Port 8080 for all domains
    server {
        listen my.external.ip.addr:8080;
        return 301 http://$Host$request_uri;
    }
    # Other servers
    include /etc/nginx/conf.d/*.conf;
}

Comme rien dans les blocs de serveur habituels n'écoute sur le port 8080, le bloc de serveur par défaut de redirection gère ces demandes de manière transparente en raison de sa position dans nginx.conf.

En fait, j'ai quatre de ces blocs de serveur et ceci est un cas d'utilisation simplifié.

188
Dayo

Vous devriez avoir un serveur par défaut pour catch-all, vous pouvez retourner 404 ou mieux de ne pas répondre du tout (économisera de la bande passante) en retournant 444 _ qui est une réponse HTTP spécifique à nginx qui ferme simplement la connexion et ne renvoie rien

server {
    listen       80  default_server;
    server_name  _; # some invalid name that won't match anything
    return       444;
}
57
iTech

J'ai été incapable de résoudre mon problème avec l'une des autres réponses. J'ai résolu le problème en vérifiant si l'hôte correspond et en renvoyant un 403 si ce n'est pas le cas. (J'ai eu un site Web aléatoire pointant vers le contenu de mes serveurs Web. Je devine au rang de recherche de Hijack)

server {
    listen 443;
    server_name example.com;

    if ($Host != "example.com") {
        return 403;
    }

    ...
}
32
Matt Carrier

Il existe plusieurs façons de spécifier le serveur par défaut.

Premier moyen - Spécifiez le serveur par défaut en premier dans la liste, si vous conservez les configurations de serveur dans un seul fichier de configuration, comme le montre Dayo ci-dessus.

Deuxième manière (mieux) Plus souple - fournissez le paramètre default_server Pour l'instruction listen, par exemple:

server {
    listen  *:80 default_server;
    root /www/project/public/;
}

Plus d'informations ici: Nginx doc/Listen

Cette méthode est donc plus utile lorsque vous conservez les configurations de serveur dans des fichiers séparés et que vous ne souhaitez pas nommer ces fichiers par ordre alphabétique.

26
Pavel

Pour répondre à votre question, nginx choisit le premier serveur s'il n'y a pas de correspondance. Voir documentation :

Si sa valeur ne correspond à aucun nom de serveur ou si la demande ne contient pas du tout ce champ d'en-tête, nginx acheminera la demande au serveur par défaut pour ce port. Dans la configuration ci-dessus, le serveur par défaut est le premier ...

Maintenant, si vous voulez avoir un serveur fourre-tout par défaut qui, par exemple, répond avec 404 à toutes les demandes, voici comment procéder:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>
    ssl_certificate_key <path to key>
    return 404;
}

Notez que vous devez spécifier certificate/key (qui peut être auto-signé), sinon toutes les connexions SSL échoueront car nginx essaiera d’accepter la connexion à l’aide de ce serveur par défaut et ne trouvera pas de certificat/clé.

18
AndreyT

Petit commentaire à répondre:

si vous avez plusieurs hôtes virtuels sur plusieurs adresses IP dans plusieurs fichiers de configuration dans sites-available /, le domaine "par défaut" pour IP sera extrait du premier fichier par ordre alphabétique.

Et comme Pavel l'a dit, il existe un argument "default_server" pour la directive "listen" http://nginx.org/en/docs/http/ngx_http_core_module.html#listen

8
Oleg Neumyvakin