웹사이트 검색

Ubuntu 16.04에서 HTTP/2 지원으로 Nginx를 설정하는 방법


소개

NGINX는 빠르고 안정적인 오픈 소스 웹 서버입니다. 낮은 메모리 공간, 높은 확장성, 구성 용이성 및 대부분의 다양한 프로토콜 지원으로 인해 인기를 얻었습니다.

지원되는 프로토콜 중 하나는 2015년 5월에 게시된 상대적으로 새로운 HTTP/2입니다. HTTP/2의 주요 장점은 콘텐츠가 풍부한 웹사이트에 대한 빠른 전송 속도입니다.

이 튜토리얼은 HTTP/2를 지원하는 빠르고 안전한 Nginx 서버를 설정하는 데 도움이 됩니다.

전제 조건

시작하기 전에 몇 가지 사항이 필요합니다.

  • 우분투 16.04 드롭릿
  • sudo 권한이 있는 루트가 아닌 사용자(자세한 내용은 Ubuntu 16.04의 초기 서버 설정을 확인하십시오.)
  • 완전히 등록된 도메인. Freenom에서 구매할 수 있습니다.
  • 귀하의 도메인 이름이 귀하의 Droplet을 가리키도록 구성되어 있는지 확인하십시오. 도움이 필요하면 이 튜토리얼을 확인하세요.
  • SSL 인증서. 다른 제공업체에서 구매하세요.

그게 전부입니다. 위에 나열된 모든 항목이 있으면 사용할 준비가 된 것입니다.

HTTP 1.1과 HTTP/2의 차이점

HTTP/2는 서버에서 브라우저로 페이지를 전달하기 위해 웹에서 사용되는 하이퍼텍스트 전송 프로토콜의 새 버전입니다. HTTP/2는 거의 20년 만에 HTTP의 첫 번째 주요 업데이트입니다. HTTP1.1은 웹 페이지가 일반적으로 인라인 CSS 스타일시트가 있는 단일 HTML 파일이었던 1999년에 대중에게 소개되었습니다. 그 이후로 인터넷은 극적으로 변화했고 이제 우리는 HTTP 1.1의 한계에 직면해 있습니다. 이 프로토콜은 대기열에 있는 페이지의 일부를 다운로드하기 때문에 대부분의 최신 웹사이트에 대한 잠재적인 전송 속도를 제한합니다(이전 부분은 다운로드 전에 완전히 다운로드해야 함). 다음 부분이 시작됩니다) 그리고 평균적인 현대 웹페이지는 다운로드하기 위해 약 100개의 요청이 필요합니다(각 요청은 사진, js 파일, css 파일 등입니다).

HTTP/2는 몇 가지 근본적인 변화를 가져오기 때문에 이 문제를 해결합니다.

  • 모든 요청은 대기열이 아닌 병렬로 다운로드됩니다.
  • HTTP 헤더가 압축됨
  • 페이지는 더 효율적인 텍스트 파일이 아닌 바이너리로 전송됩니다.
  • 서버는 사용자의 요청 없이도 데이터를 "푸시\할 수 있으므로 대기 시간이 긴 사용자의 속도가 향상됩니다.

HTTP/2에는 암호화가 필요하지 않지만 가장 널리 사용되는 두 브라우저인 Google Chrome과 Mozilla Firefox의 개발자는 보안상의 이유로 HTTPS 연결에 대해서만 HTTP/2를 지원할 것이라고 밝혔습니다. 따라서 HTTP/2 지원으로 서버를 설정하기로 결정했다면 HTTPS로도 보안을 유지해야 합니다.

1단계 - Nginx 최신 버전 설치

HTTP/2 프로토콜 지원은 Nginx 1.9.5에서 도입되었습니다. 다행히 Ubuntu 16.04의 기본 리포지토리에는 이보다 높은 버전이 포함되어 있으므로 타사 리포지토리를 추가할 필요가 없습니다.

먼저 apt 패키징 시스템에서 사용 가능한 패키지 목록을 업데이트합니다.

  1. sudo apt-get update

그런 다음 Nginx를 설치합니다.

  1. sudo apt-get install nginx

설치 프로세스가 완료되면 다음을 입력하여 Nginx 버전을 확인할 수 있습니다.

  1. sudo nginx -v

