python flask 웹서버 https SSL인증서

·2021년 11월 4일
2

https 접속을 가능하게 해주는 무료SSL인증서인 Let's Encrypt가 있다는 건 알겠는데, flask로 구현한 내 간단한 웹앱에 이걸 어떻게 적용해야하는지 딱 원하는 정보를 찾기가 어려웠다. 그러다 찾은 아래 글, 한글로 된 자료가 있으면 더 좋았겠지만 이 글이 정말 친절해서 다행이었다!
참조: https://blog.miguelgrinberg.com/post/running-your-flask-application-over-https

1. https로 접속되게 하는 가장 간단한 방법

  1. CLI 명령어: pip(또는 pip3) install pyopenssl
  2. flask 소스코드에 아래처럼 ssl_context='adhoc'를 추가
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(ssl_context='adhoc')
  1. CLI 명령어: flask run --cert=adhoc

이렇게 하고 https:// 를 붙여서 접속(로컬에서 하고 있다면 https://127.0.0.1:5000)하면 일단 접속은 된다. 다만, 아래 그림처럼 매우 불길한 경고메시지와 함께 주소창에 '주의요함'이 뜨고, "고급"을 눌러 불길하기 짝이 없는 "127.0.0.1(안전하지 않음)(으)로 이동"을 눌러야만 접속할 수 있게 된다.
(차라리 http가 더 안전해보임) -> 글쓴이도 테스트만 하고 절대 실제 사용되는 사이트에 사용하지 말라고 하고 있다.

2. Self-Signed Certificates 자체 서명된 인증서

이 방법은 서버에서 인증서를 생성하여, 신뢰할 수 있는 발급기관 또는 최상위인증기관, 정확히 모르겠으나 여튼 그런 이름으로 불리는 CA Certificate Authority 를 거치지 않고 내가 스스로 인증서도 만들고 거기에 스스로 서명하는, 즉 내 서버가 스스로 인증기관이 되는 것이다. 따라서 접속하는 유저, 사용자 입장에서는 신뢰할 수 있는 상위기관에서 인증해준 인증서가 아니므로 해당 서버 자체를 신뢰할 수 없다면 보안을 보장할 수 없다라고 브라우져가 판단해서 경고를 띄운다. 브라우져는 CA 목록을 갖고 있어서, 거기에 등록된 인증서가 아니면 신뢰할 수 없는 인증서로 판단한다는 것 같다.(내가 이해한 게 맞다면!)
자세한 원리를 위한 참조: https://m.blog.naver.com/alice_k106/221468341565

  1. CLI명령어: openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365
    openssl만 설치되어있다면 위 명령어를 통해 간단히 인증서를 만들어낼 수 있다.(입력란이 몇 개 나온다. country Name을 두 글자로.. KR, 그 외에 Seoul 등 입력해주었다.
openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 
Generating a 4096 bit RSA private key
..........................++
..........................................................................................................................................................................................................................................................................++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:KR
State or Province Name (full name) []:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) []:LetYourLightShine
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:localhost
Email Address []:  
  1. 이제 위 소스코드를 아래처럼 수정해준다.
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(ssl_context=('cert.pem', 'key.pem'))
  1. CLI명령어: flask run --cert=cert.pem --key=key.pem
    https://127.0.0.1:5000
    접속해보면 역시나 엄청난(?) 경고메시지가 뜬다. 주소창 왼쪽에 붉은색 "주의 요함"을 눌러서 인증서 정보를 열어보면 아래와 같이 방금 내가 생성했던 그 인증서 정보가 뜨고, '자체 서명된 루트 인증서'라고 알려준다.

3. 진짜 인증서 쓰기?

이걸 하다 보니, flask웹서버를 그대로 실제 production 환경에서 쓰는 일은 웬만해선 해서는 안되는 일이라는 이야기를 많이 보게 되었다. flask나 django처럼 파이썬으로 짠 웹서버애플리케이션 자체만으로도 웹브라우져에서 접속도 되고 테스트는 충분히 할 수 있지만, 실제로 서비스를 제공하는 환경에서는 앞에 apache나 nginx 웹서버를 통해 클라이언트들의 요청을 받아들이고, 그것들을 다시 WSGI서버(gunicorn이나 uWSGI를 많이 쓴다고 한다)를 통해 flask나 django같은 애플리케이션으로 전달하도록 연동해서 서버를 구축해야하고, 제대로 된 https연결은 그 환경을 먼저 구축한 뒤에 작업하는 것이었다!
https://leffept.tistory.com/345
https://wiznxt.tistory.com/814

references 정리
https://blog.miguelgrinberg.com/post/running-your-flask-application-over-https
https://m.blog.naver.com/alice_k106/221468341565
https://leffept.tistory.com/345
https://wiznxt.tistory.com/814

profile
백엔드 개발자. 공동의 목표를 함께 이해한 상태에서 솔직하게 소통하며 일하는 게 가장 즐겁고 효율적이라고 믿는 사람.

0개의 댓글