Ubuntu 22.04에서 HTTP/2 지원 Nginx 설정하는 방법

A previous version of this tutorial was written by Sergey Zhukaev.

소개

Nginx는 빠르고 신뢰할 수 있는 오픈 소스 웹 서버입니다. 낮은 메모리 사용량, 높은 확장성, 구성 용이성 및 다양한 프로토콜 지원으로 인해 인기를 얻었습니다.

HTTP/2는 웹에서 서버에서 브라우저로 페이지를 전달하는 데 사용되는 하이퍼텍스트 전송 프로토콜의 최신 버전입니다. HTTP/2는 거의 20년 만에 처음으로 큰 업데이트입니다. HTTP1.1은 1999년에 공개되었으며 그 때 웹 페이지의 크기가 훨씬 작았습니다. 그 이후 인터넷은 급격하게 변화했으며 HTTP 1.1의 한계에 직면하고 있습니다. 이전 버전인 HTTP 1.1은 대부분의 현대 웹 사이트의 잠재적인 전송 속도를 제한합니다. 왜냐하면 페이지의 일부가 대기열에 다운로드되기 때문입니다. 이전 부분이 완전히 다운로드되기 전에 다음 부분의 다운로드가 시작됩니다. 평균적인 현대 웹 페이지는 수십 개의 개별 CSS, 자바 스크립트 및 이미지 자산을 다운로드합니다.

HTTP/2는 몇 가지 근본적인 변경으로 이 문제를 해결합니다:

  • 모든 요청이 대기열이 아닌 병렬로 다운로드됩니다.
  • HTTP 헤더가 압축됩니다.
  • 페이지가 텍스트 파일이 아닌 이진으로 전송되어 효율적입니다.
  • 사용자 요청없이 서버가 데이터를 “푸시”할 수 있어 지연 시간이 긴 사용자의 속도를 향상시킵니다.

HTTP/2는 암호화를 요구하지 않지만, 두 가장 인기 있는 브라우저인 Google Chrome과 Mozilla Firefox의 개발자들은 보안상의 이유로 HTTPS 연결에 대해서만 HTTP/2를 지원할 것이라고 밝혔습니다. 따라서, HTTP/2 지원이 구성된 서버를 설정하기로 결정한다면, 해당 서버를 HTTPS로 보호해야 합니다.

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

준비 사항

시작하기 전에 몇 가지 필요한 것이 있습니다:

단계 1 — HTTP/2 지원 활성화

Nginx 설치 자습서에서 Nginx 서버 블록 설정 단계를 따르셨다면, 이미 도메인에 대한 서버 블록이 /etc/nginx/sites-available/your_domain에 적절하게 설정된 server_name 지시문으로 생성되어 있어야 합니다. 첫 번째 변경 사항은 도메인의 서버 블록을 HTTP/2를 사용하도록 수정하는 것입니다.

선호하는 편집기인 nano를 사용하여 도메인의 구성 파일을 엽니다:

  1. sudo nano /etc/nginx/sites-enabled/your_domain

파일에서 포트 443과 관련된 listen 변수를 찾으십시오:

/etc/nginx/sites-enabled/your_domain
...
    listen [::]:443 ssl ipv6only=on; 
    listen 443 ssl; 
...

첫 번째는 IPv6 연결을 위한 것입니다. 두 번째는 모든 IPv4 연결을 위한 것입니다. 둘 다 HTTP/2를 활성화할 것입니다.

listen 지시문을 수정하여 http2를 포함시킵니다:

/etc/nginx/sites-enabled/your_domain
...
    listen [::]:443 ssl http2 ipv6only=on; 
    listen 443 ssl http2; 
...

이렇게 하면 Nginx가 지원되는 브라우저에서 HTTP/2를 사용하도록 설정됩니다.

구성 파일을 저장하고 텍스트 편집기를 종료합니다. nano를 사용하는 경우 Ctrl+X를 누르고 나서 프롬프트가 나타나면 Y를 입력한 후 Enter를 누릅니다.

Nginx 구성 파일을 변경할 때마다 내장된 구문 확인 명령을 실행하는 -t 플래그를 사용하여 구성을 오류로 확인해야 합니다:

  1. sudo nginx -t

구문에 오류가 없는 경우 다음과 같은 출력을 받게 됩니다:

Output of sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

다음으로, Nginx 서버를 보다 엄격한 암호 목록을 사용하도록 구성합니다.

단계 2 — 오래된 및 보안 취약 암호 스위트 제거

HTTP/2에는 피해야 할 오래된 및 보안 취약 암호의 차단 목록이 있습니다. 암호 스위트는 전송된 데이터를 암호화하는 방법을 설명하는 암호화 알고리즘입니다.

암호를 정의하는 방법은 Nginx에 대한 TLS/SSL 인증서를 어떻게 구성했는지에 따라 다릅니다.

만약 인증서 획득에 Certbot을 사용했다면, /etc/letsencrypt/options-ssl-nginx.conf 파일도 생성되었을 것입니다. 이 파일에는 HTTP/2에 충분히 안전하지 않은 암호가 포함되어 있습니다. 그러나 이 파일을 수정하면 Certbot이 향후 업데이트를 적용하지 못하게 됩니다. 따라서 우리는 단순히 Nginx가 이 파일을 사용하지 않도록 하고 우리만의 암호 목록을 지정할 것입니다.

도메인의 서버 블록 구성 파일을 엽니다:

sudo nano /etc/nginx/sites-enabled/your_domain

options-ssl-nginx.conf 파일을 포함하는 줄을 찾아 해당 줄의 시작 부분에 # 문자를 추가하여 주석 처리합니다:

/etc/nginx/sites-enabled/your_domain

# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

그 줄 아래에 다음 줄을 추가하여 허용된 암호를 정의합니다:

/etc/nginx/sites-enabled/your_domain

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

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

자체 서명된 인증서를 사용하거나 제3자로부터 인증서를 사용하고 전제 조건에 따라 구성한 경우 텍스트 편집기에서 /etc/nginx/snippets/ssl-params.conf 파일을 엽니다:

  1. sudo nano /etc/nginx/snippets/ssl-params.conf

다음 줄을 찾습니다:

/etc/nginx/snippets/ssl-params.conf
...
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
...

다음 암호 목록을 사용하도록 수정합니다:

/etc/nginx/snippets/ssl-params.conf

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

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

다시 한 번, nginx -t 명령을 사용하여 구성의 구문 오류를 확인합니다:

  1. sudo nginx -t

오류가 발생하면 수정하고 다시 테스트합니다.

구성이 구문 검사를 통과하면 systemctl 명령을 사용하여 Nginx를 다시 시작합니다:

  1. sudo systemctl reload nginx.service

서버를 다시 시작한 후 작동하는지 확인해 봅시다.

단계 3 — HTTP/2가 활성화되었는지 확인하기

서버가 HTTP/2와 함께 실행되고 작동하는지 확인해 봅시다.

curl 명령을 사용하여 사이트에 요청을 보내고 헤더를 확인합니다:

  1. curl -I -L --http2 https://your_domain

다음과 같은 출력을 받게 될 것입니다:

HTTP/2 200
**Server**: nginx/1.18.0 (Ubuntu)
**Date**: Tue, 21 Jun 2022 22:19:09 GMT
**Content-Type**: text/html
**Content-Length**: 612
**Last-Modified**: Tue, 21 Jun 2022 22:17:56 GMT
**Connection**: keep-alive
**ETag**: "62b24394-264"
**Accept-Ranges**: bytes

또한 Google Chrome에서 HTTP/2가 사용 중인지 확인할 수 있습니다. Chrome을 열고 https://your_domain로 이동합니다. Chrome 개발자 도구를 엽니다 (보기 -> 개발자 -> 개발자 도구) 및 페이지를 다시로드합니다 (보기 -> 이 페이지 다시로드). 네트워크 탭으로 이동하여 이름이 Name으로 시작하는 테이블 헤더 행을 마우스 오른쪽 단추로 클릭하고 팝업 메뉴에서 프로토콜 옵션을 선택합니다.

h2 (HTTP/2를 나타내는)를 포함하는 새로운 프로토콜 열이 생깁니다, 이는 HTTP/2가 작동 중임을 나타냅니다.

이 시점에서 HTTP/2 프로토콜을 통해 콘텐츠를 제공할 준비가 되었습니다. HSTS를 활성화하여 보안과 성능을 개선해 봅시다.

단계 4 — HTTP 엄격한 전송 보안 (HSTS) 활성화

HTTP 요청이 HTTPS로 리디렉션되더라도, 리디렉션을 수행하지 않고 HTTP 엄격한 전송 보안 (HSTS)을 활성화할 수 있습니다. 브라우저가 HSTS 헤더를 찾으면 일정 기간 동안 서버에 정규 HTTP를 통해 다시 연결을 시도하지 않습니다. 어떤 경우에도 암호화된 HTTPS 연결만을 사용하여 데이터를 교환합니다. 이 헤더는 또한 프로토콜 다운그레이드 공격으로부터 보호합니다.

도메인의 서버 블록 구성 파일을 다시 엽니다:

sudo nano /etc/nginx/your_domain

SSL 암호를 포함하는 파일 블록에 이 줄을 추가하여 HSTS를 활성화합니다:

/etc/nginx/your_domain
server {
...
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    add_header Strict-Transport-Security "max-age=15768000" always;
}
...

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

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

/etc/nginx/your_domain
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

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

한 번 더 구문 오류가 있는지 구성을 확인합니다:

  1. sudo nginx -t

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

  1. sudo systemctl reload nginx.service

결론

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

Nginx가 서버 블록 규칙을 구문 분석하고 구현하는 방법에 대해 자세히 알아보려면 Nginx 서버 및 위치 블록 선택 알고리즘 이해를 읽어보세요.

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-with-http-2-support-on-ubuntu-22-04