Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssl error #419

Closed
yjqiang opened this issue Jun 2, 2018 · 13 comments
Closed

ssl error #419

yjqiang opened this issue Jun 2, 2018 · 13 comments
Labels

Comments

@yjqiang
Copy link

yjqiang commented Jun 2, 2018

wss://broadcastlv.chat.bilibili.com:2245/sub
It is so strange since I can connect it in website without any warnings on chrome. But when I use websockets, it shows msg "class 'ssl.SSLError'> [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)".

@aaugustin
Copy link
Member

Most likely this is because Python doesn't recognize the certificate authority that signed the certificate for that server. There were several changes around this in recent Python versions.

Try creating a SSL connection without websockets, directly with https://docs.python.org/3/library/asyncio-eventloop.html?highlight=create_connection#asyncio.AbstractEventLoop.create_connection.
If that works and websockets doesn't, then I'll investigate.

@yjqiang
Copy link
Author

yjqiang commented Jun 2, 2018

import asyncio
import websockets
import ssl
print(ssl.OPENSSL_VERSION)
async def hello(uri):
    reader, writer = await asyncio.open_connection('broadcastlv.chat.bilibili.com', 2245, ssl=True)
    async with websockets.connect(uri) as websocket:
        await websocket.send("Hello world!")
asyncio.get_event_loop().run_until_complete(hello('wss://broadcastlv.chat.bilibili.com:2245/sub'))

OpenSSL 1.1.0g 2 Nov 2017
Traceback (most recent call last):
File "/home/y**/Desktop/0.py", line 9, in
asyncio.get_event_loop().run_until_complete(hello('wss://broadcastlv.chat.bilibili.com:2245/sub'))
File "/usr/lib/python3.6/asyncio/base_events.py", line 468, in run_until_complete
return future.result()
File "/home/y**/Desktop/0.py", line 6, in hello
reader, writer = await asyncio.open_connection('broadcastlv.chat.bilibili.com', 2245, ssl=True)
File "/usr/lib/python3.6/asyncio/streams.py", line 81, in open_connection
lambda: protocol, host, port, **kwds)
File "/usr/lib/python3.6/asyncio/base_events.py", line 804, in create_connection
sock, protocol_factory, ssl, server_hostname)
File "/usr/lib/python3.6/asyncio/base_events.py", line 830, in _create_connection_transport
yield from waiter
File "/usr/lib/python3.6/asyncio/sslproto.py", line 505, in data_received
ssldata, appdata = self._sslpipe.feed_ssldata(data)
File "/usr/lib/python3.6/asyncio/sslproto.py", line 201, in feed_ssldata
self._sslobj.do_handshake()
File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)

@yjqiang
Copy link
Author

yjqiang commented Jun 2, 2018

That is wired. But it is Python's fault. Can you give me some messages about it? I want to find out the reason, like this websocket(broadcastlv.chat.bilibili.com) is out-of-date or Python has some bugs.

@aaugustin
Copy link
Member

openssl s_client -showcerts -connect broadcastlv.chat.bilibili.com:2245 </dev/null says that the certificate for that server isn't trusted by my system.

You can pass ssl=SSLContext(...) to connect where SSLContext is configured to trust the authority that signed the certificate of the server you're connecting to.

@waaadim
Copy link

waaadim commented Oct 16, 2018

@aaugustin - I'm having the same problem... any idea on what might be wrong

import asyncio, ssl, websockets
import logging
logger = logging.getLogger('websockets')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())

ssl_context = ssl.SSLContext()
ssl_context.verify_mode = ssl.CERT_NONE

async def hello():
    print("1")
    async with websockets.connect(
            'wss://10.20.0.166:11443/ext/remoteinput', ssl=True) as websocket:
        print("2")
        await websocket.send(b'\x01\xCC\x01')

asyncio.get_event_loop().run_until_complete(hello())

gives:

1
SSL handshake failed on verifying the certificate
protocol: <asyncio.sslproto.SSLProtocol object at 0x10969ad68>
transport: <_SelectorSocketTransport fd=6 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 625, in _on_handshake_complete
    raise handshake_exc
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 189, in feed_ssldata
    self._sslobj.do_handshake()
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 763, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
SSL error in data received
protocol: <asyncio.sslproto.SSLProtocol object at 0x10969ad68>
transport: <_SelectorSocketTransport closing fd=6 read=idle write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 526, in data_received
    ssldata, appdata = self._sslpipe.feed_ssldata(data)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 189, in feed_ssldata
    self._sslobj.do_handshake()
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 763, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)
Traceback (most recent call last):
  File "sockets.py", line 106, in <module>
    asyncio.get_event_loop().run_until_complete(hello())
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 568, in run_until_complete
    return future.result()
  File "sockets.py", line 102, in hello
    'wss://10.20.0.166:11443/ext/remoteinput', ssl=True) as websocket:
  File "/usr/local/lib/python3.7/site-packages/websockets/py35/client.py", line 2, in __aenter__
    return await self
  File "/usr/local/lib/python3.7/site-packages/websockets/py35/client.py", line 12, in __await_impl__
    transport, protocol = await self._creating_connection
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 970, in create_connection
    ssl_handshake_timeout=ssl_handshake_timeout)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 998, in _create_connection_transport
    await waiter
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 526, in data_received
    ssldata, appdata = self._sslpipe.feed_ssldata(data)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 189, in feed_ssldata
    self._sslobj.do_handshake()
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 763, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)

if I pass ssl=ssl_context I only get this, no matter how much I wait

