我正在尝试完成这项任务,我有一个 IP,并且我想用该 IP 发出 HTTP 请求。
假设我有 stackoverflow.com 的 IP(151.101.193.69),我想使用 Python 模块向网站发出 HTTP 请求requests
。我写了这段代码
import requests
response = requests.get("http://151.101.193.69:80")
response.text
返回页面的 html 代码。这样做我得到一个页面,上面写着
Fastly error: unknown domain: 151.101.193.69. Please check that this domain has been added to a service.
Details: cache-mxp19846-MXP
但如果我使用 Google IP 执行此操作,它就会起作用,并且请求会返回 Google 主页
import requests
response = requests.get("http://216.58.205.174:80")
response.text
答案1
是的,这很正常。
HTTP 请求始终包含“Host:”标头,指示 URL 中实际使用的名称。例如,访问http://superuser.com
将发送标头Host: superuser.com
;如果您使用http://151.101.193.69
,则标头当然会显示Host: 151.101.193.69
(甚至完全不存在)。
重要的是,许多 HTTP 服务器为许多不同的域共享相同的 IP 地址(又称虚拟主机), 和他们依靠在此标题上了解您要访问哪个域。
例如,全部Stack Exchange 域名 – superuser.com
、stackoverflow.com
、serverfault.com
、diy.stackexchange.com
、… – 共享完全相同的 IP 地址集。网络服务器区分所有这些网站的唯一方法是查看“Host”HTTP 标头。
(此外,这些地址实际上属于 Fastly CDN,而不是真正的网络服务器。大型 CDN(如 Fastly 或 CloudFlare)可能会使用相同的 IP 地址数百来自不同客户的域名。
最后,由服务器决定如何处理它无法识别的“Host”标头。有些服务器会返回错误页面,说明这一点,而其他服务器则会返回它们拥有的“第一个”域。
因此,为了成功发出请求,您需要执行以下操作:
requests.get("http://151.101.193.69", headers={"Host": "stackoverflow.com"})
但这样说很愚蠢requests.get("http://stackoverflow.com")
。唯一可能需要这种方法的情况是,当你有一个 IP 地址没有匹配 DNS 信息(例如,如果您尝试绕过 DNS)。
(而且,当您尝试访问 HTTPS 网站时,它会给您带来更多问题,因为 URL 中的域名也用于检查 TLS 证书。)