출력은 다음과 유사해야 합니다.

nginx version: nginx/1.10.0 (Ubuntu)

다음 몇 단계에서는 Nginx 구성 파일을 수정합니다. 각 단계는 Nginx 구성 옵션을 변경합니다. 그 과정에서 구성 파일의 구문을 테스트합니다. 마지막으로 Nginx가 HTTP/2를 지원하는지 확인하고 성능을 최적화하기 위해 몇 가지 사항을 변경합니다.

2단계 - 수신 포트 변경 및 HTTP/2 활성화

첫 번째 변경 사항은 수신 포트를 80에서 443으로 변경하는 것입니다.

구성 파일을 열어 보겠습니다.

  1. sudo nano /etc/nginx/sites-available/default

기본적으로 Nginx는 표준 HTTP 포트인 포트 80을 수신 대기하도록 설정되어 있습니다.

listen 80 default_server;
listen [::]:80 default_server;

보시다시피 두 개의 서로 다른 listen 변수가 있습니다. 첫 번째는 모든 IPv4 연결용입니다. 두 번째는 IPv6 연결용입니다. 둘 다에 대해 암호화를 활성화합니다.

수신 포트를 HTTPS 프로토콜에서 사용하는 443으로 수정합니다.

listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;

ssl 외에 http2도 줄에 추가했습니다. 이 변수는 지원되는 브라우저에서 HTTP/2를 사용하도록 Nginx에 지시합니다.

3단계 - 서버 이름 변경

server_name 항목을 사용하여 구성 파일과 연결해야 하는 도메인을 지정합니다. 구성 파일에서 server_name 항목을 찾습니다.

기본적으로 server_name_(밑줄)로 설정되며 이는 구성 파일이 들어오는 모든 요청을 담당함을 의미합니다. 다음과 같이 _를 실제 도메인으로 변경합니다.

server_name example.com;

구성 파일을 저장하고 텍스트 편집기를 편집합니다.

Nginx 구성 파일을 변경할 때마다 다음과 같은 구문 오류에 대한 구성을 확인해야 합니다.

  1. sudo nginx -t

구문에 오류가 없으면 다음 출력이 표시됩니다.

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

4단계 - SSL 인증서 추가

다음으로 SSL 인증서를 사용하도록 Nginx를 구성해야 합니다. SSL 인증서가 무엇인지 모르거나 현재 인증서가 없는 경우 이 문서의 전제 조건 섹션에 있는 자습서 중 하나를 따르십시오.

Nginx 구성 디렉터리 내에 SSL 인증서를 저장할 디렉터리를 만듭니다.

  1. sudo mkdir /etc/nginx/ssl

인증서와 개인 키를 이 위치에 복사하십시오. 또한 연결된 도메인을 표시하기 위해 파일 이름을 바꿉니다. 나중에 이 서버와 연결된 도메인이 두 개 이상일 때 유용합니다. example.com을 실제 호스트 이름으로 바꿉니다.

  1. sudo cp /path/to/your/certificate.crt /etc/nginx/ssl/example.com.crt
  2. sudo cp /path/to/your/private.key /etc/nginx/ssl/example.com.key

이제 구성 파일을 다시 열고 SSL을 구성해 보겠습니다.

  1. sudo nano /etc/nginx/sites-available/default

server 블록 내부의 새 줄에서 인증서 위치를 정의합니다.

ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;

파일을 저장하고 텍스트 편집기를 종료합니다.

5단계 - 오래된 암호 그룹 피하기

HTTP/2에는 오래되고 안전하지 않은 암호에 대한 방대한 블랙리스트가 있으므로 이러한 암호를 피해야 합니다. 암호 그룹은 전송 데이터를 암호화하는 방법을 설명하는 암호화 알고리즘 모음입니다.

우리는 CloudFlare와 같은 인터넷 거대 기업이 보안을 승인한 매우 인기 있는 암호 세트를 사용할 것입니다. MD5 암호화(1996년부터 안전하지 않은 것으로 알려졌으나, 그럼에도 불구하고 현재까지도 광범위하게 사용됨)의 사용을 허용하지 않습니다.

다음 구성 파일을 엽니다.

  1. sudo nano /etc/nginx/nginx.conf