1
Traceback (most recent call last):
  File "sockets.py", line 106, in <module>
    asyncio.get_event_loop().run_until_complete(hello())
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 568, in run_until_complete
    return future.result()
  File "sockets.py", line 102, in hello
    'wss://10.20.0.166:11443/ext/remoteinput', ssl=ssl_context) as websocket:
  File "/usr/local/lib/python3.7/site-packages/websockets/py35/client.py", line 2, in __aenter__
    return await self
  File "/usr/local/lib/python3.7/site-packages/websockets/py35/client.py", line 12, in __await_impl__
    transport, protocol = await self._creating_connection
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 943, in create_connection
    raise exceptions[0]
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 930, in create_connection
    await self.sock_connect(sock, address)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 475, in sock_connect
    return await fut
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 505, in _sock_connect_cb
    raise OSError(err, f'Connect call failed {address}')
TimeoutError: [Errno 60] Connect call failed ('10.20.0.166', 11443)

python 3.7, latest version of websockets

$openssl s_client -showcerts -connect 10.20.0.166:11443 </dev/null:

CONNECTED(00000003)
depth=0 /CN=10.20.0.166
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /CN=10.20.0.166
verify error:num=27:certificate not trusted
verify return:1
depth=0 /CN=10.20.0.166
verify error:num=21:unable to verify the first certificate
verify return:1
write:errno=54

also fixes described here and here don't work for me

also tried other socket libraries like websockets-client and autobahn, but was always getting the same results.

btw, everything works fine via js:

var ws = new WebSocket("wss://10.20.0.166:11443/ext/remoteinput");
ws.binaryType = 'arraybuffer';
ws.onopen = function() {
    const buffer = new ArrayBuffer(3);
    const uint8 = new Uint8Array(buffer);
    uint8.set([1, 204, 1]);

    ws.send(uint8)
    console.log("Message is sent...");
};

@aaugustin
Copy link
Member

Get websockets out of the equation and try opening a connection with:

import asyncio
import ssl

loop = asyncio.get_event_loop()
ssl_context = ssl.SSLContext()
# customize ssl_context so it works for your server...
loop.run_until_complete(loop.open_connection('10.20.0.166', 11443, ssl=ssl_context))

Once this works — and I can't help you there — try doing the same with websockets.

If it works, you're all set. If it doesn't, then it's a bug.

@aaugustin
Copy link
Member

There's a good summary of things to consider here: https://docs.python.org/3/library/ssl.html#ssl-security

@waaadim
Copy link

waaadim commented Oct 17, 2018

@aaugustin - so, if this works:

import asyncio, ssl
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.open_connection('10.20.0.166', 11443, ssl=ssl.SSLContext()))
print("the end..")


async def test_conn(host, port):
    _, writer = await asyncio.open_connection(host, port, ssl=ssl.SSLContext())

    writer.write(b'ping\n')
    print("the end..")

asyncio.get_event_loop().run_until_complete(test_conn('10.20.0.166', 11443))
the end..
the end..

and this prints only 1 then it's bug ?

import asyncio, ssl, websockets
import logging

async def hello():
    print("1")
    async with websockets.connect(
            'wss://10.20.0.166:11443/ext/remoteinput', ssl=ssl.SSLContext()) as websocket:
        print("2")
        await websocket.send(b'\x01\xCC\x01')

asyncio.get_event_loop().run_until_complete(hello())

@aaugustin
Copy link
Member

Yes, exactly.

@lambdalisue
Copy link

lambdalisue commented Jan 31, 2019

I used the following code and found that the only test4 fails with ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed error.

import asyncio
import ssl
import websockets

HOST = "example.com"
PORT = 443
ENDPOINT = "wss://%s:%s/brabrabra"


async def test1():
    _, w = await asyncio.open_connection(HOST, PORT, ssl=ssl.SSLContext())
    w.write(b"ping\n")
    print("test1 passed")


async def test2():
    _, w = await asyncio.open_connection(HOST, PORT)
    w.write(b"ping\n")
    print("test2 passed")


async def test3():
    async with websockets.connect(ENDPOINT % (HOST, PORT), ssl=ssl.SSLContext()) as ws:
        await ws.send(b"ping\n")
    print("test3 passed")


async def test4():
    async with websockets.connect(ENDPOINT % (HOST, PORT)) as ws:
        await ws.send(b"ping\n")
    print("test4 passed")


loop = asyncio.get_event_loop()
loop.run_until_complete(test1())
loop.run_until_complete(test2())
loop.run_until_complete(test3())
loop.run_until_complete(test4())

While the document of websockets.connect said like below, the test4 should pass as well isn't?

For example, you can set the ssl keyword argument to a SSLContext to enforce some TLS settings. When connecting to a wss:// URI, if this argument isn’t provided explicitly, it’s set to True, which means Python’s default SSLContext is used.

NOTE: websockets.version.version was 6.0

NOTE:

I noticed that if I use ssl.create_default_context() instead of ssl.SSLContext(), the exception is raised in test3 as well.

NOTE:

Noticed that using certifi.where() with ssl.create_default_context fix the issue.
Note sure if it helps but fyi.

import certifi

ssl_context = ssl.create_default_context(cafile=certifi.where())

@aaugustin
Copy link
Member

test2 doesn't perform a TLS handshake while test4 does.

The proper comparison would be:

async def test2():
    _, w = await asyncio.open_connection(HOST, PORT, ssl=True)
    w.write(b"ping\n")
    print("test2 passed")

I expect this will fail like test4.

@aaugustin aaugustin mentioned this issue Jun 23, 2019
18 tasks
@ahmad88me
Copy link

Having this (as suggested by waaadim) solved it for me

ssl_context = ssl.SSLContext()
ssl_context.verify_mode = ssl.CERT_NONE

@aaugustin
Copy link
Member

Please don't disable certificate validation...

It isn't hard to get it right. There are examples in websockets docs.

It's like buckling your seatbelt in a car. Annoying, but just do it please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants