2017-08-03 45 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

相關問題