[Nginx] Docker환경에서 Nginx 웹 서버에 SSL/TLS 적용하기

728x90

안녕하세요👋

오늘은 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 적용한 사이트

 

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은 역할은

  1. 인증서 발급: 도메인 소유권을 검증한 후 SSL/TLS 인증서를 발급받습니다.
  2. 자동 갱신: 발급받은 인증서를 자동으로 갱신해 줍니다. (따로 설정 해야함)
  3. 간편한 설치: 대부분의 웹 서버(예: 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) 에서 할까요?

 

  1. 트래픽 처리 및 보안:
    • 웹 서버는 클라이언트(브라우저)와 서버 간의 모든 트래픽을 처리합니다. SSL/TLS 인증서는 이 트래픽을 암호화하여 중간에서 데이터를 탈취하는 것을 방지합니다.
    • 웹 서버가 앞단에서 트래픽을 처리하고 암호화/복호화를 수행함으로써 WAS는 오직 내부 트래픽만 처리하게 되어 보안 및 성능이 향상됩니다.
  2. 부하 분산 및 리버스 프록시:
    • Nginx와 Apache는 주로 리버스 프록시로 사용됩니다. 이는 클라이언트 요청을 받아서 적절한 WAS로 전달하는 역할을 합니다.
    • SSL/TLS 처리는 리버스 프록시가 가장 앞단에서 처리하는 것이 일반적입니다. 이렇게 하면 여러 WAS가 있을 때 각각의 서버에 SSL/TLS 설정을 하지 않아도 되며, 중앙에서 인증서를 관리할 수 있습니다.
  3. 간편한 관리 및 자동화:
    • Certbot 같은 도구는 Nginx나 Apache와 쉽게 통합되어 SSL/TLS 인증서의 발급과 갱신을 자동화할 수 있습니다. 이는 WAS에 직접 인증서를 설치하는 것보다 훨씬 간편합니다.
    • Certbot은 웹 서버와 직접 연동되어 인증서 설치 및 갱신 절차를 자동으로 처리하므로, 수작업으로 관리하는 부담을 줄여줍니다.
  4. WAS의 제한 사항:
    • 일부 WAS는 SSL/TLS 설정을 지원하지 않거나, 설정 과정이 복잡할 수 있습니다. 반면, 웹 서버는 SSL/TLS 설정과 관리에 최적화되어 있어 이를 쉽게 처리할 수 있습니다.

 

따라서 was 보다는 웹 서버에서 SSL/TLS 를 관리함으로써 다양한 이점을 얻을 수 있기 때문입니다.

728x90