El servidor Python3 CGI HTTPS falla en Unix

Este servidor Python3 CGI HTTPS solía funcionar hace unas semanas (o meses), pero ahora ya no funciona en Linux (Ubuntu). Probé en Ubuntu 10.04 y Ubuntu 14.04 y el comportamiento es el mismo.

Ahora cuando trato de acceder a cualquier script CGI estoy obteniendo:

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) 

A continuación se muestra el código para el servidor:

 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() 

El servidor registra el siguiente error:

 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) 

Esto funciona si deshabilito SSL y funciona bien en Windows con SSL. Probado con Python 3.4. Lo extraño es que esto funcionó hace unos meses. ¿Puede alguien obtener este script (o cualquier servidor Python3 CGI HTTPS) para ejecutarse en sistemas Linux actualizados?

Encontré la respuesta en:
http://www.castro.aus.net/~maurice/OddsAndEnds/blog/files/d2baf24c48b972f18836cac7a27734e2-35.html

La solución es agregar:

 http.server.CGIHTTPRequestHandler.have_fork=False # Force the use of a subprocess 

Antes de iniciar el servidor.

Esto es necesario para la implementación de Mac y Unix porque, por razones de eficiencia, emplean una bifurcación para iniciar el proceso que ejecuta el CGI en lugar de crear un subproceso como lo usan otras implementaciones (es decir, Windows). En una implementación CGI no ajustada, la bifurcación funciona bien y la salida se envía al socket correctamente, sin embargo, cuando el socket está envuelto en SSL, las cosas van terriblemente mal.

La solución es forzar a las implementaciones de Unix y Mac a usar un subproceso que deje al socket SSL funcionando felizmente y que el servidor Python transfiera la salida del script CGI al cliente mientras traduce la salida a SSL.

¡Todavía no tengo ni idea de por qué esto solía funcionar!

Aunque el OP ya encontró la solución, aquí hay algunos detalles más de por qué se comporta de esa manera:

  • Los sockets simples son solo para kernel, pero los ssllwraped ponen una capa adicional de espacio de usuario en la parte superior.
  • http.server realiza una bifurcación (en plataformas que admiten fork, que no está en Windows) y una reasignación de los descriptores de archivo a stdin / stdout antes de ejecutar el progtwig cgi. De esta manera, el progtwig ejecutado funciona en los descriptores de archivo sin formato (solo kernel, no ssl)
  • Todas las escrituras del progtwig, por lo tanto, van directamente al socket del kernel, es decir, datos sin cifrar.
  • El interlocutor croará en estos datos simples porque espera marcos SSL. El tipo de error que produce depende de los datos que obtiene, por ejemplo, ssl_error_rx_record_too_long o “número de versión incorrecto” o algo así.