Http權威指南筆記(六)——代理

上一篇學習了Web服務器,這一篇我來學習一下代理的知識。現在的網絡中存在着各種各樣的代理。學習Web代理服務器,更有利於我們隊網絡請求過程的理解。

簡介

代理服務器是網絡的中間實體,其既是Web服務器,也是Web客戶端。所以其必須要能正確處理客戶端的請求,並返回響應,同時也要能正確的向服務器發起請求並接收響應。

1.1 私有和共享代理

代理服務器可以作爲某個客戶端單獨使用的私有代理,也可以作爲衆多客戶端共有的代理服務器——即公共代理。
實際當中,公共代理更爲常見,它是一種集中式代理。比如緩存代理,我們可以將某一個區域的緩存放入一個代理服務器中,那這個區域任何客戶端都能利用同一個緩存代理
私有代理,相對來比較少見,一般都是用戶自行有某些特殊需求的時候,專門爲客戶端配置代理服務器。

1.2 代理與網關

代理與網關都是網絡中的中間實體,雖然看起來作用相似。但是他們有一點區別就是:代理連接的一般是用的同一種協議應用程序。而網關一般是用於連接不同協議的應用程序。如下圖就展示了代理與網關的區別:
代理與網關
上圖a中,Web代理與客戶端和服務器之間的傳輸協議都是用的HTTP協議。圖b的網關,與客戶端使用的是HTTP協議,與服務器端則採用的是POP協議。其作用是讓客戶可以在瀏覽器上用HTTP協議進行收發郵件了。

2 代理的用途

客戶端和服務器端直接通信相較於通過代理的時間,理論上來說應該更短,爲什麼還需要在中間加一個代理呢?這就不得不說代理的用途,或者說給我們帶來的好處。

  • 內容過濾器
    通過代理,我們可以對網絡上的資源進行過濾,某些不合適客戶端的資源,我們可以將其過濾掉。比如對於小孩而言,我們可以通過代理將網絡上的成人內容進行過濾,或者對於在校學生而言,我們可以過濾掉那些和學習無關的內容,讓學生專注於學習的內容。
  • 訪問權限控制
    這種用途在一些企業的裏面非常常見,通過對訪問控制的策略進行配置,達到控制員工的越級訪問。比如:銷售部的員工,不應該查詢公司保密財務資料和,這個時候我們可以通過代理,對發起請求的用戶進行判斷,如果需要訪問保密財務數據,就需要密碼之類的指令,否則阻止其對越級資源的訪問,如下圖所示:
    訪問權限控制
  • 安全防火牆
    網絡安全工程師通常會使用代理服務器來提高安全性。代理服務器會在網絡中的單一安全節點上限制哪些應用層協議的數據可以流入或流出一個組織。還可以提供用來消除病毒的 Web 和 E-mail 代理使用的那種掛鉤程序
  • Web緩存
    根據需要,我們可以在代理服務器上緩存某些資源的副本,客戶端在獲取資源的時候,就能夠直接在代理服務器中獲取,而無需連接最終目的Web服務器,既可以減少Web服務器的併發量,也能節約帶寬資源。
  • 反向代理
    代理可以假扮Web服務器與客戶端進行通信,這種代理通常被稱爲反向代理。他們代理服務器來接收客戶端的真實請求,然後根據需要,將請求定位到所需要的服務器資源。這種代理可以提高訪問慢速Web服務器時候的性能(即一個加速器的作用),同時也可以達到負載均衡的目的。當一個請求來到的時候,可以根據當前所有服務器的負載情況,將請求給負載相對較低的服務器進行處理。
  • 內容路由器
    對這一用途不是非常理解,目前理解就是可以將用戶分級,如:普通,付費,VIP等。然後根據不同的用戶,提供不同的內容,示例圖如下:
    內容路由器
  • 轉碼器
    代理服務器在將內容發送給客戶端之前,可以修改內容的主體格式。在這些數據表示法之間進行的透明轉換被稱爲轉碼(transcoding)。如:傳輸圖片或者文檔的時候,可以先對其進行壓縮,然後再進行傳輸。
  • 匿名代理
    匿名代理的主要目的在於保護隱私,它會主動的從HTTP報文中書刪除一些和用戶身份信息相關的東西,如客戶端 IP 地址、From 首部、Referer 首部、cookie、URI 的會話 ID。

