admin管理员组文章数量:1289537
Background for this question: In a project, we have some data on a shared webhosting. The DNS record for the site is with CloudFlare and is using its proxied DNS feature.
So far so good, and creating a request like
urllib.request.Request(
'.zip',
headers={...}
)
and subsequent download works just fine.
Now, because of (performance) side-effects of the proxy-DNS, I wanted to access the data using the direct IP of the webhosting. I have to supply 'Host'
in the headers
because it is a shared webshosting.
When I do this using http
, everything still works fine, i.e. like so:
urllib.request.Request(
"http://123.456.100.1/myfile.zip",
headers={'Host': 'www.example'}
)
The problem is now when doing the same with https
I get this error:
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '123.456.100.1'
Hence, finally the question:
How can I download a file using https
and directly using the IP, while still using the Host
argument for the certificate verification?
Background for this question: In a project, we have some data on a shared webhosting. The DNS record for the site is with CloudFlare and is using its proxied DNS feature.
So far so good, and creating a request like
urllib.request.Request(
'https://www.example./myfile.zip',
headers={...}
)
and subsequent download works just fine.
Now, because of (performance) side-effects of the proxy-DNS, I wanted to access the data using the direct IP of the webhosting. I have to supply 'Host'
in the headers
because it is a shared webshosting.
When I do this using http
, everything still works fine, i.e. like so:
urllib.request.Request(
"http://123.456.100.1/myfile.zip",
headers={'Host': 'www.example.'}
)
The problem is now when doing the same with https
I get this error:
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '123.456.100.1'
Hence, finally the question:
How can I download a file using https
and directly using the IP, while still using the Host
argument for the certificate verification?
1 Answer
Reset to default 0There is no documented way to pass a hostname while using urllib
. If you really need to perform the hostname check, you can use a raw socket instead:
import socket, ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(s, server_hostname="www.example.")
ssl_sock.connect(("23.211.125.73", 443))
ssl_sock.send(b"GET / HTTP/1.0\r\nHost: www.example.\r\n\r\n")
while data := ssl_sock.recv(1024):
print(data.decode("utf-8"))
ssl_sock.close()
If you are willing to take the risk (See @PresidentJamesK.Polk's comment below), you can skip SSL hostname checking by setting check_hostname
to False
:
import ssl
import urllib.request
context = ssl.create_default_context()
context.check_hostname = False
request = urllib.request.Request(
url="https://23.211.125.73",
headers={"Host": "www.example."},
)
response = urllib.request.urlopen(request, context=context)
print(response.read().decode("utf-8"))
本文标签: pythonSSL certificate verification when accessing a server via IPStack Overflow
版权声明:本文标题:python - SSL certificate verification when accessing a server via IP - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741404515a2376862.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
SSLContext
object, which you pass with thecontext=
option. – Barmar Commented Feb 20 at 22:48hostname.shared.3xyz.myhosting
. That DNS name should not be proxied by Cloudflare. That should be the URL you use, not an IP address. And, again, if your setup is like mine, the certificate will have both your DNS names as subject alternative names. – President James K. Polk Commented Feb 21 at 2:03