Python3 CGI HTTPS服务器在Unix上失败

Python3 CGI HTTPS服务器在Unix上失败,python,linux,ubuntu,ssl,cgi,Python,Linux,Ubuntu,Ssl,Cgi,这个Python3 CGI HTTPS服务器在几周(或几个月)前就可以工作了,但现在已经不能在Linux(Ubuntu)下工作了。我在Ubuntu10.04和Ubuntu14.04上试过,结果是一样的 现在,当我尝试访问我得到的任何CGI脚本时: Secure Connection Failed An error occurred during a connection to 127.0.0.1:4443. SSL received a record that exceeded the max

这个Python3 CGI HTTPS服务器在几周(或几个月)前就可以工作了,但现在已经不能在Linux(Ubuntu)下工作了。我在Ubuntu10.04和Ubuntu14.04上试过,结果是一样的

现在,当我尝试访问我得到的任何CGI脚本时:

Secure Connection Failed

An error occurred during a connection to 127.0.0.1:4443. SSL received a record that exceeded the maximum permissible length. (Error code: ssl_error_rx_record_too_long) 
以下是服务器的代码:

import http.server
import ssl
import os

server_address = ('', 4443)
cert = os.path.abspath('./server.pem')

handler = http.server.CGIHTTPRequestHandler
handler.cgi_directories = ['/cgi-bin']

httpd = http.server.HTTPServer(server_address, handler)
httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, 
                                certfile=cert)

print ("Server started...")
httpd.serve_forever()
服务器记录以下错误:

File "/usr/lib/python3.4/ssl.py", line 618, in read
v = self._sslobj.read(len, buffer)
ssl.SSLError: [SSL: SSLV3_ALERT_UNEXPECTED_MESSAGE] sslv3 alert unexpected message (_ssl.c:1767)
如果我禁用SSL,并且在使用SSL的Windows上运行良好,则此功能可以正常工作。使用Python3.4进行测试。 奇怪的是,这在几个月前就奏效了 有人能让这个脚本(或任何python3 CGI HTTPS服务器)在更新的Linux系统上运行吗?

我在以下位置找到了答案:

解决方案是添加:

http.server.CGIHTTPRequestHandler.have_fork=False # Force the use of a subprocess
在启动服务器之前

这对于Mac和Unix实现是必需的,因为出于效率原因,它们使用fork来启动执行CGI的进程,而不是像其他实现(即Windows)那样创建子进程。在非包装的CGI实现中,fork工作正常,输出正确地发送到套接字,但是,当套接字是SSL包装的时,就会出现严重错误

解决方案是强制Unix和Mac实现使用一个子进程,让SSL套接字愉快地工作,让Python服务器将CGI脚本的输出传输到客户端,同时将输出转换为SSL


我仍然不知道为什么这会起作用

尽管OP已经找到了解决方案,但以下是它为什么会这样做的更多细节:

  • 普通套接字仅是内核,但sslwrapped套接字在其上增加了一个用户空间层
  • 在最终执行cgi程序之前,http.server执行fork(在支持fork的平台上,而不是在windows上)并将文件描述符重新映射到stdin/stdout。这样,执行的程序在普通(仅内核,无ssl)文件描述符上工作
  • 因此,程序的所有写入操作都直接进入内核套接字,即普通的未加密数据
  • 对等方将在这个普通数据上发出嘎嘎声,因为它需要SSL帧。它产生的错误类型取决于它获取的数据,例如ssl_error_rx_record_too_long或“错误的版本号”或类似的内容

我发现Linux上的Python 2.7也存在同样的问题,因此这似乎不是Python 3所独有的。