3 代理的層次及結構

3.1 代理的部署位置

根據代理的目的不同,可以將代理部署在不同的地方,常見的如下圖所示:
代理的位置
圖a中的代理,部署在LAN的出口處的局部私有代理,由其統一代理和管理本地客戶端發起的請求。這樣可以就本地客戶端發起請求進行管理。如:很多企業會使用該種方式,管理員工日常工作中的網絡訪問,一些不允許訪問的地址就會被攔截和過濾。
圖b中的代理,一般被稱爲訪問代理,這種代理在IPS提供商會經常用到,可以集中處理客戶端的請求,同時可以作爲緩存代理,將一些經常使用的資源進行緩存,讓用戶可以高速訪問資源,同時節約帶寬資源。
圖c中的就是常說的反向代理,這個前面已經介紹過了,這裏不摘贅述。
圖d一般被稱爲網絡交換器,放在真正的英特網交換節點中間,也是可以通過緩存來實現減少英特網節點之間的擁堵,同時也能實現對流量進行監控。

3.2 代理的層次結構

所謂的代理層級結構,即代理相互之間的關係。在關係當中涉及到父代理和子代理兩個概念。這兩個概念是同時成對出現,是一種相對的概念。父代理是指更靠近服務器端的代理,相對的子代理即更靠近客戶端的代理。以下圖爲例:
代理層次結構
代理2爲代理1的父代理,代理3位代理2的父代理,代理2稱爲代理3的子代理,代理1稱爲代理2的子代理。
在實際當中,一般代理的層次結構並非是禁止不變的,根據請求的不同,可能代理會選擇將請求轉發給不同的下級代理,甚至直接轉發給原始Web服務器。實際當中,常見的動態代理情景有如下幾個:

  • 負載均衡——代理會根據當前它的下一級代理的負載情況,來決定將當前請求轉發給哪個父代理,以便達到負載均衡的目的。
  • 地理位置附件路由——代理會根據當前地理位置和請求的情況,選擇不同地方的父代理。
  • 協議/類型路由——根據商定的協議或者URI來決定將當前請求轉發到哪個父代理上。
  • 基於訂購的路由——也就是常見的如果是付費用戶,就將轉發到高速緩存服務器,如果是普通用戶,就轉發到一般的Web服務器。這樣就能提高付費用戶的體驗性能。

3.3 如何將請求流行代理

  • 修改客戶端配置——可以直接修改客戶端(如瀏覽器)的配置,讓其請求發送到我們制定的代理上。
  • 修改網絡——這種一般是網絡服務提供商進行的操作,這些服務商對網絡交換和路由設備進行監視,再需要的時候,對請求進行攔截轉發。一般對用戶而言是透明的。用戶感知不到請求被髮送到代理了。
  • 修改DNS命名空間——通過對DNS的命名空間進行修改,讓代理假扮服務器的角色。這樣客戶端發送給Web服務器的請求就會被髮送到代理。如日常使用的反向代理,客戶端正常發送的請求會先被髮送到方向代理,然後再由其真正給到Web服務器。
  • Web服務器的配置——通過對Web服務器進行修改和配置,將一些請求通過重定向的方式轉發到代理服務器上。

4 追蹤報文

現在將請求從客戶端發送到服務端的路徑上通過多個代理的轉發是很常見的。有時候當出現問題的時候,我們需要跟蹤整個請求路徑上報文的轉發流程,本節就是介紹怎麼去跟蹤代理轉發的報文。

4.1 Via首部

HTTP規範指定了如果有Via首部,報文每經過一個節點,都需要將該節點添加到Via列表的末尾。通過Via首部,我們可以記錄報文轉發,診斷報文的循環等問題。

  1. Via的語法
    每個 Via 路標中最多包含 4 個組件:一個可選的協議名(默認爲 HTTP)、一個必選的協議版本、一個必選的節點名和一個可選的描述性註釋。其語法格式如下:
