我现在想知道我们是否可以在Linux环境下基于以下策略/方案制作某种SSL服务器。
(1) 对于初始请求,应该是在父服务器进程中传入的。在建立 SSL 连接并处理请求的初始解析之后,请求(套接字)将被转发到请求处理进程以进行进一步处理。
(2) 请求处理过程应该预先运行。从这个意义上说,我们不会在这里使用任何基于 fork-exec-pipe 的方案。
(3) 对于父服务器进程和请求处理进程之间的通信,已经建立了一些IPC,以便使用sendmsg() - SCM_RIGHTS 技术将打开的套接字描述符从父服务器进程复制到请求处理进程。
(4) 在SSL功能方面,我们应该使用OpenSSL(libssl)。
(5) 在请求处理过程中,我们应该利用父服务器进程的共享套接字描述符来创建新的 SSL 套接字。
关键是我不想浪费在服务器和请求处理进程之间传输数据的任何性能。我也不想根据请求生成请求处理过程。所以我想提前生成请求处理过程。
虽然我不太确定我在这里尝试做的事情对您是否有意义,但如果你们中的任何人能给我一些关于上述方法是否可行的提示,我将不胜感激。
I'm now wondering whether we can make some sort of SSL server based on the following policies/scheme under Linux environment.
(1) As for the initial request, it should be incoming in the parent server process. After establishing SSL connection and also handling initial parsing of the request, the request (socket) will be forwarded to a request-handling process to do further processing.
(2) The request-handling process will be something which should be running beforehand. We won't use any fork-exec-pipe based scheme here in this sense.
(3) As for the communication between the parent server process and the request handling process, some IPC has been established in order to copy opened socket descriptor from the parent server process to the request-handling process by using sendmsg() - SCM_RIGHTS technique.
(4) In terms of SSL functionality, we are supposed to use OpenSSL (libssl).
(5) In the request-handling process, we are supposed to create new SSL socket by making use of the shared socket descriptor from the parent server process.
The point is that I don't want to waste any performance of transferring data between the server and the request handling process. I don't want to spawn request handling process as per request basis, either. So I would like to spawn the request handling process in advance.
Although I'm not really sure whether what I'm trying make here is making sense to you, it would be appreciated if anyone of you could give me some hint on whether the above approach is feasible.
发布评论
评论(1)
目前尚不清楚您到底在寻找什么,尤其是您想在哪里进行 SSL 加密/解密。
您想在请求处理程序进程内进行加密/解密吗?
这似乎是更有可能的解释。但是,您谈到在主进程中进行一些请求解析。主进程中解析的数据是否已经是 SSL 会话的一部分?如果是这样,您必须在主进程中进行 SSL 握手(初始化和密钥交换)才能访问加密数据。如果您随后将原始套接字传递给另一个进程,它将无法访问父进程的 SSL 状态,因此它无法继续解密父进程停止的地方。如果它尝试在套接字上重新初始化 SSL,就好像它是一个干净的连接一样,客户端可能会(正确地)将连接中间未经请求的握手视为协议错误并终止连接。如果没有,就会出现安全漏洞,因为攻击者可能会恶意重定向客户端的网络流量,而不是强制重新初始化的请求处理进程。通常不可能将初始化的 SSL 会话传递到不同的进程,而不同时通知它们 OpenSSL 的完整内部状态(交换的密钥、一些序列号等),这即使不是不可能,也是很困难的。
如果您不需要接触父进程中的 SSL 会话,并且只解析实际 SSL 会话启动之前出现的一些未加密数据(类似于 IMAP 中的 STARTTLS 命令),那么您的想法将毫无问题。只需阅读您需要的内容,直到 SSL 交换应开始的位置,然后使用 SCM_RIGHTS 将套接字传递到后端进程(请参阅 cmsg(3) 或 这网站)。还有一些库可以为您完成这项工作,即 libancillary。
或者您是否希望主进程为请求处理程序进程执行 SSL 加密/解密?
在这种情况下,将原始套接字传递给请求处理程序进程是没有意义的,因为它们从中获得的唯一内容是加密数据。在这种情况下,您必须打开到后端进程的新连接,因为它将携带不同的数据(已解密)。然后,主进程将从网络套接字读取加密数据,解密并将结果写入请求处理程序的新套接字。另一个方向以此类推。
注意:如果您只是希望请求处理进程根本不用担心 SSL,我建议让它们监听环回接口并使用类似 stud 来完成 SSL/TLS 肮脏的工作。
简而言之,您必须选择以上之一。不可能同时做这两件事。
It is not clear what exactly you are looking for, especially where do you want to do the SSL encryption/decryption.
Do you want to do the encryption/decryption inside the request handler processes?
That seems the more likely interpretation. However you talk about doing some request parsing in the master process. Is the data parsed in the master process already a part of the SSL session? If so, you would have to do an SSL handshake (initialization and key exchange) in the master process in order to access the encrypted data. If you then passed the original socket to another process, it wouldn't have access to the SSL state of the parent process so it wouldn't be able to continue decrypting where the parent left off. If it tried to reinitialize SSL on the socket as if it were a clean connection, the client will probably (correctly) treat an unsolicited handshake in the middle of a connection as a protocol error and terminate the connection. If it didn't, it would present a security hole as it could be an attacker who maliciously redirected client's network traffic, instead of your request-handling process, who is forcing the re-initialization. It's generally not possible to pass initialized SSL sessions to different processes without also informing them of the complete internal state of OpenSSL (exchanged keys, some sequence numbers, etc.) along with this, which would be hard if not impossible.
If you don't need to touch the SSL session in the parent process and you parse just some unencrypted data that come before the actual SSL session starts (analogous to e.g. the STARTTLS command in IMAP), your idea will work without problems. Just read what you need to, up to the point where the SSL exchange should start, then pass the socket to the backend process using SCM_RIGHTS (see e.g. the example in cmsg(3) or this site). There are also libraries that do the work for you, namely libancillary.
Or do you expect the master process to do SSL encryption/decryption for the request handler processes?
In that case it makes no sense to pass the original socket to the request-handler processes as the only thing they would get from it is encrypted data. In the scenario you have to open a new connection to the backend process as it will carry different data (decrypted). The master process will then read encrypted data from the network socket, decrypt it and write the result to the new socket for the request-handler. Analogically in the other direction.
NB: If you just want your request handling processes not to worry about SSL at all, I'd recommend to let them listen on the loopback interface and use something like stud to do the SSL/TLS dirty work.
In short, you have to choose one of the above. It's not possible to do both at the same time.