python-hyper / hyper

HTTP/2 for Python.
http://hyper.rtfd.org/en/latest/
MIT License
1.05k stars 191 forks source link

Custom SSLContext Error - SNI and cert verify false support #343

Closed Narengowda closed 7 years ago

Narengowda commented 7 years ago

I am trying to make HTTP2 request to a server(virtual hosted) which gives SSL certificates based on host header value(SNI).

# conn = hyper.HTTP20Connection('http2.akamai.com', port=443, ssl_context=context)
# conn.request('GET', '/path', headers={'Host': 'www.mywebsite.com'})

Hyper-h2 package for Python won't support SNI or disabling cert verification! https://hyper.readthedocs.io/en/latest/advanced.html#ssl-tls-certificate-verification

One way to disable certs verification is by having custom SSLContext, and stuck in protocol assertion error

Basic code to make HTTP2 call with custom SSLContext:

import ssl
import hyper

# Custom SSLCONTEXT for not verifying SSLCertificate and Hostname
# or need SSLCONTEXT for SNI support
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_NONE
context.check_hostname = False
hyper.tls._context = context

conn = hyper.HTTP20Connection('http2.akamai.com', port=443, ssl_context=context)
conn.request('GET', '/')

print conn.get_response()

Error :

Traceback (most recent call last):
  File "ssl_custom.py", line 32, in <module>
    conn.request('GET', '/')
  File "/usr/local/lib/python2.7/site-packages/hyper/http20/connection.py", line 281, in request
    self.endheaders(message_body=body, final=True, stream_id=stream_id)
  File "/usr/local/lib/python2.7/site-packages/hyper/http20/connection.py", line 544, in endheaders
    self.connect()
  File "/usr/local/lib/python2.7/site-packages/hyper/http20/connection.py", line 373, in connect
    assert proto in H2_NPN_PROTOCOLS or proto == H2C_PROTOCOL
AssertionError
Narengowda commented 7 years ago

Stackoverflow link: https://stackoverflow.com/questions/45293922/hyper-http2-custom-sslcontext-error

Lukasa commented 7 years ago

If you are using a custom SSLContext you must set it up appropriately for HTTP/2. This involves setting some protocol negotiation parameters. You should begin by obtaining your SSLContext using this function, which you can then subsequently modify to suit your needs.

KostyaEsmukov commented 7 years ago
import ssl
import hyper
from hyper.tls import init_context

ssl_context = init_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

conn = hyper.HTTP20Connection('http2.akamai.com', port=443, ssl_context=ssl_context)
conn.request('GET', '/')

print conn.get_response()
Narengowda commented 7 years ago

@Kostya Your example worked fine but below scenario is still a problem.

ev-www.opentable.com.edgekey.net - server with virtual hosting servers based on "Host" header, I am still getting the error. Also let me know how to update SNI

ssl_context = init_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_OPTIONAL

headers={'Host': 'www.opentable.com'}
conn = hyper.HTTP20Connection('ev-www.opentable.com.edgekey.net', port=443, ssl_context=ssl_context)
conn.request('GET', '/washington-dc-restaurants', headers=headers)

print conn.get_response()