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 서버를 설정하는 데 도움이 될 것입니다.
준비 사항
시작하기 전에 몇 가지 필요한 것이 있습니다:
- Ubuntu 22.04 서버가 설정되어 있어야 합니다. 이를 위해 Ubuntu 22.04 초기 서버 설정 가이드를 따라 sudo 권한이 있는 비루트 사용자와 방화벽이 설정되어 있어야 합니다.
- 서버에 Nginx가 설치되어 있어야 합니다. 이는 Ubuntu 22.04에 Nginx 설치하는 방법을 따라 할 수 있습니다.
- A domain name configured to point to your server. You can purchase one on Namecheap or get one for free on Freenom. You can learn how to point domains to DigitalOcean Droplets by following the documentation on How To Manage Your Domain With DigitalOcean.
- A TLS/SSL certificate configured for your server. You have two options:
- 무료 인증서를 얻을 수 있습니다. 이를 위해 Let’s Encrypt의 Ubuntu 22.04에서 Let’s Encrypt로 Nginx 보안 설정하는 방법을 따릅니다.
- 당신은 또한 우분투 22.04에서 Nginx를 위한 자체 서명 SSL 인증서를 만드는 방법을 따라서 자체 서명된 인증서를 생성하고 구성할 수 있습니다.
- Nginx는 포트
80
에서 포트443
으로의 트래픽을 리디렉션하도록 구성되어 있으며, 이는 이전 선행 조건에 의해 이미 처리되어야 합니다. - Nginx는 2048비트 이상의 일회용 디피-헬만 (DHE) 키를 사용하도록 구성되어 있으며, 이 또한 이전 선행 조건에 의해 이미 처리되어야 합니다.
단계 1 — HTTP/2 지원 활성화
Nginx 설치 자습서에서 Nginx 서버 블록 설정 단계를 따르셨다면, 이미 도메인에 대한 서버 블록이 /etc/nginx/sites-available/your_domain
에 적절하게 설정된 server_name
지시문으로 생성되어 있어야 합니다. 첫 번째 변경 사항은 도메인의 서버 블록을 HTTP/2를 사용하도록 수정하는 것입니다.
선호하는 편집기인 nano
를 사용하여 도메인의 구성 파일을 엽니다:
파일에서 포트 443
과 관련된 listen
변수를 찾으십시오:
...
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
...
첫 번째는 IPv6 연결을 위한 것입니다. 두 번째는 모든 IPv4 연결을 위한 것입니다. 둘 다 HTTP/2를 활성화할 것입니다.
각 listen
지시문을 수정하여 http2
를 포함시킵니다:
...
listen [::]:443 ssl http2 ipv6only=on;
listen 443 ssl http2;
...
이렇게 하면 Nginx가 지원되는 브라우저에서 HTTP/2를 사용하도록 설정됩니다.
구성 파일을 저장하고 텍스트 편집기를 종료합니다. nano
를 사용하는 경우 Ctrl+X
를 누르고 나서 프롬프트가 나타나면 Y
를 입력한 후 Enter를 누릅니다.
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
파일을 포함하는 줄을 찾아 해당 줄의 시작 부분에 #
문자를 추가하여 주석 처리합니다:
# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
그 줄 아래에 다음 줄을 추가하여 허용된 암호를 정의합니다:
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
파일을 저장하고 편집기를 종료합니다.
자체 서명된 인증서를 사용하거나 제3자로부터 인증서를 사용하고 전제 조건에 따라 구성한 경우 텍스트 편집기에서 /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;
...
다음 암호 목록을 사용하도록 수정합니다:
...
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
파일을 저장하고 편집기를 종료합니다.
다시 한 번, nginx -t
명령을 사용하여 구성의 구문 오류를 확인합니다:
오류가 발생하면 수정하고 다시 테스트합니다.
구성이 구문 검사를 통과하면 systemctl
명령을 사용하여 Nginx를 다시 시작합니다:
서버를 다시 시작한 후 작동하는지 확인해 봅시다.
단계 3 — HTTP/2가 활성화되었는지 확인하기
서버가 HTTP/2와 함께 실행되고 작동하는지 확인해 봅시다.
curl
명령을 사용하여 사이트에 요청을 보내고 헤더를 확인합니다:
다음과 같은 출력을 받게 될 것입니다:
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를 활성화합니다:
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
변수를 추가해야 합니다. 다음과 같이:
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
파일을 저장하고 편집기를 종료합니다.
한 번 더 구문 오류가 있는지 구성을 확인합니다:
마지막으로 변경 사항을 적용하기 위해 Nginx 서버를 다시 시작합니다.
결론
이제 Nginx 서버가 HTTP/2 페이지를 제공합니다. SSL 연결의 강도를 테스트하려면 Qualys SSL Lab을 방문하고 서버에 대한 테스트를 실행하십시오. 모든 것이 올바르게 구성되어 있다면 보안에 대한 A+ 등급을 받아야 합니다.
Nginx가 서버 블록 규칙을 구문 분석하고 구현하는 방법에 대해 자세히 알아보려면 Nginx 서버 및 위치 블록 선택 알고리즘 이해를 읽어보세요.