astutobufsofaasqor
astutobufsofaasqor

Reputation: 21

Problem when accessing hosts using Python Requests via HTTPS via their IP

I am currently facing a weird problem when trying to access a server via Python Requests:

This server is using a certificate generated by a CA and the client uses a certificate signed by that same CA. The CA is signed by a self-signed root CA. When accessing a server using a hostname like this

requests.get("https://example.com/", verify="root.pem", timeout=3)

it works without any problems whatsoever. When the same code is running against a server that is only accessible via a public IP and also has a certificate with the common name and subject alternative name set to this IP, then this code fails with the error message

requests.get("https://<IP>/", verify="root.pem", timeout=3)

requests.exceptions.SSLError: HTTPSConnectionPool(host='<IP>', port=443): Max retries exceeded with url: /test/ (Caused by SSLError(SSLCertVerificationError("hostname '<IP>' doesn't match '<IP>'")))

even though for example the OpenSSL s_client does not report any errors when connecting.

Online I could not find anyone else reporting or solving this issue where there were no hostnames involved but only plain IPs. The certificates themselves are also not at issue, since checking them against one another produces no errors. Especially the error message confuses me, since the IPs are clearly the same.

Upvotes: 1

Views: 1246

Answers (2)

astutobufsofaasqor
astutobufsofaasqor

Reputation: 21

I actually found the error now, it stemmed from a wrong assumptions, that an IP address should also be documented in the certificate using the DNS name extension. I was unaware that there is an IP address extension available for such purposes. Using this resolved the issue for me.

Upvotes: 1

Steffen Ullrich
Steffen Ullrich

Reputation: 123340

Python is perfectly right. The domain given in the URL must match the subject(s) of the certificate. If you want to call it by IP then the IP has to be one of the certificates subjects (i.e. subject alternative names).

... even though for example the OpenSSL s_client does not report any errors when connecting.

This is because older versions of OpenSSL simply don't check the hostname and thus

Verify return code: 0 (ok)

Newer versions like 1.1.1 actually do which will cause something like this

Verify return code: 62 (Hostname mismatch)

Note that it is also very common that there are multiple domains on the same IP address with different certificates. And that the content served on these domains can be different from each other. And that content served on IP itself without a specific domain can again be different. Thus, expecting that IP and domain can simply be used alternatively and mean the same is the wrong expectation.

Upvotes: 1

Related Questions