본문 바로가기
BACKEND

Ubuntu 웹서버에 무료 HTTPS 적용해 보기

by 드로니뚜벅이 2024. 10. 23.

HTTP(80) 는 보안에 취약하다는 건 모두 아는 사실입니다.

요즘 브라우저에서는 HTTP 사이트에 접속하면 주의 메시지를 출력합니다. 그래서 안전한 HTTPS를 사용하고 싶은데 이게 도메인 제공업체에서 유료로 제공되는 경우가 많습니다. 무료로 서비스할 수 있는 방법이 없을까요?

 

여기서는 구글링으로 참고할 자료가 많은 nginx를 사용해서 구현해 보겠습니다.

nginx가 SSL 설정이 간단하고, Load balancing과 HTML CSS 등의 정적 리소스를 제공하는데 용이하다는 장점이 있다고 하니 믿고 적용해 보겠습니다.

 

1. nginx 설치

먼저 HTTPS 를 적용하기 위해 nginx를 설치합니다.

$ sudo apt install nginx
$ sudo service nginx start
$ sudo service nginx status

 

 

2. 인증서 발급 준비

무료 인증서 발급 기관(CA)으로 ZeroSSL이나 Let's Encrypt 가 있으며 여기서 제공하는 서비스를 많이들 사용하고 있는 것 같습니다. 저는 여기서 Let's Encrypt를 사용해 보겠습니다.

Let's Encrypt가 추천하는 인증서 발급 프로그램(ACME 클라이언트)인 Certbot을 통해 이메일과 도메인만으로 빠르고 쉽게 발급받을 수 있습니다.

(혹시, 이전에 apt 와 같은 패키지 관리자로 Certbot 패키지를 설치했다면 먼저 삭제하고 Certbot 을 설치합니다.)

$ sudo apt remove certbot
$ sudo snap install --classic certbot
certbot 2.11.0 from Certbot Project (certbot-eff) installed
$

설치가 되었다면 certbot 명령어를 커멘드 라인 (터미널)에서 실행할 수 있도록 심볼릭 링크를 설정해 줍니다. (일반적으로 데비안 계열 리눅스에서는 설치 후 자동으로 경로설정이 됩니다. certbot 명령어를 바로 입력할 수 없는 경우에 해당합니다.)

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

여기까지, 인증서 발급을 위해 필요한 모든 준비를 마쳤습니다.

 

3. 인증서 발급

모든 준비를 마쳤으니 certbot을 통해 인증서를 발급하는 명령어를 실행해야 합니다.

그런데, 인증서 발급받는 방법은 두 가지가 있습니다.

첫 번째는 명령어 하나로 자동으로 인증서를 발급한 후 필요한 설정까지 해 주는 방법이고,

두 번째는 명령어로 인증서만 발급받고 SSL과 같은 설정은 직접 수동으로 작성하는 방법입니다.

($ sudo certbot certonly --nginx)

저는 좀 더 쉬워 보이는 첫 번째 방법으로 발급받아 보겠습니다.

형식: $ sudo certbot --nginx -d { MY DOMAIN }
$ sudo certbot --nginx -d oottagiya.com -d www.oottagiya.com -d dev.oottagiya.com
...
Successfully received certificate.

이렇게 발급 받은 인증서는 90일 동안 유효합니다. 따라서, 60일마다 자동으로 갱신하는 것이 좋다고 합니다.

 

4. nginx에 SSL 적용하기

인증서를 적용할 사이트에 대한 nginx를 설정합니다.

$ cd /etc/nginx/sites-available
$ vi default

default 파일은 nginx 설치 시 자동으로 설치된 파일입니다. 편집해도 상관없지만 편의상 삭제하고 아래처럼 필요한 내용만 입력합니다.

