简体   繁体   中英

Python ssl socket server SSLV3_ALERT_CERTIFICATE_UNKNOWN issue

I am writing a python socket server with ssl and I am encountering certificate unknown error during ssl handshake.

I have created private key and certificate with openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes command on my own.
This server is intended to run in intranet(under wifi) in my PC, and users will contact my PC IPaddress with their browser. Hence I have not registered this certificate with any CA. and I don't think its mandatory in my case.
Below more details..

echoserver.py

import socket
import ssl
import threading
class echoserver:
    def __init__(self,i,p):
        self.ip=i
        self.port=p
    def handler(self,c,a):
        msg=c.recv(1024)
        c.send(msg)
    def serve(self):
        echoserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        echoserver = ssl.wrap_socket(echoserver, keyfile='keys/key.pem', certfile='keys/cert.pem', server_side=True)
        echoserver.bind((self.ip, self.port))
        echoserver.listen()
        while True:
            (c,a)=echoserver.accept()
            threading.Thread(target=self.handler, args=(c,a)).start()

es=echoserver('192.168.43.124',443) #My PC's ip assigned under wifi network
es.serve()

#Connecting from mobile phone within same network as https://192.163.43.124

Error in server during ssl handshake

        self._sslobj.do_handshake()      
    ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1108)

What I tried

  • Adding cert_reqs=ssl.CERT_NONE and ca_certs="/location/to/keys" parameters in wrap_socket function.
    Doesn't seems to work. I assume these options are for client side.
  • Adding do_handshake_on_connect=False in wrap_socket function
    In Chrome, When connected server throws same error and thread/connection closed with exception. and chrome seems to send same connection request immediately again , and the second request works flawlessly.!.
    In firefox, First connection closed with same error and there is no second request.
  • Assigning common name in certificate same as IP address
    Not working.
  • Checked certificate_unknown error in ietf specification here . It gives no clue except this explanation certificate_unknown: Some other (unspecified) issue arose in processing the certificate, rendering it unacceptable.

One other thing I noted is , if I use built-in ThreadedHTTPServer in the same way as below, It works beautifully, without any issues I mentioned above.

httpd = self.ThreadedHTTPServer((self.ip, self.port), self.handler)
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile='keys/key.pem', certfile='keys/cert.pem', server_side=True)

I am not sure why this happens and how should I proceed with this. and not sure how built-in server modules works fine.

Appreciate any leads. Thanks.

Below Python builtin HTTPServer works fine with ssl, not showing any error. Not sure how?

import ssl
from http.server import HTTPServer, BaseHTTPRequestHandler

class requesthandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type","text/html")
        self.end_headers()
        self.wfile.write("<html><body>It works</body></html>".encode('utf8'))

httpd = HTTPServer(('192.168.43.124', 443), requesthandler)
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile='keys/key.pem', certfile='keys/cert.pem', server_side=True)
httpd.serve_forever()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1108)

This means the client (browser) does not trust your certificate since it is issued by an unknown entity. If you want to use self-signed certificates you have to explicitly import these as trusted for all clients you want to use.

There is no way around this. The certificate in TLS is to make sure that the connection is done with the expected server and not some man in the middle claiming to be the expected server. If a client would trust arbitrary certificates then it would also trust certificates created by a man in the middle attacker.

Below Python builtin HTTPServer works fine with ssl, not showing any error. Not sure how?

The browser will still complain. The only difference is that the server captures the exception and thus will not crash but continue. You can do the same in your code:

    while True:
        try:
            (c,a)=echoserver.accept()
            threading.Thread(target=self.handler, args=(c,a)).start()
        except:
            pass # ignore error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM