안녕하세요👋
오늘은 Nginx 서버에 SSL/TLS 인증서 적용하는 방법을 알아보겠습니다.
서론
처음에 SSL/TLS 인증서를 왜 적용 해야하는지 몰랐습니다.
간단하게 결론부터 짧게 말을 해보자면 SSL/TLS 는 보안과 관련된 이슈가 가장 큽니다.
웹 사이트와 Client 간의 데이터 전송을 암호화 하여 보안을 강화해주며, 데이터 도청 및 위조를 방지하며
신뢰성을 높여 검색 엔진 최적화를 개선해주기 때문입니다.
한줄 요약 : 보안에 좋기 때문이다.
그리고 SSL/TLS 는 osi7 layers 에서 , 상위 계층인 세션 계층(5), 프레젠테이션 계층(6) 에 위치 합니다.
세션계층(5): SSL/TLS는 세션의 설정 관리 합니다.
프레젠테이션 계층(6) : SSL/TLS 데이터 암호화와 복호화하고 안전한 통신을 보장시킨다.
그러면 SSL/TLS 을 적용하면 어떻게 될까요?
SSL/TLS 인증서를 발급하지 않은 사이트 일 경우에는 접속을 할 경우
위 사진 처럼 돋보기 클릭을 했을 때, https 보안이 안전하지 않다고 나올 것 입니다.
SSL/TLS 가 잘 적용된 사이트 일 경우 아무런 메세지가 나오지 않을 것 입니다.
그럼 여기서 https 는 무엇일까요?
<살짝 말 수정하기>
http 와 https 는 비슷하게 생기긴 했는데 하는 역할은 다릅니다.
둘다 인터넷 규약 프로토콜이며, 데이터를 전달 하는 역할을 합니다.
HTTP
- 웹 브라우저와 웹 서버(nginx,apache) 간의 데이터를 암호화 없이 전송합니다.
- 데이터가 도청,변조될 위험이 있습니다.
- http:// 로 시작함 (요즘은 거의 안보이긴 할듯?)
HTTPS
- HTTP 프로토콜에 SSL/TLS 암호화가 추가된 프로토콜 이다.
- 데이터가 암호화되어 전송되므로 도청,변조로부터 보호됨
- https:// 로 시작됨
지금 url 을 복사해서 붙여 넣으면 맨 앞에 시작이 https:// 도메인 이름 으로 시작할 것 입니다.
한줄요약: SSL/TLS 는 HTTPS 프로토콜 기반 기술로, HTTP 통신을 안전하게 만드는 역할을 합니다.
추가적인 설명을 하자면 요즘은 SSL 이 아닌 TLS 로 암호화를 한다고 합니다.
본론
이제 SSL/TLS 를 어떻게 적용을 하는지 알아보겠습니다.
방법은 2가지가 있습니다.
1) 유료로 SSL/TLS 인증서 발급 하는 업체 이용 (많은 업체 있습니다)
=> 가격은 용도? 크기? 등 여러 가지 요소에 따라 천차만별인 것 같습니다.
2) Lets Encrypt 사이트 이용
- 무료로 SSL 인증서 발급
- 3개월마다 인증서 갱신을 해줘야함(자동화 가능함)
저는 돈이 없는 개발자 이기 때문에, 무료로 하는 방법을 알려드리도록 하겠습니다.
일단 위 과정을 진행하기 위한 선수 조건으로는 도메인 구매 입니다.
도메인이 구매가 되어 있어야 Nginx 와 설정 및 SSL/TLS 인증서 발급을 할 수 있습니다.
실제 도메인이 없다면 SSL/TLS 인증서가 발급되지 않습니다.
위 과정에서 실제 도메인이 있는지 조회하는 과정이 필수로 있기 때문에 Localhost 환경에서는 불가능 합니다.
저는 간단하게 Docker 를 사용하여 WordPress 환경을 구축하였습니다.
https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-docker-compose
궁금 하신 분은 위 문서를 읽어보시면서 천천히 따라 해보시길 추천합니다.
전체 docker-compose.yml 입니다.
version: '3'
services:
db:
image: mysql:8.0
container_name: db
restart: unless-stopped
env_file: .env
environment:
- MYSQL_DATABASE=wordpress
ports:
- "13306:3306"
volumes:
- ./dbdata:/var/lib/mysql
command: '--default-authentication-plugin=mysql_native_password'
networks:
- app-network
wordpress:
depends_on:
- db
image: wordpress:php8.3-fpm-alpine
container_name: wordpress
restart: unless-stopped
env_file: .env
environment:
- WORDPRESS_DB_HOST=db:3306
- WORDPRESS_DB_USER=$MYSQL_USER
- WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
- WORDPRESS_DB_NAME=wordpress
volumes:
- ./wordpress:/var/www/html
networks:
- app-network
webserver:
depends_on:
- wordpress
image: nginx:1.15.12-alpine
container_name: webserver
restart: unless-stopped
ports:
- "31080:80" # 31080포트로 들어오는 트래픽이 컨테이너의 80포트로 전달
- "31443:443" # 31443포트로 들어오는 트래픽이 컨테이너의 443포트로 전달
volumes:
- ./wordpress:/var/www/html
- ./nginx-conf:/etc/nginx/conf.d
- ./certbot-etc:/etc/letsencrypt
networks:
- app-network
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot-etc:/etc/letsencrypt
웹 서버에서 포트를 2개로 처리하는 이유는 http, https 트래픽을 동시에 처리하기 위해 두 포트를 사용합니다.
- 일반적으로 80 포트는 HTTP, 443 포트는 HTTPS를 처리합니다.
- Docker Compose 설정에서 호스트의 포트와 컨테이너의 포트를 매핑하여 외부에서 각각의 서비스에 접근할 수 있게 합니다.
- 31080:80: 호스트의 31080 포트로 들어오는 트래픽을 컨테이너의 80 포트로 전달합니다 -> http 트래픽을 처리.
- 31443:443: 호스트의 31443 포트로 들어오는 트래픽을 컨테이너의 443 포트로 전달합니다 -> https 트래픽을 처리.
위처럼 다른 포트로 처리하는 것은 국룰 인것 같습니다.
(그대신 나중에 http 로 접속해도 https 로 접속이 되게끔 리다이렉트 하는 작업이 필요하겠죠?)
위 docker-compose 파일을 통해 db,webserver,wordpress,certbot 이 설치가 되었습니다.
🌟중요🌟
Certbot은 Let's Encrypt에서 제공하는 무료 SSL/TLS 인증서를 자동으로 발급하고 갱신해주는 오픈 소스 도구입니다.
SSL/TLS 인증서는 웹사이트와 사용자 간의 데이터를 암호화하여 보안성을 높여줍니다.
위 Certbot 이 있어야지 SSL/TLS 인증서를 무료로 발급 받을 수 있습니다.
Certbot은 역할은
- 인증서 발급: 도메인 소유권을 검증한 후 SSL/TLS 인증서를 발급받습니다.
- 자동 갱신: 발급받은 인증서를 자동으로 갱신해 줍니다. (따로 설정 해야함)
- 간편한 설치: 대부분의 웹 서버(예: Apache, Nginx)와 통합되어 간단히 설치하고 설정할 수 있습니다.
이제 docker compose 실행을 하면
$ docker compose up -d // docker compose 실행
위 사진 처럼 잘 Running 이 되야 합니다.
다음으로 certbot 을 사용해서 SSL/TLS 인증서를 발급 받을 것 입니다.
위 인증서를 받기 전에 nginx.conf 를 수정 합니다.
server {
server_name abc.co.kr www.abc.co.kr; # 내 도메인들 적기
include nginxconfig.io/security-wp.conf;
access_log /var/log/nginx/abc/access.log;
error_log /var/log/nginx/abc/error.log;
ssl_certificate /etc/letsencrypt/archive/abc.co.kr/fullchain1.pem;
ssl_certificate_key /etc/letsencrypt/archive/abc.co.kr/privkey1.pem;
location / {
proxy_pass http://127.0.0.1:31080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
client_max_body_size 20M;
proxy_http_version 1.1;
proxy_buffering off;
chunked_transfer_encoding off;
}
include nginxconfig.io/general-pp.conf;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/abc.co.kr/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/abc.co.kr/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
}
server {
if ($host = abc.co.kr) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name abc.co.kr;
return 404; # managed by Certbot
}
위 처럼 nginx 파일을 수정 합니다.
다음으로 Certbot 을 실행합니다.
아래 명령어 둘중 한개를 사용해서 진행합니다.
// 1번 명령어
$ docker-compose run certbot certonly --webroot --webroot-path=/var/www/html --email abc@abc.co.kr --agree-tos --no-eff-email -d abc.co.kr -d www.abc.co.kr
// 2번 명령어
$ certbot certonly --nginx -d abc.co.kr
위 명령어를 입력 하면 아래와 같은 결과물이 주어질 것 입니다.
cert.pem@ --> /etc/letsencrypt/archive/abc.co.kr/cert1.pem
chain.pem@ --> /etc/letsencrypt/archive/abc.co.kr/chain1.pem
fullchain.pem@ --> /etc/letsencrypt/archive/abc.co.kr/fullchain1.pem
privkey.pem@ --> /etc/letsencrypt/archive/abc.co.kr/privkey1.pem
여기서 경로만 떼서 엔진엑스 파일에 붙여 ssl 설정을 한 것 입니다.
다음으로 Nginx를 재시작 합니다.
$ docker-compose restart webserver
webserver 만 재시작을 합니다. ( $ docker compose restart 통해서 전체 재시작을 해도 상관없음)
이제 설정이 다 끝났습니다.
이제 제 도메인으로 접속을 하면 https 로 적용이 되는 것을 확인할 수 있습니다.
certbot 이용시 3개월 마다 인증서를 갱신해줘야 한다.
✅ 적용된걸 어떻게 확인하나요 ?
1) 시크릿 모드
-> 기본 브라우저에서는 캐시에 저장이 되어있을 꺼임 , 캐쉬를 초기화 한 상태로 해야함 귀찮으니 시크릿 모드
2) http:// 도메인 이름
-> 검색시 https 로 리다이렉트가 되는지 체크 해야함
3) https:// 도메인 이름
이렇게 검색시에 SSL/TLS 가 잘 적용이 되는것도 확인 해야함.
결론
🙋 궁금했던 점
1) 왜 SSL/TLS 인증서 발급을 WAS 가 아닌, 웹 서버(nginx,apache) 에서 할까요?
- 트래픽 처리 및 보안:
- 웹 서버는 클라이언트(브라우저)와 서버 간의 모든 트래픽을 처리합니다. SSL/TLS 인증서는 이 트래픽을 암호화하여 중간에서 데이터를 탈취하는 것을 방지합니다.
- 웹 서버가 앞단에서 트래픽을 처리하고 암호화/복호화를 수행함으로써 WAS는 오직 내부 트래픽만 처리하게 되어 보안 및 성능이 향상됩니다.
- 부하 분산 및 리버스 프록시:
- Nginx와 Apache는 주로 리버스 프록시로 사용됩니다. 이는 클라이언트 요청을 받아서 적절한 WAS로 전달하는 역할을 합니다.
- SSL/TLS 처리는 리버스 프록시가 가장 앞단에서 처리하는 것이 일반적입니다. 이렇게 하면 여러 WAS가 있을 때 각각의 서버에 SSL/TLS 설정을 하지 않아도 되며, 중앙에서 인증서를 관리할 수 있습니다.
- 간편한 관리 및 자동화:
- Certbot 같은 도구는 Nginx나 Apache와 쉽게 통합되어 SSL/TLS 인증서의 발급과 갱신을 자동화할 수 있습니다. 이는 WAS에 직접 인증서를 설치하는 것보다 훨씬 간편합니다.
- Certbot은 웹 서버와 직접 연동되어 인증서 설치 및 갱신 절차를 자동으로 처리하므로, 수작업으로 관리하는 부담을 줄여줍니다.
- WAS의 제한 사항:
- 일부 WAS는 SSL/TLS 설정을 지원하지 않거나, 설정 과정이 복잡할 수 있습니다. 반면, 웹 서버는 SSL/TLS 설정과 관리에 최적화되어 있어 이를 쉽게 처리할 수 있습니다.
따라서 was 보다는 웹 서버에서 SSL/TLS 를 관리함으로써 다양한 이점을 얻을 수 있기 때문입니다.