openvpn從2.0開始支援server模式,也就是支援多個client串連,之前都是p2p,僅僅是一對串連,一個用戶端對應一個伺服器,後來有了server模式後,多個用戶端可以串連一個伺服器,那麼隨後呢,隨後可能就是對等模式了,所有進入vpn的終端都以完全對等的方式相互可以通訊,或者說相互可以建立隧道,這種平等的分布式模型最符合未來的發展,也許鑒於此吧,openvpn的2.1版本增加了topology選項,有三個可選的模式,分別是net30,p2p和subnet,下面一個一個說,最終引出一個空想的結論。
net30的名稱很怪異,30的意思是什嗎?其實是一個掩碼,ipv4一共32位,30位的掩碼餘下了兩台主機的位置,拋開00和11剩下兩台的位置。舉一個執行個體,伺服器端啟動之後,為tun0配置一個p2p地址:ifconfig tun0 10.0.0.1 pointopoint 10.0.0.2,此時要問10.0.0.2何在?答案是不在,沒有這個地址,配置這個地址是為了相容以前的網路,雖然在ip網下的基於廣播的乙太網路上很難理解這個p2p配置,試想如果不在乙太網路上,p2p就可以理解了,10.0.0.2是個ip地址,它的下面不一定就是我們熟悉的乙太網路,如果真的存在一個p2p的鏈路層,對應10.0.0.2地址的主機是可以有的,並且和10.0.0.1一定是直連,即使該主機不存在,配置這個地址也不多,在伺服器啟動後會產生兩條路由,一條是10.0.0.0/24的網關是10.0.0.2,另一條是10.0.0.2的出口在tun0,有了這兩條路由之後,10.0.0.2也就完全成了一個過渡,沒有了真實的意義,用戶端呢?一樣的道理,伺服器分配給了客戶一個掩碼為30個1的ip位址區段,然後這個位址區段中一個ip地址給了主機,另一個對應的主機不存在(在廣播網路中的情況,如在p2p網路中,這個地址對應的主機就存在了,不管那麼多了),和伺服器是一樣的,在廣播網路中,這個地址僅僅是個路由過渡的作用。這種設計看起來很醜陋,沒有主機的ip地址白白浪費了卻一般起不到什麼作用,所以openvpn2.1又提供了另一個模式選項,那就是p2p。
p2p的名稱不詭異,很顯然就是點對點,什麼意思呢?如果用一種事後諸葛亮的曆史觀來思考這個問題的話,p2p的模式為subnet埋下了伏筆,起碼首先解放了用戶端,由於伺服器被所有的用戶端串連,因此不容易平滑的過渡,所以首先解放分散的用戶端,這種曆史觀也是黃仁宇的曆史觀,有點大歷史的意思,雖然老黃被很多人批駁!p2p模式為用戶端不再分配一個掩碼為30的位址區段,而是分配一個掩碼為32的主機地址,這樣就為用戶端省下了一個ip地址,後事如何,自己思考,很顯然,曆史觀是必須培養的,技術史也一樣,曆史觀有了之後,所有的事情基本都出於同一本原!為了尋求最後的解脫,subnet成了最後的稻草!
subnet的含義很容易理解,就是將vpn組建成一個完整並且完全的區域網路,伺服器的ip可以理解成網關,比如10.0.0.1,僅此一個ip地址,沒有別的p2p的地址,用戶端的地址也是一樣,沒有額外的為了相容的ip地址,也僅僅就一個地址,這樣用戶端和伺服器就成了一個名副其實的區域網路了,既然二者構成了一個區域網路,再添加新的成員也就很容易了,既然構建vpn區域網路已成趨勢,那麼伺服器和用戶端在虛擬連結層的差別也就不再重要了,伺服器和用戶端僅僅在應用程式層有意義。接下來就要考慮一旦這個多個用戶端和一個伺服器組成的vpn區域網路一但形成,它們怎麼通訊。
openvpn提供了client-to-client參數選項,該選項使能了用戶端之間的通訊,client-to-client的路由,實際上並不是什麼三層路由的概念,vpn伺服器在client-to-client網路中並不是一台路由器,而是一台交換器,畢竟區域網路通訊不需要路由器,雖然這是一個虛擬網卡在廣域網路上構建的區域網路,
最好的vpn區域網路還不是上面所說的將伺服器作為交換器的vpn區域網路,而是一個所有節點完全對等的區域網路,所有節點構成分布式網狀結構,伺服器僅僅實現vpn區域網路的准入驗證即可,通訊過程完全無需經過vpn伺服器,所有節點之間彼此都可以建立隧道,現在問題是,用戶端之間如何?ssl串連,要有ssl串連,必然需要一個伺服器,如此一來,二者又將不再對等,於是我們需要修改我們的准入網模型,一旦該節點是准入的,那麼兩個准入節點之間的通訊將不再認證而僅僅加密,餘下的必須完成的認證過程交給各個節點的上層邏輯,於是問題就轉化成了如何在通訊二者之間協商一個共用密鑰,這個就很好辦了,kerberos就可以搞定,或者其它?接下來的一個問題是如何使得任何兩個節點間可以建立隧道,如果如此,則它們必然要知道彼此的真實公網ip地址,這個其實不難辦到,讓所有的節點都加上學習功能即可,所有學習的內容由伺服器下發(push),每兩個client之間的第一次通訊必然要經過伺服器,然後伺服器告知通訊雙方對端的真實公網地址,於是接下來的通訊就不需要伺服器了,這就卸載了伺服器的很多負載,如果你在區域網路上總覺得這個方案太麻煩或者不可理喻,那麼放到廣域網路試試。理論是這樣,那麼實際上資料如何通訊呢?
一個用戶端的tun0的ip為10.0.0.3,真實公網ip為23.12.34.56,另一個用戶端的tun0的ip為10.0.0.4,真實公網ip為32.21.43.65,它們同時串連在tun0地址為10.0.0.1,真真實位址為100.100.100.1的vpn伺服器上,曾經的一張字跡很醜的手繪圖片已經解釋了用戶端和伺服器如何通訊,現在看看用戶端之間如何通訊,以ping為例,第一次0.3的機器ping0.4的機器,通過路由進行隧道封裝,資料到達了0.1,然後直達openvpn,此時進入openvpn的資料是一個源ip為0.3,目的ip為0.4的未經處理資料“流”,然後openvpn將之寫入tun0,經過路由後,資料被寫入tun0,從而又進入應用程式層的openvpn,此時,openvpn剖析出目的地址是10.0.0.4,屬於vpn網段但是不是自己,那麼它查看自己是否設定了client-to-client,如果設定了,那麼它會查詢自己的串連表,發現32.21.43.65作為用戶端串連了自己,它的vpn地址為10.0.0.4,於是伺服器查看32.21.43.65的路由,並且將源ip為0.3,目的為0.4的資料包連同ip頭加封一個源為伺服器真實ip,目的為0.4真實ip的ip頭髮給了vpn地址為0.4的用戶端,接下來伺服器將0.3和0.4用戶端的真真實位址分別發給了0.4和0.3,以期望它們能自己建立隧道,...,資料到達0.4之後,經過openvpn的轉寄,資料最終進入tun0接收,最終tun0發現就是它要的資料,於是傳輸終止,資料順利到達。第二次通訊時,0.3和0.4就可以利用從0.1伺服器學習而來的ip地址資訊自行建立隧道進行通訊,當然建立隧道時要付出一些“代價”,那就是協商密鑰,kerberos和ssl,自己看著辦吧。
事到如此,一切很合理,從最初的p2p的vpn,到subnet的vpn,最終分布式的革命熱情不可收拾,一切真的很合理。最後不得不利用ip over ssl的合理與成功來抨擊一下IPSec,tun/tap驅動可以實現userspace的IPSec,要想和kernel中的IPSec一致,需要在使用者空間得到發往虛擬網卡的IP包以後經IPSec相關的協議封裝後用raw-IP發送出去,實現和核心的IPSec同樣語義的基礎上帶來的好處就是解決了穿越nat的問題,實際上可以保持和核心vpn的一致,但是更靈活。net30完全是一個p2p模型,p2p是個過渡,subnet實現了一個適用於廣播型網路比如乙太網路的vpn模型,從此,如果vpn風靡了,那麼估計就會有很多人不再必須知道什麼是乙太網路交換器裝置了,他們只需要能在vpn的subnet上馳騁就可以了,正如如今的很多進階開發工程師並不很精通體繫結構和彙編,甚至沒怎麼寫過c代碼,也不甚懂OS和DBS,但是他們依然很優秀,世界多彩了,靈活了,分工也就更加精細了。