PromleeBlog
sitemap
aboutMe

posting thumbnail
HTTPS와 SSL 인증서로 웹 서버 보안 강화 - 코딩과 함께 배우는 네트워크 13일차
Securing Web Server with HTTPS and SSL Certificates - Learning Network with Coding Day 13

📅

🚀

들어가기 전에 🔗

지난 시간에는 Python으로 직접 TCP 채팅 애플리케이션을 만들어보는 실습을 통해 TCP 프로토콜의 기본 개념과 소켓 프로그래밍을 배웠습니다.
오늘은 우리가 매일같이 주고받는 웹 데이터의 보안을 한층 강화하는 기술, 바로
HTTPS
와 그 핵심 요소인
SSL/TLS 인증서
에 대해 깊이 있게 알아보겠습니다.
단순히 HTTP에 'S' 하나 붙었을 뿐이지만, 그 뒤에는 복잡하고 정교한 암호화와 인증 과정이 숨어있습니다.
Python을 이용해 간단한 HTTPS 웹 서버를 직접 구축하고, 자체 서명 인증서를 만들어 적용해보겠습니다.

🚀

HTTPS와 SSL/TLS: 왜 필요할까요? 🔗

참고: HTTP와 HTTPS 웹의 언어 - 코딩과 함께 배우는 네트워크 6일차
우리가 6일차에 배웠던 HTTP는 데이터를 암호화하지 않고 그대로 주고받기 때문에, 중간에 누군가가 데이터를 엿보거나(도청), 내용을 바꿔치기(변조)할 위험이 있었습니다.
특히 로그인 정보, 개인 정보, 결제 정보 같은 민감한 데이터를 HTTP로 주고받는 것은 매우 위험합니다.

이러한 문제를 해결하기 위해 등장한 것이 바로
HTTPS(HyperText Transfer Protocol Secure)
입니다.
HTTPS는 HTTP 통신 내용을
SSL(Secure Sockets Layer)
또는 그 후속 기술인
TLS(Transport Layer Security)
라는 프로토콜을 이용해 암호화하여 안전하게 보호합니다.


SSL/TLS의 주요 역할

🚀

SSL 인증서란 무엇일까요? 웹 서버의 디지털 신분증 🔗

HTTPS 통신에서 서버를 인증하고 암호화 통신에 필요한 정보(공개키)를 제공하는 것이 바로
SSL/TLS 인증서
입니다.
이 인증서는 신뢰할 수 있는 제3자 기관인
인증 기관(CA, Certificate Authority)
에 의해 발급되며, 웹 서버의 신원을 보증하는 일종의 디지털 신분증 역할을 합니다.
SSL 인증서
SSL 인증서

SSL 인증서에 포함된 주요 정보 🔗

웹 브라우저는 웹사이트 접속 시 이 SSL 인증서를 확인하여, 해당 사이트가 신뢰할 수 있는지, 그리고 안전한 암호화 통신을 할 준비가 되었는지 판단합니다.

SSL 인증서의 종류 🔗

발급 시 검증 수준에 따라 여러 종류가 있습니다.

🚀

실습 1: 로컬 테스트용 자체 서명 SSL 인증서 만들기 - OpenSSL 사용 🔗

실제 웹 서비스를 운영하려면 신뢰할 수 있는 CA로부터 SSL 인증서를 발급받아야 하지만, 개발이나 로컬 테스트 목적이라면 우리가 직접
자체 서명 인증서(Self-signed Certificate)
를 만들어 사용할 수 있습니다.
자체 서명 인증서는 CA의 보증 없이 스스로 서명한 인증서이므로, 공용 인터넷에서는 신뢰받지 못하지만(브라우저 경고 발생), 로컬 환경에서 HTTPS 기능을 테스트하는 데는 유용합니다.

여기서는
OpenSSL
이라는 오픈 소스 도구를 사용하여 자체 서명 인증서와 개인키를 생성해 보겠습니다.
OpenSSL은 대부분의 리눅스와 macOS에는 기본적으로 설치되어 있으며, 윈도우 사용자는 별도로 설치해야 할 수 있습니다.

터미널(명령 프롬프트)에서 다음 명령어를 순서대로 입력합니다.
  1. 개인키(Private Key) 생성 (server.key)
    openssl genrsa -out server.key 2048
    • genrsa: RSA 개인키를 생성하는 명령어입니다.
    • -out server.key: 생성된 개인키를 server.key라는 파일로 저장합니다.
    • 2048: 2048비트 길이의 키를 생성합니다. (일반적으로 권장되는 길이)
  2. 인증서 서명 요청(CSR - Certificate Signing Request) 생성 (server.csr)
    openssl req -new -key server.key -out server.csr
    • req: 인증서 요청 및 생성 관련 명령어입니다.
    • -new: 새로운 CSR을 생성합니다.
    • -key server.key: 위에서 생성한 개인키(server.key)를 사용합니다.
    • -out server.csr: 생성된 CSR을 server.csr 파일로 저장합니다.
    • 이 명령을 실행하면 국가, 도시, 회사 이름, 도메인 이름(Common Name) 등을 입력하라는 메시지가 나옵니다. 로컬 테스트용이므로 간단히 입력하거나 엔터를 눌러 기본값으로 넘어가도 됩니다.
      Common Name에는 localhost를 입력하는 것이 좋습니다.
  3. 자체 서명 인증서(Self-Signed Certificate) 생성 (server.crt)
    openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
    • x509: X.509 표준 인증서 처리 명령어입니다.
    • -req: 입력이 CSR임을 나타냅니다.
    • -days 365: 인증서의 유효 기간을 365일로 설정합니다.
    • -in server.csr: 위에서 생성한 CSR(server.csr)을 입력으로 사용합니다.
    • -signkey server.key: 개인키(server.key)로 서명합니다. (자체 서명)
    • -out server.crt: 생성된 인증서를 server.crt 파일로 저장합니다.
이제 현재 디렉터리에 server.key(개인키) 파일과 server.crt(자체 서명 인증서) 파일이 생성되었을 것입니다. 이 두 파일이 HTTPS 서버를 만드는 데 사용됩니다.
SSL 인증서 생성
SSL 인증서 생성

🚀

실습 2: Python으로 간단한 HTTPS 웹 서버 만들기 🔗

Python의 http.server 모듈과 ssl 모듈을 이용하여 매우 간단한 HTTPS 웹 서버를 만들어 보겠습니다.
import http.server # 기본적인 HTTP 서버 기능을 제공하는 모듈
import ssl # SSL/TLS 기능을 제공하는 모듈
import socketserver # 고급 소켓 서버 기능을 제공하는 모듈 (여기서는 TCP 서버 기반)
 
  # 서버 설정
HOST = 'localhost' # 또는 '0.0.0.0' (모든 인터페이스에서 접속 허용)
PORT = 8443        # HTTPS 기본 포트는 443이지만, 테스트용으로 다른 포트 사용
 
  # 사용할 SSL 인증서 파일 경로 (위에서 생성한 파일들)
CERT_FILE = 'server.crt' # 자체 서명 인증서 파일
KEY_FILE = 'server.key'  # 개인키 파일
 
  # 간단한 요청 핸들러 정의 (기본 SimpleHTTPRequestHandler 사용)
  # 이 핸들러는 현재 디렉터리의 파일들을 웹으로 제공합니다.
Handler = http.server.SimpleHTTPRequestHandler
 
  # TCP 서버 생성 (아직 SSL 적용 전)
  # socketserver.TCPServer를 사용하면 다중 요청 처리가 더 용이합니다.
httpd = socketserver.TCPServer((HOST, PORT), Handler)
 
  # SSL 컨텍스트 생성 및 설정
  # ssl.PROTOCOL_TLS_SERVER는 최신 TLS 프로토콜 버전을 사용하도록 권장됩니다.
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
  # 생성한 인증서 파일과 개인키 파일을 로드합니다.
ssl_context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
 
  # 생성한 TCP 서버 소켓을 SSL 소켓으로 래핑(Wrapping)합니다.
httpd.socket = ssl_context.wrap_socket(httpd.socket, server_side=True)
 
print(f"[*] HTTPS 서버가 https://{HOST}:{PORT} 에서 실행 중입니다...")
print("[*] 웹 브라우저에서 위 주소로 접속하세요.")
print("[*] (자체 서명 인증서이므로 브라우저에서 보안 경고가 나타날 수 있습니다.)")
print("[*] Ctrl+C를 눌러 서버를 종료할 수 있습니다.")
 
try:
    # 서버 실행 (요청을 계속 처리)
    httpd.serve_forever()
except KeyboardInterrupt:
    print("\n[*] HTTPS 서버를 종료합니다.")
finally:
    httpd.server_close() # 서버 소켓 닫기
    print("[*] 서버가 안전하게 종료되었습니다.")

실행 방법 🔗

  1. 위 OpenSSL 명령어로 server.keyserver.crt 파일을 먼저 생성합니다.
  2. 위 Python 코드를 https_server.py와 같이 저장합니다. (인증서 파일들과 같은 디렉터리에 저장하면 경로 지정이 편합니다.)
  3. 터미널에서 python https_server.py 명령으로 서버를 실행합니다.
https 서버 실행
https 서버 실행

🚀

브라우저로 HTTPS 서버 접속 및 보안 통신 확인 🔗

  1. 웹 브라우저 실행
    크롬, 파이어폭스, 엣지 등 웹 브라우저를 엽니다.
  2. 주소 입력
    주소창에 https://localhost:8443 (또는 설정한 HOST와 PORT)을 입력하고 엔터를 칩니다. http가 아닌 https로 시작해야 합니다!
  3. 보안 경고 확인 (자체 서명 인증서의 경우)
    :
    • 자체 서명 인증서를 사용했기 때문에, 브라우저는 이 인증서를 신뢰할 수 없다는 보안 경고를 표시할 가능성이 매우 높습니다. (예: "연결이 비공개로 설정되어 있지 않습니다", "경고: 잠재적인 보안 위험Ahead")
    • 이는 정상적인 현상입니다. CA로부터 발급받은 인증서가 아니기 때문입니다.
    • 경고 페이지에서 "고급(Advanced)" 또는 "위험을 감수하고 진행(Proceed to localhost (unsafe))" 등의 옵션을 클릭하여 예외적으로 사이트에 접속합니다.
    보안 경고 확인
    보안 경고 확인
  4. 자물쇠 아이콘 및 인증서 정보 확인
    :
    • 경고를 지나 사이트에 접속되면, 주소창 옆에 자물쇠 아이콘이 (보통은 경고 표시와 함께) 나타나는지 확인합니다.
    • 자물쇠 아이콘을 클릭하면 연결이 안전하지 않다는 메시지와 함께 인증서 정보를 볼 수 있는 옵션이 나옵니다.
    • 인증서 정보를 열어보면 우리가 OpenSSL로 생성할 때 입력했던 정보(Common Name: localhost 등)와 발급자(Issuer) 정보가 자신으로 되어 있는 것을 확인할 수 있습니다.
    인증서 정보
    인증서 정보
    인증서 세부정보
    인증서 세부정보
이 실습을 통해 HTTPS 통신이 어떻게 이루어지는지, SSL 인증서가 어떤 역할을 하는지 직접 경험할 수 있습니다.
실제 서비스에서는 반드시 신뢰할 수 있는 CA로부터 인증서를 발급받아 사용해야 합니다.

🚀

HTTPS 적용의 중요성과 이점 🔗


🚀

결론 🔗

오늘은 웹 통신의 보안을 책임지는 HTTPS와 SSL/TLS 인증서에 대해 배우고, 직접 자체 서명 인증서를 만들어 Python으로 간단한 HTTPS 웹 서버를 구축하는 실습까지 진행했습니다.
자체 서명 인증서로 인해 브라우저에서 보안 경고가 뜨는 것을 보았지만, 이를 통해 SSL 인증서가 신뢰할 수 있는 CA를 통해 발급되어야 하는 이유를 더욱 명확히 알 수 있었습니다.

다음 시간에는 지금까지 배운 네트워크 지식을 총정리하고, 앞으로 더 깊이 있는 학습을 위한 로드맵을 그려보는 시간을 갖겠습니다.

참고 🔗