Python3 CGI HTTPS服务器在Unix上失败

时间:2014-12-04 20:24:23

标签: python linux ubuntu ssl cgi

这个Python3 CGI HTTPS服务器曾经使用几周(或几个月),但现在不再适用于Linux(Ubuntu)。我试过Ubuntu 10.04和Ubuntu 14.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上正常工作,则此方法有效。用Python 3.4测试。 奇怪的是,这在几个月前就开始了 任何人都可以在更新的Linux系统上运行此脚本(或任何python3 CGI HTTPS服务器)吗?

2 个答案:

答案 0 :(得分:2)

我找到了答案:
http://www.castro.aus.net/~maurice/OddsAndEnds/blog/files/d2baf24c48b972f18836cac7a27734e2-35.html

解决方案是添加:

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。

我仍然不知道为什么以前这样做了!

答案 1 :(得分:1)

虽然OP已经找到了解决方案,但这里有一些更详细的原因:

  • 普通套接字仅限内核,但sslwraped套接字在顶部放置了一个额外的用户空间层。
  • http.server执行fork(在支持fork的平台上,不在Windows上)以及在最终执行cgi程序之前将文件描述符重新映射到stdin / stdout。这样执行的程序就可以在plain(仅内核,没有ssl)文件描述符
  • 上运行
  • 程序的所有写入因此直接进入内核套接字,即明文未加密的数据。
  • 对等体会在这个普通数据上呱呱叫,因为它需要SSL帧。它产生的错误类型取决于它获得的数据,例如ssl_error_rx_record_too_long或"错误的版本号"或类似的东西。