Via               = "Via" ":" 1#( waypoint )
waypoint          = ( received-protocol received-by [ comment ] )
received-protocol = [ protocol-name "/" ] protocol-version
received-by       = ( host [ ":" port ] ) | pseudonym

其中:
協議名:默認爲HTTP,如果是HTTP可以省略,如果不是,則必須加上
協議版本:這個字段的格式和協議有關,如HTTP協議的就是 1.0,1.1等
節點名:主機名加端口號。端口號如果省略,則人爲是該協議的默認端口號,主機名不一定是真實的。
節點註釋:用於對節點的註釋說明,可以省略。
如下面的Via首部:
Via = 1.1 cache.joes-hardware.com, 1.1 proxy.irenes-isp.net
說明有兩個代理,第一個代理是 HTTP協議的1.1版本,節點爲cache.joes-hardware.com,第二個代理也是HTTP協議的1.1版本,節點名稱爲proxy.irenes-isp.net

  1. Via的請求和響應路徑
    請求和響應報文都會經過代理進行傳輸,因此,請求和響應報文中都要有 Via 首部。
    請求和響應通常都是通過同一條 TCP 連接傳送的,所以響應報文會沿着與請求報文相同的路徑回傳。如果一條請求報文經過了代理 A、B 和 C,相應的響應報文就會通過代理 C、B、A 進行傳輸。因此,響應的 Via 首部基本上總是與請求的 Via 首部相反
  2. Via與網關
    有些代理會爲使用非 HTTP 協議的服務器提供網關的功能。Via 首部記錄了這些協議轉換,這樣,HTTP 應用程序就會了解代理鏈上各點的協議處理能力以及所做的協議轉換了
  3. Server與Via首部
    Server首部是用於對原始服務器的描述,如:
Server: Apache/1.3.14 (Unix) PHP/4.0.4
Server: Netscape-Enterprise/4.1
Server: Microsoft-IIS/5.0

Server首部不能用於代理,代理不應該對該首部首部進行修改,代理只需要添加Via即可。

  1. Via和隱私、安全問題
    如果出於隱私或者安全考慮,不想提供主機名和端口號等信息。可以使用一個假的節點信息,但是必須要有節點信息。同時如果是同一組織下的同一協議,且同一版本,可以將多個節點合併爲一個節點。但是前提是同一組織,同一協議,同一協議版本。任何一個不同都不能進行合併。

4.2 TRACE方法

通過 HTTP/1.1 的 TRACE 方法,用戶可以跟蹤經代理鏈傳輸的請求報文,觀察報文經過了哪些代理,以及每個代理是如何對請求報文進行修改的。TRACE 對代理流的調試非常有用。當然,前提是要服務器支持TRACE方法。
如下所示,展示了TRACE方法請求響應過程:
TRACE方法
從圖中可以看到,TRACE的處理過程爲:當TRACE請求到達服務器後,如果服務器支持該方法,會將完整的請求報文封裝爲響應體,然後返回給客戶端。響應頭中的Content-type的值爲:message/http。客戶端收到該響應後,就能通過響應體中的數據知道請求報文最終被修改後的內容。
一般情況下,TRACE的請求會沿着整條路徑一路轉發,最終達到原始服務器。但是如果請求體中包含Max-forward,那轉發次數就會被限制在該首部規定的值以內。工作原理是,沒經過一次轉發,就會將Max-forward的值-1,當其值爲0的時候,就證明達到了最大限制,這個時候無論是否達到最終服務器,都應該結束該條請求繼續轉發,並返回響應。

5 代理認證

代理可以作爲訪問控制設備使用。HTTP 定義了一種名爲代理認證(proxy authentication)的機制,這種機制可以阻止對內容的請求,直到用戶向代理提供了有效的訪問權限證書爲止。
其工作流程如下:

  1. 當一個受限訪問的請求達到代理時,代理檢查該訪問是否有權限,如果沒有,會返回一個407狀態碼和Proxy Authorization Required的信息,告知客戶端需要使用證書。同時可以包含一個怎麼獲取該證書的描述信息。
  2. 客戶端收到該響應後,會根據提示嘗試獲取證書,或者提示用戶提供證書
  3. 客戶端獲得證書後,會再次發送請求,這次會在請求頭中添加Proxy-Authorization字段來提供證書
  4. 服務器收到請求,會判斷證書是否有效,有效則繼續後面的流程,否則回到1的情況。