ssl_prefer_server_ciphers on; 뒤에 이 행을 추가하십시오.

ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

파일을 저장하고 텍스트 편집기를 종료합니다.

다시 한 번 구문 오류에 대한 구성을 확인하십시오.

  1. sudo nginx -t

6단계 - 키 교환 보안 강화

보안 연결 설정의 첫 번째 단계는 서버와 클라이언트 간의 개인 키 교환입니다. 문제는 지금까지 그들 사이의 연결이 암호화되지 않았다는 것입니다. 즉, 데이터 전송이 제3자에게 표시된다는 의미입니다. 그래서 Diffie-Hellman-Merkle 알고리즘이 필요합니다. 작동 방식에 대한 기술적인 세부 사항은 간단히 설명할 수 없는 복잡한 문제이지만 세부 사항에 관심이 있는 경우 이 YouTube 비디오를 볼 수 있습니다.

기본적으로 Nginx는 상대적으로 해독하기 쉬운 1028비트 DHE(Ephemeral Diffie-Hellman) 키를 사용합니다. 최대의 보안을 제공하려면 보다 안전한 자체 DHE 키를 구축해야 합니다.

이를 수행하려면 다음 명령을 실행하십시오.

  1. sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

SSL 인증서와 동일한 폴더에 DH 매개변수를 생성해야 합니다. 이 자습서에서 인증서는 /etc/nginx/ssl/에 있습니다. 그 이유는 Nginx가 항상 인증서 폴더에서 사용자가 제공한 DHE 키를 찾고 존재하는 경우 이를 사용하기 때문입니다.

파일 경로 뒤의 변수(이 경우 2048)는 키의 길이를 지정합니다. 2048비트 길이의 키는 충분히 안전하며 Mozilla Foundation에서 권장하지만 더 많은 암호화를 원하는 경우 4096으로 변경할 수 있습니다.

생성 프로세스는 약 5분 정도 소요됩니다.

완료되면 기본 Nginx 구성 파일을 다시 엽니다.

  1. sudo nano /etc/nginx/sites-available/default

server 블록 내의 새 줄에서 사용자 지정 DHE 키의 위치를 정의합니다.

ssl_dhparam  /etc/nginx/ssl/dhparam.pem;

7단계 - 모든 HTTP 요청을 HTTPS로 리디렉션

우리는 HTTPS를 통해서만 콘텐츠를 제공하는 데 관심이 있기 때문에 서버가 HTTP 요청을 받으면 Nginx에게 무엇을 해야 하는지 알려줘야 합니다.

파일 맨 아래에 모든 HTTP 요청을 HTTPS로 리디렉션하기 위한 새 서버 블록을 생성합니다(서버 이름을 실제 도메인 이름으로 바꿔야 함).

server {
       listen         80;
       listen    [::]:80;
	   server_name    example.com;
       return         301 https://$server_name$request_uri;
}

파일을 저장하고 구성 파일을 종료합니다.

구문 오류에 대한 구성을 확인하십시오.

  1. sudo nginx -t

8단계 - Nginx 다시 로드

이것이 모든 Nginx 구성 변경에 대한 것입니다. 변경 사항이 있을 때마다 구문 오류를 확인했으므로 Nginx를 다시 시작하고 변경 사항을 테스트할 준비가 되어 있어야 합니다.

요약하자면 주석 처리된 줄을 무시하면 이제 구성 파일이 다음과 유사하게 표시됩니다.

server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;

        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;

        server_name example.com;

        location / {
                try_files $uri $uri/ =404;
        }

        ssl_certificate /etc/nginx/ssl/example.com.crt;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;
}


server {
       listen         80;
       listen    [::]:80;
       server_name    example.com;
       return         301 https://$server_name$request_uri;
}

변경 사항을 적용하려면 Nginx 서버를 다시 시작하십시오.

  1. sudo systemctl restart nginx

9단계 - 변경 사항 확인

서버가 실행 중인지 확인합시다. 웹 브라우저를 열고 도메인으로 이동합니다(example.com을 실제 도메인 이름으로 대체).

example.com

