nginx가 도메인 이름에 응답하는 이유는 무엇입니까?


139

Ruby / Sinatra 앱으로 nginx를 실행 중이며 모두 잘 작동합니다. 그러나 현재 동일한 서버에서 두 번째 응용 프로그램을 실행하려고하는데 이상한 것이 있습니다. 먼저 내 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

서버가 다른 도메인 이름을 통해 해당 서버에 충돌하는 모든 호스트에 응답 하는 방법 server_nameFAKE.COM유의하십시오. 특정 서버가 요청에 대해서만 응답하도록하려면 FAKE.COM어떻게해야합니까?


listen fake.com | something.com:80 명령은하지 필터 server_name.
Alexei Martchenko가

답변:


202

nginx 설정의 첫 번째 서버 블록은 특정 서버 블록이없는 서버에 도달하는 모든 요청의 기본값입니다.

구성에서 실제 도메인이 REAL.COM이라고 가정하면 사용자가 입력하면 서버로 확인 되며이 설정에 대한 서버 블록이 없으므로 FAKE.COM의 서버 블록이 첫 번째입니다 서버 블록 (귀하의 경우 서버 블록 만)이 해당 요청을 처리합니다.

이것이 적절한 Nginx 설정이 특정 도메인에 대한 다른 서버를 따르기 전에 기본값에 대한 특정 서버 블록을 갖는 이유입니다.

# Default server
server {
    return 404;
}

server {
    server_name domain_1;
    [...]
}

server {
    server_name domain_2;
    [...]
}

기타

** 편집하다 **

일부 사용자는이 예제에서 약간 혼란스러워 단일 conf 파일 등으로 제한된다고 생각합니다.

위는 OP가 필요에 따라 개발하는 간단한 예입니다.

개인적으로 이와 같이 별도의 vhost conf 파일을 사용합니다 (CentOS / RHEL) :

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

/etc/nginx/conf.d/ domain_1.conf, domain_2.conf ... domain_n.conf를 포함합니다. domain_n.conf는 기본 nginx.conf 파일에서 서버 블록 다음에 포함되며, 항상 첫 번째이며 default_server로 재정의되지 않는 한 항상 기본값입니다. 다른 곳에서 지시하십시오.

이 경우 다른 서버에 대한 conf 파일의 파일 이름의 알파벳 순서는 관련이 없습니다.

또한이 배열은 여러 기본값을 정의 할 수 있다는 점에서 많은 유연성을 제공합니다.

필자의 경우에는 내부 인터페이스에서만 포트 8080을 수신하는 Apache를 사용하고 PHP 및 Perl 스크립트를 Apache로 프록시합니다.

그러나 Apache가 표준 포트 80에서 실행되고 있지 않다는 것을 감지하고 나를 "도움"시키려고 할 때 첨부 된 출력 HTML에서 ": 8080"으로 링크를 반환하는 두 개의 별도 응용 프로그램을 실행합니다.

외부 인터페이스에서 Apache에 도달 할 수없고 링크가 포트 80을 가리켜 야하므로 링크가 유효하지 않은 문제가 발생합니다.

이러한 요청을 리디렉션하기 위해 포트 8080에 대한 기본 서버를 생성하여이 문제를 해결합니다.

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;
}

일반 서버 블록의 포트 8080에서 수신 대기하는 것이 없으므로 리디렉션 기본 서버 블록은 nginx.conf에서의 위치 때문에 이러한 요청을 투명하게 처리합니다.

실제로 이러한 서버 블록 중 4 개가 있으며 이는 간단한 사용 사례입니다.


1
Nginx는 대소 문자 구분이 필요합니다. "서버"는 서버이고 "반환"은 반환해야합니다. 이 코드를 복사 할 때 약간의 문제가 해결되기를 바랍니다.
Capaj

2
정적은 Oleg Neumyvkin의 답변을 참조하십시오-사이트에 사용 가능한 구성 파일이 여러 개인 경우 첫 번째 파일의 알파벳 순서로 첫 번째 서버가 기본값입니다. 이것이 문제가 될 수 있습니다. 또한 많은 배포판에서 'nginx -t'를 실행하여 다시 시작하기 전에 구성을 테스트합니다. 다시 시작하지 못하게하는 오류가있을 수 있습니다.
jwhitlock

2
이것은 불완전하며 허용되는 답변이되어서는 안됩니다. 이것이 작동하려면 모든 청취 지시문에서 default_server를 제거해야합니다.
Ben

@ben 첫째, OP는 그의 문제 예제에 "default_server"를 가지고 있지 않으며 그 대답은 그 질문의 구체적인 내용에 맞추어 져 있습니다. 둘째, 첫 번째로 정의 된 서버를 기본값으로 설정하라는 지시를 따를 때 다른 사람이 별도의 서버 위치에 default_server를 정의하는 이유는 무엇입니까? 어쨌든, default_server가 구체적으로 정의 된 경우,이 Q / A 세트는 발생할 수있는 문제를 해결하기 위해 살펴 봐야하는 것이 아닙니다.
Dayo

1
@Dayo OP에서 게시 한 특정 구성을 해결 한 것이 맞습니다. 그러나 질문에 대한 완전한 대답을 얻으려면 default_server를 언급해야한다고 생각합니다. 응답을 읽고 default_server가 어떻게 그것을 방해하는지 알 수 없습니다. 일부 배포판은 default_server가 사용자에게 명확하지 않은 파일에 정의되어 배송되기 때문에 더욱 가능성이 높습니다.
Ben