6 代理的互操作性

由於客戶端,代理、服務器都是由不同的廠商進行提供。那就意味着它們之間或多或少存在一些差異。某些首部字段,可能代理支持,但是服務器不支持,又或者一些請求方法,服務器支持,代理不支持。爲了更好的系統工作,一般採用如下的原則進行處理。

  1. 當代理遇到自己不能處理的首部字段的時候,一般應該將其進行轉發,並且保持原有的順序,同樣,如果代理對某個方法無法處理,其應該嘗試將報文轉發到下一級節點。
  2. 通過OPTIONS方法,用於判斷服務器所支持的特性,這樣在請求前知道了服務器所支持的特性,就能更好的同不同代理和服務器之間進行互操作了
    OPTIONS請求的URI如果是一個”*“號,請求的就是整個服務器所支持的功能,如果請求的URI是某個具體的資源,就是查詢指定資源支持的功能。如果OPTIONS請求成功,會返回一個200 OK的響應。其有一個Allow首部字段,其值會列出所有支持的請求方法。如:
    Allow: GET, HEAD, PUT

7 代理的一些其他問題

7.1 代理的URI和服務器URI的區別

客戶端向代理和服務器發送請求的時候,URI是有區別的。如果是向服務器發送請求,URI一般不會包含shceme,host和port,如:

GET /index.html HTTP/1.0
User-Agent: SuperBrowser v1.3

如果是向代理髮起請求,就會包含完整的URI路徑,如:

GET http://www.marys-antiques.com/index.html HTTP/1.0
User-Agent: SuperBrowser v1.3

之所以出現上述的區別,是因爲,最初沒有代理的時候,客戶端發送的請求都是給最終服務器的,服務器是知道自己的主機名和端口等信息的,所以爲了減少冗餘信息,發送部分URI就可以了。但是代理出現以後,代理可能並不是針對某單個服務器的,這個時候嗎,如果沒有完整的URI路徑,代理就無法知道將該請求發往哪個下一級節點。
但是我們客戶端並不一定都顯式的知道請求是發文代理還是服務器的,這個時候採用如下原則:

  1. 沒有顯示設置代理的客戶端,會發送部分URI;
  2. 明確設置了代理,或者客戶端明確知道自己將要發送給代理的時候,發送完整的URI

到這裏還需要提到的一點是,上述提到的問題,即除了URI中的路徑部分外,還需要確定主機名。除了代理會遇到這個問題,前面章節提到的虛擬Web服務器也會遇到相同的問題,但是解決方式是不同,代理同時是要求直接使用完整的URI,Web虛擬主機是需要Host請求頭來提供主機和端口信息。

7.2 攔截代理的URI處理

上一小節提到了,客戶端在知道是發送給代理的時候,是發送完整的URI,但是像一些攔截作用的代理,客戶端一般是不知道請求是發給代理的,這個時候,客戶端默認只會發送部分URI。這個時候,攔截代理怎麼處理請求呢?這個時候就要求我們的代理要具有處理部分URI的能力。一般代理的處理原則如下:

  • 如果提供了完的URI,則使用完整的URI
  • 如果提供了部分URI,但是有Host請求頭,應該使用Host的值來確定主機名和端口信息
  • 如果提供了部分URI,且沒有Host請求頭,按照下面的方式處理:如果代理是反向代理一類的代理,可以用真實服務器的地址和端口號來配置代理;如果是攔截代理一類的代理,一般攔截者本身是可以提供真實主機地址和端口信息的
  • 如果代理最終都無法獲得真實的主機地址和端口號等必要信息,就必須返回一條錯誤報文給客戶端,讓其提供Host請求頭

最後除了上述提到的問題外,另外一個代理還需要注意的問題是,對URI的修改問題。有時候可能客戶端提供的URI並不一定非常規範,這個時候代理檢查到問題後,需要做的是能夠識別出URI,就進行轉發或者處理該請求,不行就返回錯誤信息,不要嘗試去修正URI。雖然修正URI出發點是好的,但是可能會造成一些其他問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章