모든 것이 올바르게 구성되었으면 자동으로 HTTPS로 리디렉션됩니다. 이제 HTTP/2가 작동하는지 확인하겠습니다. Chrome 개발자 도구를 열고(보기 -> 개발자 -> 개발자 도구) 페이지를 다시 로드합니다(보기 -> 이 페이지 새로고침). 그런 다음 네트워크 탭으로 이동하여 이름으로 시작하는 테이블 헤더 행을 클릭하고 마우스 오른쪽 버튼으로 클릭한 다음 프로토콜 옵션을 선택합니다.

이제 HTTP/2 콘텐츠를 제공하는 웹사이트의 새 열에 h2(HTTP/2를 나타냄)가 표시되어야 합니다.

이 시점에서 서버는 HTTP/2 프로토콜을 통해 콘텐츠를 제공할 준비가 되었지만 프로덕션에서 사용할 서버를 준비하기 위해 수행해야 할 몇 가지 작업이 아직 남아 있습니다.

10단계 — 최고의 성능을 위한 Nginx 최적화

이 단계에서는 최상의 성능과 보안을 위해 기본 Nginx 구성 파일을 조정합니다.

먼저 콘솔에 다음을 입력하여 nginx.conf를 엽니다.

  1. sudo nano /etc/nginx/nginx.conf

연결 자격 증명 캐싱 활성화

HTTP에 비해 HTTPS는 서버와 사용자 간의 초기 연결을 설정하는 데 상대적으로 더 오랜 시간이 걸립니다. 이러한 페이지 로드 속도 차이를 최소화하기 위해 연결 자격 증명의 캐싱을 활성화합니다. 즉, 요청된 모든 페이지에서 새 세션을 생성하는 대신 서버는 대신 캐시된 버전의 자격 증명을 사용합니다.

세션 캐싱을 활성화하려면 nginx.conf 파일의 http 블록 끝에 다음 줄을 추가합니다.

ssl_session_cache shared:SSL:5m;
ssl_session_timeout 1h;

ssl_session_cache는 세션 정보를 포함할 캐시 크기를 지정합니다. 1MB는 약 4000개의 세션에 대한 정보를 저장할 수 있습니다. 기본값인 5MB는 대부분의 사용자에게 충분하지만 트래픽이 매우 많을 것으로 예상되는 경우 이 값을 적절하게 늘릴 수 있습니다.

ssl_session_timeout은 특정 세션이 캐시에 저장되는 시간을 제한합니다. 이 값은 너무 크면 안 되지만(1시간 이상) 너무 낮게 설정해도 무의미합니다.

HSTS(HTTP Strict Transport Security) 활성화

Nginx 구성 파일에서 모든 일반 HTTP 요청을 HTTPS로 리디렉션하도록 이미 설정했지만 처음부터 이러한 리디렉션을 수행하지 않으려면 HTTP Strict Transport Security를 활성화해야 합니다.

브라우저가 HSTS 헤더를 찾으면 지정된 시간 동안 다시 일반 HTTP를 통해 서버에 연결을 시도하지 않습니다. 어쨌든 암호화된 HTTPS 연결만을 사용하여 데이터를 교환합니다. 이 헤더는 또한 프로토콜 다운그레이드 공격으로부터 우리를 보호해야 합니다.

nginx.conf에 다음 행을 추가하십시오.

add_header Strict-Transport-Security "max-age=15768000" always;

max-age는 초 단위로 설정됩니다. 15768000초는 6개월에 해당합니다.

기본적으로 이 헤더는 하위 도메인 요청에 추가되지 않습니다. 하위 도메인이 있고 모든 하위 도메인에 HSTS를 적용하려면 다음과 같이 줄 끝에 includeSubDomains 변수를 추가해야 합니다.

add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

파일을 저장하고 텍스트 편집기를 종료합니다.

다시 한 번 구문 오류에 대한 구성을 확인하십시오.

  1. sudo nginx -t

마지막으로 Nginx 서버를 다시 시작하여 변경 사항을 적용합니다.

  1. sudo systemctl restart nginx

결론

Nginx 서버가 이제 HTTP/2 페이지를 제공하고 있습니다. SSL 연결의 강도를 테스트하려면 Qualys SSL Lab을 방문하여 서버에 대해 테스트를 실행하십시오. 모든 것이 올바르게 구성되면 보안에 대해 A+ 마크를 받아야 합니다.