nginx : 정확히 이름이 지정된 SSL 서버 블록이 모든 SSL의 포괄 역할을하는 것을 방지하는 방법


17

가상 서버가 많은 웹 서버가 있습니다. 그중 하나만 SSL입니다. 문제는 SSL을 수신하는 catchall 서버 블록이 없기 때문에 다른 사이트에 대한 https 요청은 1 SSL 블록에 의해 제공된다는 것입니다.

기본적으로 내 구성은 다음과 같습니다.

# the catch all
server {
  listen 80 default;

  # I could add this, but since I have no default cert, I cannot enable SSL,
  # and this listen ends up doing nothing (apparently).
  # listen 443; 

  server_name _;
  # ...
}

# some server
server {
  listen 80;
  server_name server1.com;
  # ...
}

# some other server ...
server {
  listen 80;
  server_name server2.com;
  # ...
}

# ... and it's https equivalent
server {
  listen 443;
  ssl on;
  server_name server2.com;
  # ...
}

이제 443에 대한 기본 리스너가 없으므로 https 블록 으로 요청이 처리 https://server1.com됩니다 server2.com. 이에 대한 논리를 다음 server_name워드 프로세서.

일치하는 것이 없으면 구성 파일의 서버 {...} 블록이 다음 순서에 따라 사용됩니다.

  1. 일치하는 청취 지시문이있는 서버 블록 [default | default_server]
  2. 일치하는 청취 지시문이있는 첫 번째 서버 블록 (또는 암시 적 청취 80)

이 문제에 대해 선호되는 솔루션은 무엇입니까? 443에서 수신 대기하고 잘못된 요청을 처리 할 수 ​​있도록 모든 서버 포착 블록에 대해 더미 인증서를 설정해야합니까? 내가 알지 못하는 매개 변수가 정확한 호스트 이름과 강제로 일치 server합니까?


사람들이 https를 사용하여 다른 사이트에 액세스하려고하면 어떻게됩니까?
David Schwartz

호스트 이름이 일치하지 않는 한 nginx가 https를 전혀 제공하지 않거나 동일한 호스트에서 http로 리디렉션하는 것이 이상적입니다.
numbers1311407

답변:


9

호스트 이름이 일치하지 않는 한 nginx가 https를 전혀 제공하지 않거나 동일한 호스트에서 http로 리디렉션하는 것이 이상적입니다.

둘 다 가능하지 않습니다. https://foo.example.com/으로 가는 클라이언트로부터의 연결은 이름 중 하나로 "foo.example.com"을 사용하는 SSL 인증서 이외의 다른 것으로는 허용되지 않습니다. SSL 연결이 승인 될 때까지 리디렉션 할 기회가 없습니다.

SSL에 대해 각 사이트를 구성하면 인증서 오류를 클릭하는 사용자가 요청한 사이트를 얻게됩니다. 오류 페이지 만 제공하는 SSL에 대해 "모두 포획"사이트를 구성하고 SSL을 지원해야하는 한 사이트에 대한 이름 기반 가상 호스팅을 구성하면 클라이언트에 오류 페이지를 제공 할 수 있습니다.

SSL과 HTTP 가상 호스팅은 잘 어울리지 않습니다.


이것은 문서를 읽은 후에 모은 것입니다. 나는 뭔가를 놓치고 싶었습니다. SSL 경고는 전혀 신경 쓰지 않습니다. 누군가가 server1.com 에 들어가서 server2.com의 홈페이지를보고있는 것을 원하지 않습니다 ... nginx에게 요청을 수락 하지 않도록 지시 할 방법이 없습니까?
numbers1311407

요청을 수락하지 않으면 첫 번째 사이트가 작동하지 않습니다. 사용자가 액세스하려는 사이트를 찾으려면 요청을 수락해야합니다.
David Schwartz

2
" foo.example.com으로 가는 클라이언트로부터의 연결은 이름 중 하나로"foo.example.com "을 사용하는 SSL 인증서 이외의 다른 어떤 것도 받아 들일 수 없습니다." -이것은 정확하지 않습니다. 서버는 요청을 수락하며 요청 된 DN이 서버 인증서 DN과 일치하는지 확인하는 것은 클라이언트의 책임입니다.
ColinM

4

수행 할 수있는 유일한 방법은 자체 서명 된 SSL 인증서를 작성하고이를 사용하여 수신 https 요청을 제어하는 ​​것입니다. 이 게시물에 요약 된 몇 가지 간단한 단계를 통해 자체 서명 된 SSL 인증서를 만들 수 있습니다 .

파일 이름이 server.crt 인 자체 서명 인증서를 작성한다고 가정 해 봅시다. 그런 다음 nginx 구성에 다음을 추가하십시오.

