[Nginx] SSL 적용하기

Coastby·2023년 3월 15일
1

Daengnyang 프로젝트

목록 보기
9/12

SSL 인증서 적용

📌 SSL/TLS

SSL(Secure Socket Layer) 또는 TLS(Transport Layer Security)은 전송계층 상에서 클라이언트, 서버에 대한 인증 및 데이터 암호화를 수행한다. 클라이언트와 서버 양단 간 응용계층 및 TCP 전송계층 사이에서 안전한 보안 채널을 형성해주는 역할을 하는 보안용 프로토콜이다. 이 둘은 버전의 차이이며, 보통 SSL이라 통칭한다.

  • 응용계층 및 전송계층 사이에 위치하나 전송계층과 보다 밀접하게 동작한다.
  • 운반용 프로토콜 : TCP 또는 UDP
  • 사용 포트 : HTTPS의 경우, HTTP를 위한 SSL/TLS 보안 터널 형성을 위해, 443 사용
  • 주요 기능 : 상호 인증, 메세지 인증 (메세지 무결성), 메세지 압축 (디폴트 Null), 암호화용 세션 키 생성을 위한 키 교환 등

HTTPS(Hypertext Transfer Protocol Over SSL)는 SSL 위에 SSL을 적용한 HTTP로 보안을 강화한 전송 기능이다. 그래서 SSL 인증서 적용이 된 도메인만이 https:// 주소를 가질 수 있다.

📌 Let’s Encrypt

Let’s Encrypt는 무료로 TLS 인증서를 발급해주는 비영리기관이다. 무료인 대신 만료기한이 90일로 주기적으로 재발급해야 한다. 서비스를 운영한다면 더 보안등급이 높은 유료 인증서를 사용해야 한다.

CertBot (공식페이지)

CertBot은 Let’s Encrypt 인증서를 사용하여 HTTPS를 적용할 수 있게 하는 오픈 소스툴이다.

공식페이지에서는 Snap을 이용한 설치가 권장된다. 우리는 apt-get을 이용하여 다운받았다.

  1. apt 업데이트

    $ apt-get update
    $ apt-get upgrade
  2. certbot을 설치한다.

    $ apt-get install python3-certbot-nginx
  3. 설치된 certbot을 이용하여 도메인에 대한 SSL 인증서를 발급받는다.

    $ certbot certonly --nginx -d example.com
    • certonly : certbot 명령어로 인증서를 다운받고, 설치할 수 있다. 하지만 설치까지 진행하면 설정이 자동으로 된다. 따라서 certonly 옵션으로 인증서 다운만 받고 설정은 추후에 진행할 수 있다.
    • —nginx : 해당 도메인에 대한 소유주가 자신임을 인증하기 위해 이용할 플러그인이다. nginx에 대한 인증서 취득 및 설치가 자동으로 이루어진다.
  4. /etc/letsencrypt/live/example.com 경로에 5개의 파일 (4개의 pem, 1개의 README)가 생성되었는지 확인한다.

    $ ll /etc/letsencrypt/live/example.com

Nginx 설정

sites-available과 sites-enabled을 이용하던지, conf.d 디렉토리를 이용하여 conf 파일을 작성한다.

  1. nginx 메인 설정파일 확인

    $ cd /etc/nginx
    $ vi nginx.conf

    /etc/nginx/conf.d 아래에 있는 모든 .conf 파일, /etc/nginx/sites-enabled의 모든 파일들을 include한다.

    1) conf.d 디렉토리에 conf 파일은 작성만 하면된다.

    2) sites-available 디렉토리에 작성하면, 아래 명령어를 통해 심볼릭 링크를 만들어준다.

    $ sudo nginx -t    # 문법 확인
    $ sudo ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled
  1. test.conf 파일 작성

    example.com : 본인의 도메인 주소를 넣어준다.

    # 1)
    server {
      listen 80; # 80포트로 받을 때
      server_name example.com; # 도메인주소
      return 301 https://example.com$request_uri;
    
    }
    
    # 2)
    server {
      listen 443 ssl http2;
      server_name example.com;
    
      # ssl 인증서 적용하기
      ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
      
      location / { # location 이후 특정 url을 처리하는 방법을 정의(여기서는 / ->, 모든 request)
        proxy_pass https//localhost:9001; # Request에 대해 어디로 리다이렉트하는지 작성. 8443 -> 자신의 springboot app 이사용하는 포트
        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;
      }
    }
    
    # 3)
    server {
        if ($host = example.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
      listen 80;
      server_name example.com;
        return 404; # managed by Certbot
    }

    1) 80포트로 들어오는 요청 즉, http로 들어오는 모든 요청을 https로 리다이렉션을 한다.

    2) https://로 들어오는 요청을 서비스 중인 포트로 연결시켜준다.

    • proxy_pass : 프록시 주소, 백엔드 운영 서버 ip를 넣어준다.
    • proxy_set_header Host $http_host : HTTP Request의 Host 헤더 값, 클라이언트가 요청한 원래 호스트 주소
    • X-Real-IP $remote_addr: 실제 방문자의 원격 ip 주소
    • X-Forwarded-For $proxy_add_x_forwared_for : 클라이언트가 프록시 처리한 모든 서버의 IP 주소를 포함하는 목록
    • X-forwarded-Proto $scheme : HTTP의 구조로 http or https를 의미한다. HTTPS 서버 블록 내에서 사용할 경우 프록시 서버의 HTTP 응답이 HTTPS로 변환된다.

    3) 도메인 이름이 다르면 404 에러 처리를 한다.

  2. Nginx 재시작

    $ sudo service nginx restart

인증서 관련 명령어

  • 모든 명령어는 root 권한
  • 인증서 확인
    $ certbot certificates
  • 인증서 자동 갱신
    $ certbot renew --dry-run
  • 인증서 삭제
    $ certbot delete --cert-name {인증서 이름}

🚫 도메인으로 안 들어가진다.

도메인 적용되는데 시간이 걸리니 20분 정도 기다렸다가 하자.

🚫 에러

아래와 같은 에러 로그가 찍히고 화면은 502 Bad GateWay가 떴다.

nginx 에러로그 위치 : /var/log/nginx/error.log

2023/03/15 04:23:08 [error] 75117#75117: *94 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream, client: 51.89.5.185, server: daengnyang.site, request: "GET /.env HTTP/1.1", upstream: "https://127.0.0.1:9001/.env", host: "13.125.45.96"
2023/03/15 04:23:09 [error] 75117#75117: *96 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream, client: 51.89.5.185, server: daengnyang.site, request: "POST / HTTP/1.1", upstream: "https://127.0.0.1:9001/", host: "13.125.45.96"
2023/03/15 04:28:58 [error] 75117#75117: *99 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream, client: 205.169.39.84, server: daengnyang.site, request: "GET / HTTP/1.1", upstream: "https://127.0.0.1:9001/", host: "daengnyang.site"

⭕️ 해결

위의 에러로그를 검색하면 가장 많이 나오는 것이 설정파일 문제라고 한다.

nginx 설정에서 443으로 들어온 요청은 http로 우리 서비스와 연결시켜줬어야 하는데 https로 또 연결을 하고 있었다. 설정파일 수정하고 해결되었다.

참고
https://velog.io/@jihyunhillpark/2.-spring-boot-기반-앱-배포-Cerbot-인증서-발급과-SSL-적용
https://dallog.github.io/deploy-full-course3/

profile
훈이야 화이팅

0개의 댓글