Python Flask - Flask 서버에 무료 SSL 인증서 적용하는 방법 (Windows, win-acme, NginX)

반응형

무료 인증서를 발급 받기 위해 Let's Encrypt의 SSL 인증을 받아야 할 때,

보통 서버(Apache, NginX 등)를 이용하여 웹 루트를 정하고 인증을 받는 방식으로 진행한다.

특히 윈도우에서 win-acme 도구를 이용하여 무료 SSL 인증서 발급 시

보통 파일 방식으로 인증을 받는 식인데, 문제는 여기서 발생한다.

Flask의 경우에는 서버 자체에서 특정 URL의 경로를 미리 정의해주지 않으면 안된다는 것이다.

하지만 win-acme 도구는 사이트 인증 시 내가 지정한 웹 루트에

랜덤으로 주어진 코드가 적혀있는 파일이 생성되는데,

이런 동적인 상황에 생성되는 랜덤 주소 URL 링크를 미리 알 방법이 없다.

예를 들어, 내가 지정한 웹 루트에 '.well-known/acme-challenge/랜덤값' 이 주어지는데,

이 랜덤값을 미리 알 수 없으니 SSL 인증을 위해 해당 주소를 사전에 정의할 수 없다는 것이다.

 

이 글은,

1) 윈도우 운영체제에서

2) 엔진엑스를 이용하여

3) 파이썬 플라스크 서버를

4) win-acme 도구를 통해 네트워크 경로의 파일 방식으로 

무료 SSL 인증서를 발급 받을 수 있도록 인증하는 방법에 대해 다룬다.

 

이 글은 Flask 서버에 한정되어 SSL 인증을 받을 수 있는 방법을 설명한다.

윈도우에서 무료 SSL 인증서를 발급받고자 한다면 아래의 글을 확인하자.

 

Nginx 설정

우선 win-acme 도구를 통해 해당 경로의 파일을 생성할 수 있도록 엔진엑스를 설정해주자.

location 부분에 /.well-known/acme-challenge/ 경로 접근 시 생성될 디렉토리를 지정해준다.

플라스크 서버는 기본적으로 파일을 다루는 디렉토리의 기본 경로는 static이다.

때문에 가능하면 플라스크가 구동되고 있는 프로젝트 루트 디렉토리에서

하위 디렉토리인 'static'으로 SSL 인증을 받을 수 있도록 경로를 지정해주자.

내 경우엔 FlaskBlogServer 라는 프로젝트 디렉토리의 static 디렉토리를 지정해두었다.

그러면 SSL 인증 시 생성될 디렉토리 구조는

'C:\WorkSpace\FlaskBlogServer\static\.well-known\acme-challenge\파일이름'이 된다.

# 설정 예시
server {
    listen          80; # Python Flask Auto Posting Server
    server_name     post.eunbyeol.co.kr;
    return 301      https://$server_name$request_uri;

    location /.well-known/acme-challenge/ {
        root        C:/WorkSpace/FlaskBlogServer/static;
    }

 

Flask Routes 설정

가장 중요한 부분이다.

동적으로 생성되는 파일의 값을 허용하기 위해서는

요청되는 루트의 뒷 부분의 값을 문자열로 받아 처리할 수 있도록 해야 한다.

나는 여기서 경로의 마지막 부분의 값을 변수로 받아 생성된 파일을 다시 리턴할 수 있도록 하였다.

# 블루 프린트 등록
routesBp = Blueprint('routes', __name__, template_folder='../templates')

# SSL 인증을 받기 위한 경로 설정
@routesBp.route('/.well-known/acme-challenge/<path:filename>')
def serve_acme_challenge(filename):
    return send_from_directory('static/.well-known/acme-challenge', filename)
  • send_from_directory : 서버에서 특정 디렉토리 내에 있는 파일을 클라이언트로 전송할 때 사용하는 함수이다. 파일 다운로드 기능이나 동적으로 파일을 제공할 때 유용하게 사용할 수 있다.

이로써 SSL 인증을 받기 위한 Nginx와 Flask의 설정이 끝났다.

 

win-acme로 인증 받기

인증을 진행해보자.

win-acme를 실행하여 차례대로 아래의 과정을 진행한다.

 

  • Please choose from the menu:
    • M: Create certificate (full options)
  • How shall we determine the domain(s) to include in the certificate?:
    • 2: Manual input
  • Host:
    • SSL 인증받을 본인 웹 사이트 주소 입력 (예시: post.eunbyeol.co.kr)
  • Friendly name '[Manual] post.eunbyeol.co.kr'. <Enter> to accept or type desired name:
    • 그냥 Enter로 진행
  • Would you like to split this source into multiple certificates?:
    • 1: Separate certificate for each domain (e.g. *.example.com)
  • How would you like prove ownership for the domain(s)?:
    • 1: [http] Save verification files on (network) path
  • Path:
    • Flask 프로젝트의 static 경로 입력 (예시: C:\WorkSpace\FlaskBlogServer\static)
  • Copy default web.config before validation? (y/n*)
    • N
  • What kind of private key should be used for the certificate?:
    • 2: RSA key
  • How would you like to store the certificate?:
    • 2: PEM encoded files (Apache, nginx, etc.)
  • File path:
    • SSL 인증서가 저장될 경로 입력 (예시: C:\dev\nginx-1.26.1\ssl)
  • Choose from the menu:
    • 1: None
  • Would you like to store it in another way too?:
    • 5: No (additional) store steps
  • Which installation step should run first?:
    • 3: No (additional) installation steps

 

입력을 모두 마치면 인증이 진행되며, 지정한 경로에 .pem 파일이 생성된다.

생성된 파일로 SSL을 적용하면 된다.

win-acme 도구를 통해 flask 서버의 ssl 인증서를 발급 받은 결과 화면

 

NginX에 SSL 인증서 적용하기

http 주소를 https로 리다이렉트 하기

우선 https로 접속할 수 있게 http로 접속 시 리다이렉트를 해줄 수 있도록 하자.

확인해봐야할 부분은 'return 301'이다.

요청받은 주소를 https로 변경하여 접속할 수 있도록 해준다.

아래는 예시 코드이다.

server {
    listen          80; # Python Flask Auto Posting Server
    server_name     post.eunbyeol.co.kr;
    return 301      https://$server_name$request_uri; # https로 리다이렉트
}

 

https의 SSL 인증서 적용하기

위의 과정을 통해 발급 받은 pem 인증 파일을 Nginx에 등록해주자.

win-acme에서 지정한 SSL 파일 저장 경로에 존재하는 pem 파일을

아래의 예시를 보고 자신에게 맞게 변경하여 넣어주자.

server {
    listen          443 ssl;
    server_name     post.eunbyeol.co.kr;

    ssl_certificate C:/dev/nginx-1.26.1/ssl/post.eunbyeol.co.kr-crt.pem;
    ssl_certificate_key C:/dev/nginx-1.26.1/ssl/post.eunbyeol.co.kr-key.pem;
    ssl_trusted_certificate C:/dev/nginx-1.26.1/ssl/post.eunbyeol.co.kr-chain.pem;

    location / {
        proxy_pass  http://192.168.0.78:4002/;
    }
}

 

변경사항을 적용할 수 있도록 엔진엑스를 리로드해주고,

만약 플라스크 서버가 켜져있다면 서버 또한 재시작해준다.

그리고 웹 사이트에 접속하면 정상적으로 SSL이 적용되어

https로 페이지를 보여주는 것을 확인할 수 있다.

SSL 인증서를 적용하고 난 후 웹 사이트에 접속하여 https로 이상없이 접속되는 것을 확인하는 예시 이미지

반응형