[Webserver]miniWebserver+https-(9)

👉🏻 주요 변경사항은 아래와 같습니다.
The major changes are as follows.

✔️ ❗️ 표시된 부분이 변경사항입니다.
The parts marked with ❗️ are the changes.

✔️ http,https 네임스페이스 적용
Apply http, https namespaces

# Server.h
namespace http{
    class Server { ... };
}

# HttpsServer.cpp
namespace https {
    class Server { ... };
}

✔️ https프로토콜 적용 / Apply HTTPS protocol

👉🏻 openssl 적용하기 / Apply openssl

✔️ openssl 설치 / install openssl

brew install openssl

✔️ openssl 설치 경로 확인 / Check the openssl installation path

MacBookAir build % brew --prefix openssl
/opt/homebrew/opt/openssl@3

✔️ CMakeLists.txt 파일에 openssl 적용
Apply openssl to the CMakeLists.txt file

# cmake최소버전지정 / Specify minimum CMake version
cmake_minimum_required(VERSION 3.10)

# 프로젝트 이름과 버전 설정 / Project name and version settings
project(mini_webserver_9 VERSION 1.0)

# C++ 표준 버전 지정(c++20) / C++ Standard Version Specification (C++20)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Openssl❗️
include_directories(/opt/homebrew/opt/openssl@3/include)
link_directories(/opt/homebrew/opt/openssl@3/lib)

# ❗️ 실행 파일 생성 대상 소스 파일 나열 / List source files to be used for creating executable files
add_executable(main
    Main.cpp
    Router.cpp
    Server.cpp
    HttpsServer.cpp 
)

# Openssl + main 링크 / link❗️
target_link_libraries(main ssl crypto)

✔️ 테스트용 인증서 생성 (key.pem, cert.pem)
Generate a certificate for testing(key.pem, cert.pem)

— 인증서 생성 명령 / Certificate creation command

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
- req : 자체 서명 인증서를 생성 / Generate a self-signed certificate
- x509 : x.509형식으로 생성 / Created in x.509 format
- newkey rsa:4096 :
새 4096비트 RSA 개인키와 인증서 요청을 함께 생성
Generate a new 4096-bit RSA private key and a certificate request together
- keyout key.pem : 개인키가 저장될 파일명 / filename where the private key will be stored
- out cert.pem : 생성될 인증서 파일명 / Certificate filename to be generated
- days 365 : 인증서 유효기간 / Certificate validity period
- nodes: 암호화하지않음(비밀번호 없이 사용가능) / Unencrypted (can be used without a password)

— 질문에 그냥 기본 값으로 모두 엔터를 입력합니다.
For the questions, just press Enter for all default values.

MacBookAir cert % openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
..+.........+.+.....+...+.+..+..........+.....+....+++++++++++++++++++++++++++++++++++++++++++++*.....+.....+............+.+..............+...+...+++++++++++++++++++++++++++++++++++++++++++++*...........+.....+.+......

... 중략/skipping the middle ...

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) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
MacBookAir cert % 

👉🏻코드 / Code

✔️ httpsServer.h ,httpsServer.cpp파일이 추가되었습니다.

✔️인증서 검사 및 등록(httpsServer.cpp,main.cpp)

— httpsServer.cpp

bool https::Server::initialize_ssl(const std::string& cert_file, const std::string& key_file) { ... } 

— main.cpp

    if (!server3.initialize_ssl("../cert/cert.pem", "../cert/key.pem")) {
        std::cerr << "SSL initialization failed. Exiting.\n";
        return -1;
    }

✔️ 소켓에 적용 / Apply to socket

void https::Server::handle_client(int client_socket) {
    // https설정 추가 / Add https settings❗️
    SSL* ssl = SSL_new(ssl_ctx);
    if (!ssl) {
        std::cerr << "[SSL] SSL_new() failed\n";
        close(client_socket);
        return;
    }
    // client_socket에 ssl적용 / Apply SSL to client_socket❗️
    SSL_set_fd(ssl, client_socket);
    if (SSL_accept(ssl) <= 0) {
        ERR_print_errors_fp(stderr);
        SSL_free(ssl);
        close(client_socket);
        return;
    }
... 중략 / skipping the middle...

        // http설정 / http setting
        //write(client_socket, response.c_str(), response.size());
        //
        // https설정.  https setting ❗️
        SSL_write(ssl, response.c_str(), static_cast<int>(response.size()));

}

✔️ stop함수에서 소켓,SSL/TLS ,openssl 종료
Terminate socket, SSL/TLS, and openssl in the stop function

— httpsServer.cpp

void https::Server::stop() {

    if (running.load() && server_fd != -1) { //
        // 플래그를 false로 설정하여 루프 종료 신호 전송
        // Set flag to false to send loop termination signal
        running.store(false);
        //close(server_fd); //❗️ -

        // 실제로는 여기서 소켓을 닫거나 리소스 해제를 수행합니다.
        // In practice, close the socket or release resources here.
        //server_fd = -1; // 닫았으므로 초기화 / Initialize to -1 after closing

        //  ❗️ -> 변경된 코드 / changed code
        // 서버 소켓 닫기 (열려있다면) / Close server socket (if open)
        if (server_fd != -1) {
            close(server_fd);
            server_fd = -1;
        }

        // SSL 컨텍스트 해제 (존재한다면) Release SSL context (if any) ❗️
        if (ssl_ctx) {
            SSL_CTX_free(ssl_ctx);
            ssl_ctx = nullptr;
        }

        // OpenSSL 라이브러리 정리 / OpenSSL Library Cleanup ❗️
        EVP_cleanup();

        std::cout << "[Server] Shutdown initiated." << std::endl;
    }
}

👉🏻빌드 / Build

cd build
cmake ..
make

👉🏻실행 / Run

./main

👉🏻 브라우저 접속 / Access Browser

https://localhost:6443/

Leave a Reply