2017-08-03 29 views
2

在我正在阅读的一本书中,作者显示了HTTP标头的含义。也就是说他说有多台服务器托管多个网站。多个站点共享一个IP地址:我无法使用Host标头访问特殊站点

让我们做到这一点:

ping fideloper.com 

我们可以看到IP地址:198.211.113.202。

现在让我们仅使用IP地址:

curl -I 198.211.113.202 

我们赶上:

$ curl -I 198.211.113.202 
HTTP/1.1 301 Moved Permanently 
Server: nginx 
Date: Thu, 03 Aug 2017 14:48:33 GMT 
Content-Type: text/html 
Content-Length: 178 
Connection: keep-alive 
Location: https://book.serversforhackers.com/ 

让我们接下来看,当我们一个主机头添加到HTTP请求会发生什么:

$ curl -I -H "Host: fideloper.com" 198.211.113.202 
HTTP/1.1 200 OK 
Server: nginx 
Content-Type: text/html; charset=UTF-8 
Connection: keep-alive 
Vary: Accept-Encoding 
Cache-Control: max-age=86400, public 
Date: Thu, 03 Aug 2017 13:23:58 GMT 
Last-Modified: Fri, 30 Dec 2016 22:32:12 GMT 
X-Frame-Options: SAMEORIGIN 
Set-Cookie: laravel_session=eyJpdiI6IjhVQlk2UWcyRExsaDllVEpJOERaT3dcL2d2aE9mMHV4eUduSjFkQTRKU0R3PSIsInZhbHVlIjoiMmcwVUpNSjFETWs1amJaNzhGZXVGZjFPZ3hINUZ1eHNsR0dBV1FvdE9mQ1RFak5IVXBKUEs2aEZzaEhpRHRodE1LcGhFbFI3OTR3NzQxZG9YUlN5WlE9PSIsIm1hYyI6ImRhNTVlZjM5MDYyYjUxMTY0MjBkZjZkYTQ1ZTQ1YmNlNjU3ODYzNGNjZTBjZWUyZWMyMjEzYjZhOWY1MWYyMDUifQ%3D%3D; expires=Thu, 03-Aug-2017 15:23:58 GMT; Max-Age=7200; path=/; httponly 
X-Fastcgi-Cache: HIT 

这意味着serversforhackers.com是默认站点。

于是笔者说,我们可以要求黑客服务器在同一台服务器上:

$ curl -I -H "Host: serversforhackers.com” 198.211.113.202 

在这里,在这本书HTTP /接收1.1 200 OK。

但我receve这样的:

curl -I -H "Host: serversforhackers.com" 198.211.113.202 
HTTP/1.1 301 Moved Permanently 
Server: nginx 
Date: Thu, 03 Aug 2017 14:55:14 GMT 
Content-Type: text/html 
Content-Length: 178 
Connection: keep-alive 
Location: https://book.serversforhackers.com/ 

那么,笔者组织了301重定向,现在使用HTTPS。

我可以这样做:

curl -I https://serversforhackers.com 

但这并不说明什么默认网站的整体思路,以及如何主机头可以解决在共享IP地址的特殊部位。

是否仍有可能通过IP地址获得200 Ok的地址?

回答

2

在没有HTTPS的HTTP/1.1中,Host标头是唯一将主机名发送到服务器的地方。

使用HTTPS,事情更有趣。

首先,你的客户通常会尝试检查服务器的TLS证书与预期名称:

$ curl -I -H "Host: book.serverforhackers.com" https://198.211.113.202 
curl: (51) SSL: certificate subject name (book.serversforhackers.com) does not match target host name '198.211.113.202' 

大多数客户提供一种方式来覆盖此检查。卷曲,虽然以-k/--insecure选项:

$ curl -k -I -H "Host: book.serverforhackers.com" https://198.211.113.202 
HTTP/1.1 200 OK 
Server: nginx 
[...] 

但然后还有第二个问题。我不能与你的榜样服务器来说明它,但这里有一个我在网上查到:

$ curl -k -I https://analytics.usa.gov 
HTTP/1.1 200 OK 
Content-Type: text/html 
[...] 

$ host analytics.usa.gov | head -n 1 
analytics.usa.gov has address 54.240.184.142 

$ curl -k -I -H "Host: analytics.usa.gov" https://54.240.184.142 
curl: (35) gnutls_handshake() failed: Handshake failed 

这是由server name indication (SNI)造成的 - TLS的功能(HTTPS),其中主机名是在发送TLS握手。这是必要的,因为服务器在它可以接收任何HTTP头之前需要提供正确的证书(对于正确的主机名)。在上面的例子中,当我们使用https://54.240.184.142时,curl不发送正确的SNI,服务器拒绝握手。其他服务器可能会接受连接,但将其路由到错误的地方,其中Host标题最终会被忽略。

使用卷曲,您不能像设置Host标头那样使用单独的选项来设置SNI。 curl将始终从请求URL中获取它。但卷曲有一个特殊的--resolve选项:

为特定主机和端口对提供自定义地址。使用这种方法,可以使curl请求使用指定的地址,并防止使用正常解析的地址。考虑它是在命令行上提供的一种/ etc/hosts替代品。

在这种情况下:

$ curl -I --resolve analytics.usa.gov:443:54.240.184.142 https://analytics.usa.gov 
HTTP/1.1 200 OK 
Content-Type: text/html 
[...] 

(443是HTTPS的标准TCP端口)

如果你想在一个较低的水平进行实验,您可以使用openssl工具建立原始TLS与正确的SNI连接:

$ openssl s_client -connect 54.240.184.142:443 -servername analytics.usa.gov -crlf 

然后,您将能够键入HTTP请求并查看正确的回应:

HEAD/HTTP/1.1 
Host: analytics.usa.gov 

HTTP/1.1 200 OK 
Content-Type: text/html 
[...] 

最后,请注意,HTTP/2,有一个名为:authority特殊头(是的,有一个冒号)可以由某些客户端可以用来代替Host。它们之间的区别在于与HTTP/1.1和代理的向后兼容性:有关详细信息,请参阅RFC 7540 § 8.1.2.3RFC 7230 § 5.3

相关问题