Table of contents
TCP에 이어 암호화 통신을 지원하는 TLS 소스코드 예제이다.
TLS
Transport Layer Security
TCP위에서 동작
네트워크에서 Data를 안전하게 송신하기 위한 암호화 프로토콜
•
TLS 주요 특징
◦
데이터 암호화 → 대칭/비대칭( AES, RSA, ECC, ..) 암호화를 사용하여 기밀성(Confidentiality) 보장 (데이터 보호, 도청 방지)
◦
무결성 (Integrity) → 전송 중 데이터가 변경되지 않도록 HMAC을 사용하여 검증
◦
인증 (Authentication) → X.509 인증서를 사용하여 Server와 Client가 신뢰 할 수 있는지 확인
◦
TLS Handshake → 공개 키 기반 암호화(Public Key Cryptography)로 보안 세션 설정
TLS 상호인증 (Mutual TLS, mTLS)
•
Server뿐만 아니라 클라이언트도 인증서를 사용하여 자신을 인증하는 방식
◦
Server와 Client가 서로 신뢰할 수 있는 경우에만 연결을 허용
•
예제는.. Root CA가 다른 경우 연결 거부하도록 구현
1.
Server와 Client는 서로의 인증서를 검증하기 위해 신뢰할 수 있는 CA(Certificate Authority, 인증기관)를 사용한다.
2.
Server는 Client의 인증서를 검증하고, Client는 Server의 인증서를 검증한다.
3.
서로의 인증서가 동일한 Root CA에서 발급되었는지 확인
a.
Root CA가 동일하다면 ? 연결 
b.
Root CA가 다르다면 ? 연결 
Server 인증서 : CA1에서 발급
Client 인증서 : CA2에서 발급
•
CA1 ≠ CA2 → 인증 실패 → 연결 거부
TLS Server - Client 함수 흐름
•
TLS는 Handshake 과정에서 Key를 교환한 후,
대칭키 암호화를 통해 Data를 전송한다.
•
TCP에서 암호화 하는 과정이 추가되는 것이며,
암호화를 위해 SSL/TLS 라이브러리 (OpenSSL)을 사용한다.
•
TLS는 1-Way Authentication(단방향 인증)과 Mutual Authentication(상호인증) 방식이 있는데, 이 글의 예제에서는 상호인증(Mutual TLS, mTLS)을 다루고 있다.
•
Server
◦
initialize_openssl() OpenSSL 라이브러리를 초기화
▪
SSL_library_init() -
▪
SSL_load_error_strings() -
▪
OpenSSL_add_ssl_algorithms() -
◦
create_context() TLS Server 컨텍스트(SSL_CTX)를 생성
▪
SSL_CTX_new(TLS_server_method()) -
◦
configure_context() Server 인증서 및 키 설정, Root CA 로드, 인증서 체인 검증
▪
SSL_CTX_use_certificate_file() -
▪
SSL_CTX_use_PrivateKey_file() -
▪
SSL_CTX_check_private_key() -
▪
SSL_CTX_load_verify_locations() -
▪
SSL_CTX_set_verify() -
▪
X509_STORE_new() -
▪
X509_STORE_load_locations(ca) -
▪
SSL_CTX_get0_certificate(server) -
▪
X509_STORE_CTX_new() -
▪
X509_STORE_CTX_init(dServer) -
▪
X509_verify_cert(dServer) -
▪
X509_STORE_CTX_free(dServer) -
▪
X509_STORE_free(server) -
◦
socket() - (TCP)Socket 생성
◦
bind() - 특정 IP와 Port에 Socket Binding
◦
listen() - Client 연결 요청을 대기
◦
accept() - Client 연결 수락 & 새로운 Socket 반환
◦
SSL_new() - TLS 세션(SSL 객체) 생성
◦
SSL_set_fd() - SSL 객체와 소켓을 연결
◦
SSL_accept() - TLS 핸드셰이크 수행 (클라이언트와 상호 인증)
◦
SSL_read() - 클라이언트로부터 데이터 수신
▪
recv() - Client로 부터 Data 수신
◦
SSL_write() - 클라이언트에게 데이터 전송
▪
send() - Client에게 Data 송신
◦
SSL_free() - SSL 객체 해제
◦
close() - Socket을 닫고 연결 종료
◦
SSL_CTX_free() - SSL 컨텍스트 해제
◦
EVP_cleanup() - OpenSSL 정리
•
Client
◦
initialize_openssl() OpenSSL 라이브러리를 초기화
▪
SSL_library_init() -
▪
SSL_load_error_strings() -
▪
OpenSSL_add_ssl_algorithms() -
◦
create_context() TLS Server 컨텍스트(SSL_CTX)를 생성
▪
SSL_CTX_new(TLS_server_method()) -
◦
SSL_CTX_use_certificate_file() - 클라이언트 인증서 로드 (mTLS)
◦
SSL_CTX_use_PrivateKey_file() - 클라이언트 개인 키 로드
◦
SSL_CTX_load_verify_locations(ca) - 신뢰할 수 있는 CA 인증서 설정
◦
SSL_CTX_set_verify(client) - Server 인증서 검증 설정
◦
socket() - Socket 생성
◦
connect() - Server에 연결 요청
◦
SSL_new() - TLS 세션(SSL 객체) 생성
◦
SSL_set_fd() - SSL 객체와 소켓을 연결
◦
SSL_connect() - TLS 핸드셰이크 수행
◦
SSL_write() - Server에 Data 송신
▪
send() - Server에 Data 송신
◦
SSL_read() - Server로 부터 Data 수신
▪
recv() - Server로 부터 Data 수신
◦
SSL_free() - SSL 객체 해제
◦
close() - Socket을 닫고 연결 종료
◦
SSL_CTX_free() - SSL 컨텍스트 해제
◦
EVP_cleanup() - OpenSSL 정리
TLS Handshake
1.
Client가 Server에 연결 요청
Client → Server : ClientHello 메시지를 보냄 (지원하는 암호화 방식 포함)
2.
Server가 응답 (Server 인증)
Server → Client : ServerHello, Certificate 메시지를 보냄
Server 인증서 검증 (Client가 신뢰할 수 있는 CA인지 확인)
3.
Client 인증 (mTLS)
Client → Server : Client 인증서 전송
Server가 Client 인증서 검증 (Root CA 체크)
Root CA가 다르면 연결 거부
4.
세션 키 교환 및 암호화 설정
Client와 Server가 세션 키를 공유하여 대칭키 암호화로 전환
5.
안전한 TLS 통신 시작
이후 모든 데이터는 암호화된 채로 송수신 !
TLS - Source Code
•
테스트 환경 참고
◦
Ubuntu 22.04.3 LTS
◦
Linux DESKTOP-711RRPG 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
◦
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
•
예제코드는 리눅스 기반으로 작성
1.
내 PC 8080 포트를 사용하여 server를 띄워두고
2.
client로 server(127.0.0.1:8080)에 message를 하나 보내고
3.
server도 client로 message를 하나 보내고,
4.
client는 종료, server는 listen상태로 대기
tls_server.c
tls_client.c
Makefile
위 코드를 그대로 저장 후 make tls 명령으로 컴파일하면, 테스트 해볼 수 있다 