using requests with TLS doesn't give SNI support
The current version of Requests should be just fine with SNI. Further down the GitHub issue you can see the requirements:
- pyOpenSSL
- ndg-httpsclient
- pyasn1
Try installing those packages and then give it another shot.
EDIT: As of Requests v2.12.1, ndg-httpsclient and pyasn1 are no longer required. The full list of required packages is now:
- pyOpenSSL
- idna
Python Requests SSL Error 504
The server requires SNI (server name indication) and will cause a TLS alert if the SNI extension is not used. SNI is available with python 3 and with python 2.7.9+. For older versions of python see using requests with TLS doesn't give SNI support.
SSL and TLS in Python requests
Requests uses the Python standard library ssl module under the hood - this supports various versions of SSL and TLS. You can tell requests to use a specific protocol (like TLSv1) by creating an HTTPAdapter
that customizes the PoolManager instance that gets created.
I had to do something like this, but was bitten by the fact that we were also going via a proxy - in that case the init_poolmanager
method isn't called, because it uses a ProxyManager
instead. I used this:
class ForceTLSV1Adapter(adapters.HTTPAdapter):
"""Require TLSv1 for the connection"""
def init_poolmanager(self, connections, maxsize, block=False):
# This method gets called when there's no proxy.
self.poolmanager = poolmanager.PoolManager(
num_pools=connections,
maxsize=maxsize,
block=block,
ssl_version=ssl.PROTOCOL_TLSv1,
)
def proxy_manager_for(self, proxy, **proxy_kwargs):
# This method is called when there is a proxy.
proxy_kwargs['ssl_version'] = ssl.PROTOCOL_TLSv1
return super(ForceTLSV1Adapter, self).proxy_manager_for(proxy, **proxy_kwargs)
Can SNI be enabled without problems to servers that do not support SNI in TLS handshake
SNI is an optional TLS extension ("server_name"). This means any proper TLS stack which does not explicitly support this extension will ignore it. SNI is widely used and all modern browsers have enabled it.
This gives some confidence that almost all sites should work if you use TLS with SNI enabled. There might be still some sites out there which use a broken TLS stack which will fail just because SNI is present. But these sites will fail too when accessed by a modern browser. Also, way more sites will fail if SNI is not present, like everything behind Cloudflare Free SSL. Thus enabling SNI by default and maybe dealing with the fallout of a very few broken sites is definitely better then dealing with lots of sites which don't work without SNI.
Why does Python's `requests` reject my SSL certificate, which browsers accept
You are using a requests library without support for SNI (server name indication), but you have multiple SSL certificates behind the same IP address which requires SNI. You can verify this with openssl s_client
. Without given a name for SNI the server just gives the default certificate for this IP, which is *.webfaction.com:
openssl s_client -connect ram.rachum.com:443
...
0 ...CN=*.webfaction.com
But if you specify a hostname for SNI it returns the expected certificate:
openssl s_client -connect ram.rachum.com:443 -servername ram.rachum.com
...
0 ...CN=ram.rachum.com...
Maybe you need to upgrade your requests library and other modules too, see using requests with TLS doesn't give SNI support
How to simulate non-SNI browsers (without SNI support)?
You can use the most commonly used SSL library, OpenSSL. Windows binaries are available to download.
openssl s_client -connect domain.com:443
command serves very well to test SSL connection from client side. It doesn't support SNI by default. You can append -servername domain.com
argument to enable SNI.
Python requests SSL certificate verification fails, even after adding CA certificates
You need to install pyopenssl and ndg-httpsclient
See using requests with TLS doesn't give SNI support for more details
Related Topics
How to Prevent Errno 32 Broken Pipe
How to Stop Flask from Initialising Twice in Debug Mode
How to Create an Encrypted Zip File
Why Do -1 and -2 Both Hash to -2 in Cpython
How to Dynamically Load a Python Class
Regular Expressions: Search in List
Why Does Python Pep-8 Strongly Recommend Spaces Over Tabs for Indentation
Check If All Elements of a List Are of the Same Type
How to Get Python's Elementtree to Pretty Print to an Xml File
Get Contents of a Tkinter Entry Widget
Getting a MAChine's External Ip Address with Python
How to Convert a Timezone Aware String to Datetime in Python Without Dateutil
How to Set Folder Permissions in Windows
Python Regular Expressions - How to Capture Multiple Groups from a Wildcard Expression
Why Doesn't Os.Path.Join() Work in This Case