nevertheless
Nginx로 HTTPS 설정하기 (+lego) 본문
HTTPS
HTTPS란 HyperText Transfer Protocol Secure의 약자로, 웹 통신 프로토콜인 HTTP의 보안 버전.
HTTP는 단순 텍스트를 주고 받기 때문에, 서버와 클라이언트 사이에서 자원을 주고 받을 때 누군가 데이터를 가로챌 수 있다. 이 문제점을 HTTPS 프로토콜리 해결한다.
공개키 암호화 방식을 사용하여 암호화한다.
SSL & TLS
SSL(Secure Sockets Layer)과 TLS(Transport Payer Security)은 네트워크 통신에서 보안을 제공하기 위해 사용되는 암호화 프로토콜.
HTTPS 통신 흐름
- CA(Certificate Authority)는 공개키 저장소로, CA 기업의 공개키는 브라우저가 이미 알고 있음!
- 기업은 서버의 공개키/개인키 생성
- CA에 인증서 발급 요청
CACA는 서버 정보를 포함한 인증서(Certificate)를 만들어서, CA의 개인키로 서명해서 서버에게 발급해줌.
-> 이 인증서가 바로 SSL 또는 TLS - 클라이언트(브라우저)가 서버에 접속 시도 (HTTPS)
- 클라이언트가 https://example.com에 접속 시도
- 서버는 자신의 인증서(CA의 서명이 포함됨)를 브라우저에게 보냄
- 브라우저는 인증서의 서명을 검증하기 위해,
• 인증서에 적힌 발급한 CA 이름을 확인하고
• 해당 CA의 공개키로 서명을 복호화
• 인증서 내용이 위조되지 않았음을 확인 - 인증서 안의 서버 공개키를 얻음
Let's Encrypt
무료 SSL 인증서 보급. 자동화된 개방형 인증 기관(CA)
인증서 발급 도구(cerbot, lego 등)
HTTPS 활성화를 위해 Let’s Encrypt를 이용해 SSL/TLS 인증서를 발급받고, 갱신할 수 있도록 도와주는 무료 오픈소스 소프트웨어 도구
Nginx
정적 콘텐츠를 제공할 수 있는 웹서버(Web Server)
또는 클라이언트의 요청을 내부 서버에 전달하고, 그 결과를 다시 클라이언트에게 전달하는 리버스 프록시(프론트맨)
Nginx+lego로 HTTPS 설정하기
순서는 다음과 같다.
- nginx 설치
- lego 설치 및 ssl 인증서 발급
- nginx 설정 파일 업데이트
Nginx 설치
# Nginx 설치
$ sudo apt install nginx
# Nginx 실행
$ sudo systemxtl start nginx
$ sudo systemxtl enable nginx
Lego 설치
# lego 클라이언트 설치
$ cd /tmp
$ curl -Ls https://api.github.com/repos/xenolf/lego/releases/latest | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -i - tar xf lego_vX.Y.Z_linux_amd64.tar.gz
# 다운받은 lego 압축파일명 확인
$ cd /tmp
$ curl -Ls https://api.github.com/repos/xenolf/lego/releases/latest | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -i - tar xf lego_vX.Y.Z_linux_amd64.tar.gz
# 파일 압축을 품
$ tar xf lego_v1.2.1_linux_amd64.tar.gz
# 생성된 lego 파일을 /usr/local/bin으로 옮김
$ sudo mv lego /usr/local/bin/lego
# 설치 확인
$ lego --version
SSL 인증서 발급
$ sudo mkdir -p /etc/lego
# 아래 예시에서 이메일, 도메인, 웹 서버를 바꿔서 입력
$ sudo lego --email="you@example.com"
--domains="yourdomain.com" --http \
--path="/etc/lego"
run
/etc/nginx/sites-available/ 안에 있는 설정 파일에서 다음 경로들이 맞는지 확인:
- ssl_certificate /etc/lego/certificates/cau-chunghaha.p-e.kr.crt;
- ssl_certificate_key /etc/lego/certificates/cau-chunghaha.p-e.kr.key;
NGINX 설정 파일 수정
# nginx 설정 수정
$ sudo vim /etc/nginx/sites-available/{도메인}
# /etc/nginx/sites-available/{도메인}
server {
listen 80;
server_name {도메인} www.{도메인};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name {도메인} www.{도메인};
ssl_certificate /etc/letsencrypt/live/{도메인}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{도메인}/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/ {
alias /path/to/static/files/;
}
location /media/ {
alias /path/to/media/files/;
}
}
$ sudo vim /etc/nginx/nginx.conf
# /etc/nginx/nginx.conf
# http 블럭 마지막줄
# include /etc/nginx/sites-enabled/*; 를 찾아주세요.
http {
include /etc/nginx/sites-enabled/{도메인};
}
심볼릭 링크 생성
$ sudo ln -s /etc/nginx/sites-available/{도메인} /etc/nginx/sites-enabled/
nginx 재시작
$ sudo systemctl restart nginx
$ sudo nginx -t
$ sudo systemctl status nginx
도메인 인증서 만료일 확인
$ openssl s_client -connect 도메인명:443 | openssl x509 -noout -dates
자동갱신
** nignx 끄고 시작하기!
갱신 스크립트 만들기
$ sudo nano /usr/local/bin/renew-ssl.sh
아래 내용을 붙여넣음:
#!/bin/bash
# nginx 중지
systemctl stop nginx
# 인증서 갱신 시도
/usr/local/bin/lego \
--email="you@example.com" \
--domains="yourdomain.com" \
--http --path="/etc/lego" renew
# nginx 시작
systemctl start nginx
저장하고 나가기: Ctrl + X → Y → Enter
파일에 권한 줌:
$ sudo chmod +x /usr/local/bin/renew-ssl.sh
Cron으로 자동 실행 등록
$ sudo crontab -e
맨 아래에 다음 줄 추가 (매일 새벽 3시 갱신 시도):
0 3 * * * /usr/local/bin/renew-ssl.sh >> /var/log/ssl-renew.log 2>&1
잘 작동하는지 테스트
** nginx 재시작!
$ sudo /usr/local/bin/renew-ssl.sh
