무료 인증서를 발급 받기 위해 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을 적용하면 된다.
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로 페이지를 보여주는 것을 확인할 수 있다.