server {
    listen  443;

    ssl    on;
    ssl_certificate         /etc/nginx/ssl/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/server.key;

    server_name server1.com;

    keepalive_timeout 60;
    rewrite ^       http://$server_name$request_uri? permanent;
}

여전히 브라우저 SSL 경고 메시지가 표시되지만 최소한 다음에 발생할 작업을 제어 할 수 있습니다.


1
동의합니다. 브라우저에 신뢰할 수없는 인증서에 대한 경고 메시지가 표시되는 문제가 있지만 사용자가 https : // <ip-address>로 이동하여 실제 가상 호스트 중 하나에 대해 동일하게 유효하지 않은 인증서를 서버에 가져 가지 못하게하려는 경우 (잘못된 호스트 이름이 일치하지 않기 때문에 잘못된 자체 서명 더미 인증서를 제공하는 것이 좋습니다. 그런 종류의 사람들은 "여기에는 다른 호스트의 인증서조차 볼 것이 없다"고 말합니다.
Daniel F

2

범용 서버 블록을 추가하고 상태 코드 444를 반환합니다. 데이터를 보내기 전에 nginx에 연결을 닫으라고 지시합니다.

server {
    listen 443 default_server ssl;
    server_name _;
    return 444;
}

1

요즘에는 TLS 서버 이름 표시 확장 (SNI, RFC 6066)을 사용할 수 있습니다. HTTPS 리스너는 적절한 인증서를 제공하기 전에 도메인 이름을 인식 할 수 있습니다.

즉, 모든 도메인에 대한 인증서가 필요하고 SNI를 사용하여 다른 도메인 중 하나를 인식하는 경우 서버 이름이 필요한 단일 이름과 일치하지 않는 한 HTTP 301을 HTTP 비 암호화 버전으로 리디렉션 할 수 있습니다. 암호화.

SNI에 대한 자세한 내용은 nginx 설명서 ( http://nginx.org/en/docs/http/configuring_https_servers.html)를 참조하십시오.


0

요청 된 호스트 이름을 http {}블록의 유효한 호스트 이름에 맵핑하십시오 .

map $ssl_server_name $correct_hostname_example {
  default 0;
  example.com 1;
  www.example.com 1;
}

그런 다음 server {}블록에서 잘못된 호스트 이름으로 연결을 종료하십시오.

if ($correct_hostname_example = 0) {
  return 444;
}

여러 서버 블록에 필요에 따라 여러 맵을 사용하십시오. 인증서 중 하나를 사용하여 연결이 계속 설정되지만이 마지막 블록이 SSL을 제공하는 모든 서버 블록에있는 경우 유효하지 않은 호스트 이름으로 연결을 효과적으로 "차단"합니다. 첫 번째 서버 블록에서만 필요할 수 있지만 모든 서버 블록에 추가하면 순서가 중요하지 않습니다.

$ssl_server_name변수 nginx를 1.7 이상으로 존재한다.


0

이것이 내가 문제를 해결 한 방법입니다.

  1. 자체 서명 된 인증서를 작성하십시오.

openssl req -nodes -x509 -newkey rsa:4096 -keyout self_key.pem -out self_cert.pem -days 3650

  1. NginX가 찾을 수있는 곳에 복사하십시오 :

cp self*.pem /etc/nginx/ssl/

  1. 포괄 경로 설정 :
server {
    listen 443 default_server ssl;

    ssl on;
    ssl_certificate /etc/nginx/ssl/self_cert.pem;
    ssl_certificate_key /etc/nginx/ssl/self_key.pem;

    return 301 http://$host;
}

이 수행 할 작업 : 그것은 당신에게 경고를 줄 것 자체 인증서가없는 모든 서버에 (주위 방법이)하지만 경고는 잘못된 인증서 이름을 말을하지 않습니다. 사용자가 "어쨌든 방문"을 클릭하면 입력 한 사이트의 비 SSL 버전으로 리디렉션됩니다.

경고 :

SLL 가능 사이트가 정의 www.example.com하고 만 정의 하지 않으면 example.com포괄 경로는 https://example.com자체 서명 인증서 및 해당 경고와 함께 제공 됩니다.


-2

http로 리디렉션 :

server {
    listen       443;
    server_name  *.com;
    rewrite        ^ http://$host$request_uri? permanent;
}    

404 :

server {
    listen       443;
    server_name  *.com;
    return 404;
}    

1
HTTP 리디렉션이 발생하기 전에 SSL 터널을 설정해야하므로 SSL 경고가 계속 발생합니다. David Schwartz의 답변을 참조하십시오.
cjc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.