如何让HTTPS服务器进程池配合安全SSL连接工作?
进程池架构下HTTPS服务器的实现困境
我已实现一款HTTP服务器,采用主进程接受连接、预生成进程池处理请求的架构,通过sendmsg()结合msghdr与cmsghdr传递已打开的套接字。
同时,我也通过<openssl/ssl.h>中的SSL_CTX_new、SSL_new、SSL_accept、SSL_read等函数,完成了单进程HTTPS服务器的常规实现。
但我始终无法将两者结合,核心需求与困境如下:
- 拒绝为每个请求新建进程,必须使用预生成的进程池
- 主进程需以root权限运行以访问私钥,但进程池绝不允许以root身份运行
- 主进程必须完成
SSL_new创建SSL*并执行SSL_accept()握手,但找不到方法将SSL*与套接字一同传递给进程池(已知Apache实现了该逻辑)
开发环境为FreeBSD,使用C/C++语言,无法更换开发语言。
以下是已实现的关键代码大纲:
非安全服务器主进程代码
union cmsghdr_with_int { struct cmsghdr hdr; unsigned char buffer[CMSG_SPACE(sizeof(int))]; }; main() ---- listensock = socket(AF_INET, SOCK_STREAM, 0); setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, (char *) & r, sizeof(r)); struct sockaddr_in addr; ...... fill it up ...... bind(listensock, (struct sockaddr *) & addr, sizeof(addr)); listen(listensock, 5); socketpair(PF_LOCAL, SOCK_STREAM, 0, sockpair); for each child pid_t p = fork(); if (p == 0) close(sockpair[0]); child_run(); close(sockpair[1]); loop: ... select(listensock + 1, & fds, NULL, NULL, & tv); acceptsock = accept(listensock, NULL, NULL); ... set up cmsghdr_with_int msgctrlbuffer ... and msghdr msghd with iov length 1 ... and char socketbuffer[...] ... and struct cmsghdr * msgctrl with SOL_SOCKET, SCM_RIGHTS, CMSG_LEN * (int *) CMSG_DATA(msgctrl) = acceptsock; sendmsg(sockpair[0], & msghd, 0); r = close(acceptsock); close(listensock);
非安全服务器进程池代码
main() ---- loop: ... set up msghdr msghd with iovlen 1, CMSG_SPACE recvmsg(fromserver, & msghd, 0); msgctrl = CMSG_FIRSTHDR(& msghd); while (msgctrl != NULL) if ... CMSG_LEN, SOL_SOCKET, SCM_RIGHTS ... acceptsock = * (int *) CMSG_DATA(msgctrl); read headers send response close acceptsock
单进程安全服务器代码
main() ---- const SSL_METHOD * meth = TLS_server_method(); sslctxt = SSL_CTX_new(meth); SSL_CTX_use_certificate_file(sslctxt, "...apache...xxxxx.crt", SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(sslctxt, "...apache...xxxxx.key", SSL_FILETYPE_PEM); ... the usual socket-bind-listen while (... still serving ...) int sock = accept(mainsock, ... usual SSL * sslio = SSL_new(sslctxt); SSL_set_fd(sslio, sock); SSL_accept(sslio); read headers: SSL_read(sslio, buffer, sizeof(buffer) - 1); send response: SSL_write(sslio, s.c_str(), s.length()); SSL_shutdown(sslio); SSL_free(sslio); close(sock); close(mainsock); SSL_CTX_free(sslctxt);
内容的提问来源于stack exchange,提问作者Jim Sykes
相关产品推荐
相关产品推荐