server {
    listen 443 ssl; # 443 포트의 요청을 받음
    server_name oottagiya.com; # 도메인 지정

    location / { 
        root /home/yunix/webserver/frontend/dist; # 빌드된 프론트엔드의 파일 위치
        index index.html; # 렌더링 해줄 html 파일 이름 
        try_files $uri $uri/ /index.html; # 사용자가 존재하지 않는 uri로 요청시 index.html을 보여줌
    }

    ssl_certificate /etc/letsencrypt/live/oottagiya.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/oottagiya.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

server {
    listen 80; # 80 포트의 요청을 받음
    server_name oottagiya.com;
    return 301 https://oottagiya.com$request_uri; # 동일한 uri를 https로 리다이렉트
}

위 내용은 https://oottagiya.com 으로 요청이 오면 index.html을 띄워주는 내용입니다. 단, http://oottagiya.com 으로 요청이 오면 https(443)으로 리다이렉션해 줍니다.

 

 

4-1. SSL 관련 설정

ssl_certificate

certbot이 발급해 준 fullchain.pem 경로를 지정합니다. (/etc/letsencrypt/{위에서 인증서 발급받는 도메일}/fullchain.pem으로 작성해도 됩니다)

 

ssl_certificate_key

certbot이 발급해 준 privkey.pem의 경로를 지정합니다. 위치는 ssl_certificate와 동일합니다. (/etc/letsencrypt/{위에서 인증서 발급받는 도메일}/privkey.pem)

 

option-ssl-nginx-conf

ssl의 session_cache, session_timeout, ssl_protocols 등의 설정 정보가 있습니다.

 

ssl_dhparam

 

4-2. 설정 파일 문법 체크

아래 명령어로 nginx 문법에 맞게 수정되었는지 문법을 체크합니다.

$ sudo nginx -t
$ sudo nginx -s reload

 

 

5. 심볼링 링크 설정

sites-available

웹사이트의 구성 정보를 설정하는 곳입니다.

 

sites-enabled

sites-available 에서 구성한 사이트 중  nginx에서 실제로 사용하고자 하는 사이트의 심볼릭 링크를 가지는 디렉토리입니다.

 

/etc/nginx/sites-available/{설정파일} 을 /etc/nginx/sites-enabled/ 폴더에 심볼릭 링크를 생성해 줍니다. 

$ sudo ln -s /etc/nginx/sites-available/oottagiya.com.conf /etc/nginx/sites-enabled/

 

 

6. ngix 재시작

$ sudo service nginx restart # or > sudo nginx -s reload

 

 

7. HTTPS로 재접속

https://www.oottagiya.com으로 웹페이지에 접속되는지 확인합니다.

http://www.oottagiya.com 으로 접속해도 https://www.oottagiya.com 으로 리다이렉션되는지 확인합니다.

 

 

8. 백엔드 서버도 HTTPS 적용

프론트엔드와 동일하게 설정하면 됩니다.

server {
    listen 443 ssl; # 443 포트의 요청을 받음
    server_name dev.oottagiya.com; # 도메인 지정

    location / {
        proxy_pass http://{백엔드 서버 IP}:8080; // localhost로 요청 위임
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
    }
    ssl_certificate  /etc/letsencrypt/live/dev.oottagiya.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dev.oottagiya.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

server {
    listen 80; # 80 포트의 요청을 받음
    server_name dev.oottagiya.com;
    return 404; # http로 요청하면 404 응답
}

 

location

프론트엔드 설정과 좀 다르지요?

 

proxy_pass

nginx는 서버에 대한 요청을 처리할 수 없기 때문에 백엔드 서버에게 요청을 위임해야 하기 때문에 서버가 동작하고 있는 주소를 지정해 줍니다.

 

header

x-forwarded-for

클라이언트의 IP 주소를 식별하는 표준 헤더로 $proxy_add_x_forwarded_for 로 설정해 줍니다.

이렇게 설정해 주면 클라이언트 IP를 x-forwared-for 헤더에 append 해 줍니다.

x-forwarded-proto

클라이언트가 프록시(nginx)로 요청을 보낼 때의 프로토콜로, $scheme로 설정해 줍니다.

x-real-ip

바로 직전의 클라이언트의 IP를 나타냅니다. 

 

설정파일에서 proxy_set_header로 헤더를 설정하면 서버로 들어오는 요청에 대한 로킹 정보는 아래와 같습니다.

<생략> 추후 추가됩니다.

###### HTTP Request ######
GET /boards/contents HTTP/1.0
x-forwarded-for: 210.110.23.14 # $proxy_add_x_forwarded_for 로 설정
x-forwarded-proto: https # $scheme 로 설정
x-real-ip: 210.110.23.14 # $remote_addr로 설정
host: dev.oottagiya.com # $http_host 로 설정
connection: close

 

9. SSL 인증서 갱신

안타깝게도 Let's Encrypt 인증서는 발급된 시점에서 90일(3개월)로 제한되어 있기 때문에 만료되기 전에 갱신해 줘야 합니다. 하지만 다행스럽게도 갱신하는 방법도 제공해 주고 있기 때문에 설명 내용을 참고하세요.

$ sudo certbot renew --dry-run

 

 

참고사이트

 

 

 

 

 

 

'BACKEND' 카테고리의 다른 글

자빅스(Zabbix) 모니터링 시스템  (0) 2022.12.06