san*_*lio 4 networking linux ip curl msys2
我的意思是使用IP而不是服务器名称,直接curl
从http://...
.\n我在Msys2,Win 10下(这就是为什么在这里发帖而不是在askubuntu中发帖的原因,例如),但我想这将是在 Linux 中也一样。
我无法完成这项工作。\n我在下面发布了我尝试过的详细信息。\n我使用 时遇到了类似的失败wget
。\n我写了一篇单独的文章,因为我不确定解释和解决方案与此处相同。
这样做的正确方法是什么?
\n注意:使用curl ftp://<IP>/...
\n 而不是curl http://<IP>/...
\n 效果很好。
这是我尝试过的:
\n $ ping us.archive.ubuntu.com\n \n Haciendo ping a us.archive.ubuntu.com [91.189.91.38] con 32 bytes de datos:\n Respuesta desde 91.189.91.38: bytes=32 tiempo=173ms TTL=52\n Respuesta desde 91.189.91.38: bytes=32 tiempo=166ms TTL=52\n Respuesta desde 91.189.91.38: bytes=32 tiempo=172ms TTL=52\n \n Estad\xc3\xadsticas de ping para 91.189.91.38:\n Paquetes: enviados = 3, recibidos = 3, perdidos = 0\n (0% perdidos),\n Tiempos aproximados de ida y vuelta en milisegundos:\n M\xc3\xadnimo = 166ms, M\xc3\xa1ximo = 173ms, Media = 170ms\n Control-C\n
Run Code Online (Sandbox Code Playgroud)\ncurl
使用服务器名称读取该文件。\n工作正常。$ curl -L http://us.archive.ubuntu.com/ubuntu/pool/universe/y/yudit/yudit-common_2.9.6-7_all.deb --output yudit-common_2.9.6-7_all.deb\n % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 1599k 100 1599k 0 0 256k 0 0:00:06 0:00:06 --:--:-- 344k\n
Run Code Online (Sandbox Code Playgroud)\ncurl
使用 IP 地址 ing 该文件。\n它不起作用。\n附加--header "Host:us.archive.ubuntu.com"
到命令行会产生完全相同的结果。\n我不确定这会丢弃“主机标头”问题作为原因。$ curl -L http://91.189.91.39/ubuntu/pool/universe/y/yudit/yudit-common_2.9.6-7_all.deb --output yudit-common_2.9.6-7_all.deb\n % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n100 274 100 274 0 0 76 0 0:00:03 0:00:03 --:--:-- 76\n\n$ cat yudit-common_2.9.6-7_all.deb\n<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested URL was not found on this server.</p>\n<hr>\n<address>Apache/2.4.29 (Ubuntu) Server at 91.189.91.39 Port 80</address>\n</body></html>\n
Run Code Online (Sandbox Code Playgroud)\n编辑\n根据gronostaj 的回答,我尝试了两个命令。
\nA. 这有效(与上面第 2 条相同),
\n $ curl -v --resolve us.archive.ubuntu.com:80:91.189.91.39 -L http://us.archive.ubuntu.com/ubuntu/pool/universe/y/yudit/yudit-common_2.9.6-7_all.deb -- output yudit-common_2.9.6-7_all.deb\n ...\n <\n { [7725 bytes data]\n 0 1599k 0 7725 0 0 5360 0 0:05:05 0:00:01 0:05:04 7874* STATE: PERFORM => DONE handle 0x800744e0; line 2199 (connection #0)\n * multi_done\n 100 1599k 100 1599k 0 0 675k 0 0:00:02 0:00:02 --:--:-- 838k\n * Connection #0 to host us.archive.ubuntu.com left intact\n
Run Code Online (Sandbox Code Playgroud)\nB. 这没有(与上面第 3 条相同)。
\n $ curl -v --resolve us.archive.ubuntu.com:80:91.189.91.39 -L http://91.189.91.39/ubuntu/pool/universe/y/yudit/yudit-common_2.9.6-7_all.deb --output yu dit-common_2.9.6-7_all.deb\n ...\n <\n { [274 bytes data]\n 100 274 100 274 0 0 434 0 --:--:-- --:--:-- --:--:-- 444* STATE: PERFORM => DONE handle 0x800744c8; line 2199 (connection #0)\n * multi_done\n 100 274 100 274 0 0 430 0 --:--:-- --:--:-- --:--:-- 439\n * Connection #0 to host 91.189.91.39 left intact\n
Run Code Online (Sandbox Code Playgroud)\n我想知道 B 是否是第 3 项失败的正确修复,或者它实际上使用的是服务器名称而不是直接 IP(如第 2 项中所示)。
\n服务器并不“只知道”请求的是哪个域:客户端正在解析域名本身并直接连接到 IP。事实证明,从单个 IP 为多个网站提供服务的能力会很方便,因此Host
在 HTTP 标准的修订版中引入了该标头。符合规范的 HTTP 客户端将从请求 URL 中提取域并将其发送到Host
标头中:
实施例1
$ curl -v superuser.com
* Rebuilt URL to: superuser.com/
* Trying 151.101.1.69...
* TCP_NODELAY set
* Connected to superuser.com (151.101.1.69) port 80 (#0)
> GET / HTTP/1.1
> Host: superuser.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< cache-control: no-cache, no-store, must-revalidate
< location: https://superuser.com/
[...]
<
* Connection #0 to host superuser.com left intact
Run Code Online (Sandbox Code Playgroud)
客户端将Host: superuser.com
请求中的标头发送到 的superuser.com
IP。服务器回复请求重定向到该站点的 HTTPS 版本。没有文档正文,这是有道理的,因为浏览器应该重定向您。curl
没有 就不会这样做-L
。
现在我们尝试直接使用IP:
实施例2
$ curl -v 151.101.1.69
* Rebuilt URL to: 151.101.1.69/
* Trying 151.101.1.69...
* TCP_NODELAY set
* Connected to 151.101.1.69 (151.101.1.69) port 80 (#0)
> GET / HTTP/1.1
> Host: 151.101.1.69
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 500 Domain Not Found
< Server: Varnish
[...]
<
<html>
<head>
<title>Fastly error: unknown domain 151.101.1.69</title>
</head>
<body>
<p>Fastly error: unknown domain: 151.101.1.69. Please check that this domain has been added to a service.</p>
* Connection #0 to host 151.101.1.69 left intact
<p>Details: cache-ams21021-AMS</p></body></html>
Run Code Online (Sandbox Code Playgroud)
curl
在标头中发送 IP Host
,响应是 500 错误,正文详细说明了问题。服务器不为Host
标头中提供的域提供服务。
让我们手动提供标头:
实施例3
$ curl -H 'Host: superuser.com' -v 151.101.1.69
* Rebuilt URL to: 151.101.1.69/
* Trying 151.101.1.69...
* TCP_NODELAY set
* Connected to 151.101.1.69 (151.101.1.69) port 80 (#0)
> GET / HTTP/1.1
> Host: superuser.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< cache-control: no-cache, no-store, must-revalidate
< location: https://superuser.com/
[...]
<
* Connection #0 to host 151.101.1.69 left intact
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,我们再次获得了重定向。服务器并不“仅仅知道”请求是通过直接提供IP来发出的,因为它总是这样发出的:客户端负责解析域名。事实证明,从单个 IP 为多个网站提供服务的能力会很方便,因此Host
在 HTTP 标准的修订版中引入了该标头。
不幸的是,这不适用于 HTTPS。HTTPS 基本上是用 TLS 封装的 HTTP。在通过 HTTP 发送任何内容之前,需要先设置 TLS 连接。此过程涉及服务器为请求的域提供适当的证书。为此需要该领域的知识,因此我们回到了第一个方面。此问题已由 SNI 解决,SNI 是 TLS 的扩展,它指定客户端如何将域通信到服务器,以便可以使用正确的证书。
您可以使用以下命令通过curl 来模拟这一点--resolve
:
实施例4
$ curl -v --resolve superuser.com:443:151.101.65.69 https://superuser.com
* Added superuser.com:443:151.101.65.69 to DNS cache
* Rebuilt URL to: https://superuser.com/
* Hostname superuser.com was found in DNS cache
[...]
* Connected to superuser.com (151.101.65.69) port 443 (#0)
[...]
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=*.stackexchange.com
* start date: Aug 7 13:01:00 2020 GMT
* expire date: Nov 5 13:01:00 2020 GMT
* subjectAltName: host "superuser.com" matched cert's "superuser.com"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
[...]
> GET / HTTP/2
> Host: superuser.com
> User-Agent: curl/7.58.0
> Accept: */*
>
[...]
< HTTP/2 200
< cache-control: private
< content-type: text/html; charset=utf-8
[...]
<!DOCTYPE html>
[...]
Run Code Online (Sandbox Code Playgroud)
--resolve
绕过给定主机的 DNS 解析。正如手册所说,它是“一种 /etc/hosts 的替代方案”。参数语法是<host>:<port>:<ip>
. 所以这个命令:
实施例5
curl -v --resolve superuser.com:443:151.101.65.69 https://superuser.com
Run Code Online (Sandbox Code Playgroud)
方法:
-v
:详细(打印标头和 TLS 详细信息)--resolve superuser.com:443:151.101.65.69
:如果连接到superuser.com
端口443
,则实际使用IP 151.101.65.69
https://superuser.com
:使用 HTTPS 向 superuser.com 发出请求至于为什么域必须重复两次,当对单个卷曲调用发出多个请求时,例如由于重定向和-L
被提供,这是有意义的:
实施例6
$ curl -v --resolve superuser.com:443:151.101.65.69 -L http://superuser.com
Run Code Online (Sandbox Code Playgroud)
该命令将首先superuser.com
使用 DNS 进行解析。--resolve
不适用于此请求,因为它是为端口 443 指定的,而我们通过 HTTP 在端口 80 上进行连接。服务器响应 301 重定向到https://superuser.com
。我们已经指定了-L
,因此curl 将向该URL 发出第二个请求。这次是通过端口 443 上的 HTTPS 进行的,我们已使用 为该主机和端口指定了 IP --resolve
,因此将使用指定的 IP(忽略先前的 DNS 查找)。Host
在这两种情况下都会生成标头,因为superuser.com
这就是我们所要求的。
这是实际的卷曲输出。请注意,第二个请求会生成“在 DNS 缓存中找到主机名 superuser.com”消息,该消息已--resolve
生效。
实施例6(续)
* Added superuser.com:443:151.101.65.69 to DNS cache
* Rebuilt URL to: http://superuser.com/
* Trying 151.101.65.69...
* TCP_NODELAY set
* Connected to superuser.com (151.101.65.69) port 80 (#0)
> GET / HTTP/1.1
> Host: superuser.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< cache-control: no-cache, no-store, must-revalidate
< location: https://superuser.com/
[...]
* Ignoring the response-body
[...]
* Connection #0 to host superuser.com left intact
* Issue another request to this URL: 'https://superuser.com/'
* Hostname superuser.com was found in DNS cache
* Trying 151.101.65.69...
* TCP_NODELAY set
* Connected to superuser.com (151.101.65.69) port 443 (#1)
[...]
Run Code Online (Sandbox Code Playgroud)
--resolve
使用时--resolve
,必须请求域名(,而不是直接请求IP。请求IP将:
Host
为 IP 而不是域生成标头,--resolve
不适用,因为--resolve
绕过域名解析,当没有提供域名时,不需要域名解析。所以你想要这个:
实施例7
curl --resolve example.com:80:93.184.216.34 http://example.com
Run Code Online (Sandbox Code Playgroud)
而不是这个:
实施例8
curl --resolve example.com:80:93.184.216.34 http://93.184.216.34
Run Code Online (Sandbox Code Playgroud)
在示例 7 中,curl
将使用 提供的 IP 地址--resolve
,而不是example.com
DNS 解析的 IP 地址。
--resolve
适用每个--resolve
(允许多个)由 3 个组件组成:主机、端口和 IP。--resolve
如果主机和端口匹配,则适用于请求,在这种情况下,将绕过此特定请求的 DNS 解析并--resolve
使用匹配的 IP。在许多情况下,单个curl
调用仅发出一个请求,在这种情况下,--resolve
仅当其主机和端口与请求的主机和端口匹配时才有意义。所以这个调用没有意义,因为--resolve
由于端口不匹配而永远不会匹配(HTTPS默认使用443):
实施例9
curl --resolve example.com:80:93.184.216.34 https://example.com
Run Code Online (Sandbox Code Playgroud)
每次调用何时curl
发出多个请求?我知道的情况是何时-L
提供并且第一个请求导致 3xx 响应(它是重定向响应系列,请参阅httpstatuses.com)。这些响应带有一个Location
标头,告诉浏览器向该标头中提供的地址发出另一个请求。如果没有-L
,curl
将简单地打印 3xx 响应。-L
它将像浏览器一样发出另一个请求。(请注意,第二个请求也可能导致 3xx 响应,从而生成第三个请求,依此类推)。
例如,对 superuser.com 的 HTTP 请求会导致 301 响应,并重定向到 HTTPS 版本,请参阅示例 1,其中Location
显示了标头。这样-L
您会得到一个与您首先请求 HTTPS 版本相同的响应。HTTP 和 HTTPS 使用不同的端口(80 和 443),因此--resolve
在这种情况下您需要两个 s,每个端口一个。您还可以有意仅指定一个来覆盖仅针对 HTTP(或 HTTPS)请求的域名解析,而让另一个指向 DNS 将返回的实际 IP。
归档时间: |
|
查看次数: |
29126 次 |
最近记录: |