透明代理實質上類似一種攔截,用戶端以為自己訪問的是自己要訪問的伺服器,實際上這次訪問早已被所謂的透明代理接管了,透明代理主機將使用者的訪問重新導向到原生應用程式層代理進程,從使用者發出的http協議頭中得到使用者需要訪問的地址資訊,然後代理使用者去訪問或者按照本地的配置給予策略化的服務。一種合理的模式是vpn中的應用,為了便於管理,一般使用者需要本公司的Proxy 伺服器提供互連網服務,可是如果一個使用者在出差中使用公司配給的涉密膝上型電腦,他必然需要通過vpn串連到公司網路,然後再通過公司的Proxy 伺服器上網,在這種模式中,我用一種簡單的方式來闡述思想,那就是暫且不考慮vpn的細節,也就是暫且不考慮網路層的事情,而集中於應用程式層,畢竟,代理進程都工作在應用程式層,我使用stunnel(在linux下先apt-get或rpm或者make install,然後man或者info一下)作為使用者直接連接的Proxy 伺服器用戶端,使用另一個stuunel作為伺服器,兩個stuunel之間通過SSL協議串連,無疑這個串連是安全的。這個串連不是長串連,而是只有在stuunel接收到使用者的訪問請求時才會初始化一個ssl串連到stunnel伺服器,使用者的訪問過程通過這個ssl串連到達stunnel伺服器,進而被轉寄到真實的伺服器。這裡面有幾個細節,stunnel用戶端如何知道使用者要訪問什麼地址,stunnel用戶端又是怎樣將這個資訊傳給伺服器,然後讓伺服器區代理使用者訪問真真實位址。
如果stunnel用戶端不能將使用者要訪問的真真實位址告知stunnel伺服器或者stunnel伺服器不處理它,那麼這隻能部分實現一個反向 Proxy,也就是事先配置,所以必然需要將使用者的真實欲訪問地址傳達給伺服器。第一個細節的解答,那就是首先將所有的訪問重新導向到本機(使用iptables),然後解析使用者發起的http協議的頭,得到原始地址資訊,如果不是http協議而是普通的tcp應用或者udp應用,由於地址資訊並不一定儲存在協議頭中,因此必然需要用另一種方式得到原始地址資訊,這就是ioctl調用,linux提供了一個netfilter命令,可以得到重新導向之前的原始地址資訊,包括ip地址和連接埠,現在無論是哪種應用,http也好,普通的tcp也好,都得到了原始地址資訊,由於我們的Proxy 伺服器不在本地而在遠端,所以現在解決第二個問題,之前很長時間,我們必須自己寫協議來把這個資訊傳輸給伺服器,現在,不需要那麼麻煩了,在ssl協議的情況下,新更新的ssl協議規範在RFC5246中介紹,client發起的hello訊息中多了一個extension欄位,也就是client可以在hello的時候就把一些附件資訊傳給server,於是完全可以在這個hello訊息中將client得到的原始地址資訊傳輸給server,這樣在client和server的ssl串連初始化好了之後,server就可以使用從client-hello中得到的原始地址發起一個到真真實位址的串連,從而實現一個透明代理。