61

catch-all 의 기본 서버가 있어야합니다 . 연결을 닫고 아무것도 반환하지 않는 nginx 특정 HTTP 응답을 404반환하여 전혀 응답하지 않기 위해 반환 하거나 더 나은 대역폭을 절약 할 수 있습니다444

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

nginx 1.8.0에서 나를 위해 일했습니다. server_name _;내가 Nginx에 대한 이전 버전하지 않았다, 그러나 그것은했다. 이제 최신 nginx 버전의 경우 server_name _;. 고마워
다니엘

해결되었습니다. 세미콜론을 잊어 버렸습니다; _;
user1201917

2
@ iTech : 어떤 이유로 든 모든 요청에 ​​대해 444를 반환합니다. 단서가 있습니까?
Divick

에 대한 444유용한 정보를 제공하고 오류 코드를 반환하는 것보다 훨씬 깨끗한 솔루션을 제공합니다.
qqilihq

1
인증서 / 키를 지정하는 것이 중요합니다. 그렇지 않으면 아래의 답변에서 @AndreyT가 지적한 것처럼 모든 SSL 연결이 일치하고 실패합니다.
Mark Fletcher

35

다른 답변으로 문제를 해결할 수 없습니다. 호스트가 일치하는지 확인하고 403을 반환하면 문제가 해결되었습니다. (웹 서버 콘텐츠를 가리키는 임의의 웹 사이트가 있습니다. 검색 순위를 가로 챌 것 같습니다)

server {
    listen 443;
    server_name example.com;

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

    ...
}


1
예를 들어 동등한 지시어가없는 변수를 테스트해야하는 경우 if를 사용하지 않는 경우가 있습니다.
에드워드

4
@Esolitos 말 그대로이 기사의 세 번째 줄은이 사용 사례가 괜찮다고 말합니다. 나는 조심해야 할 필요성을 이해하지만 합리적인 사용 사례에서 손가락을 흔들지 마십시오.
mpowered

내 의견으로는 가장 쉽고 가장 간결한 솔루션은 3 줄의 코드 만 필요하기 때문에 vhost 파일에 붙여 넣을 수 있으며 나중에 $ $ 만 변경하면됩니다.
아키토

28

귀하의 질문에 대답하기 위해-nginx는 일치하는 것이 없으면 첫 번째 서버를 선택합니다. 설명서를 참조하십시오 :

해당 값이 서버 이름과 일치하지 않거나 요청에이 헤더 필드가 전혀 없으면 nginx는이 포트의 기본 서버로 요청을 라우팅합니다. 위의 구성에서 기본 서버는 첫 번째 서버입니다.

이제 모든 요청에 ​​대해 404로 응답하는 기본 catch-all 서버를 원한다면 다음과 같이하십시오.

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;
}

인증서 / 키 (자체 서명 가능)를 지정해야합니다. 그렇지 않으면 nginx가이 default_server를 사용하여 연결을 수락하려고 시도하고 인증서 / 키를 찾지 못하므로 모든 SSL 연결이 실패합니다.


3
이 답변이 왜 목록에 있는지 잘 모르겠습니다. 이것은 길을 따라 반짝이는 것들에 방해받지 않고 질문에 대답하는 것입니다.
mmc

이것은 내가 www가 아닌 ​​www에서 www로 리디렉션하려고 할 때이 리디렉션 경로에 내 SSL 인증서를 포함시켜야한다는 문제를 해결하는 데 도움이되었습니다. 그렇지 않으면 다른 도메인의 기본 SSL 인증서를 가져 오는 것입니다.
endyourif

1
이것은 대부분의 구성에 가장 적합한 답변 인 것 같습니다 ... 요즘 누가 SSL없이 nginx를 사용하고 있는지 확실하지 않지만 이것이 SSL을 다루는 유일한 사람이라는 사실은 매우 중요합니다.
mpowered

server_name _;필요하지 않은 것 같습니다 .
Julien Salinas '

26

기본 서버를 지정하는 몇 가지 방법이 있습니다.

첫 번째 방법 -위에 표시된 Dayo와 같이 하나의 구성 파일에 서버 구성을 유지하는 경우 목록에서 기본 서버를 먼저 지정하십시오.

두 번째 방법 (더 나은) 더 융통성 있음- 명령에 대한 default_server매개 변수를 제공하십시오 ( listen예 :

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

자세한 내용은 여기 : Nginx doc / Listen

이 방법은 서버 구성을 별도의 파일로 유지하고 해당 파일의 이름을 사전 순으로 지정하지 않을 때 더 유용합니다.


3
이것이 정답이어야합니다. 허용 된 답변이 잘못되었습니다. 다른 서버를 구성에 추가해도 다른 서버가 기본 서버로 구성된 경우 문제를 해결하지 못합니다.
Ben

1
@Pavel 제공된 답변이 여러 개의 개별 호스트 파일에서 작동하지 않는 이유는 없습니다. 또한 이것으로 기본 서버가 항상 기본 nginx.conf 파일에 있다는 것을 알고 있으며 별도의 많은 vhost 파일 중 어느 것이 이것을 포함하는지 기억할 필요가 없습니다.
Dayo

ssl에 대해서도 443을 듣는 것을 잊지 마십시오 (아래 @AndreyT의 답변 참조).
콘스탄티노스

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.