一個(gè)傳統(tǒng)的 VPN(如 OpenVPN、PPTP)由一個(gè) VPN 服務(wù)器和一個(gè)或多個(gè)連接到這臺(tái)服務(wù)器的客戶端組成。當(dāng)任意兩個(gè) VPN 客戶端彼此通信時(shí),VPN 服務(wù)器需要中繼它們之間的 VPN 數(shù)據(jù)流量。這樣一個(gè)中心輻射型的 VPN 拓?fù)浣Y(jié)構(gòu)存在的問題是,當(dāng)連接的客戶端增多以后,VPN 服務(wù)器很容易成為一個(gè)性能上的瓶頸。從某種意義上來說,中心化的 VPN 服務(wù)器也同樣成為一個(gè)單點(diǎn)故障的來源,也就是當(dāng) VPN 服務(wù)器出現(xiàn)故障的時(shí)候,整個(gè) VPN 都將無法被任何 VPN 客戶端訪問。
點(diǎn)對(duì)點(diǎn) VPN(又稱 P2P VPN)是另一個(gè) VPN 模型,它能解決傳統(tǒng)的基于服務(wù)器-客戶端模型的 VPN 存在的這些問題。一個(gè) P2P VPN 中不再有一個(gè)中心的 VPN 服務(wù)器,任何擁有一個(gè)公開 IP 地址的節(jié)點(diǎn)都能引導(dǎo)其他節(jié)點(diǎn)進(jìn)入 VPN。當(dāng)連接到一個(gè) VPN 之后,每一個(gè)節(jié)點(diǎn)都能與 VPN 中的任何其他節(jié)點(diǎn)直接通信,而不需要經(jīng)過一個(gè)中間的服務(wù)器節(jié)點(diǎn)。當(dāng)然任何節(jié)點(diǎn)出現(xiàn)故障時(shí),VPN 中的剩余節(jié)點(diǎn)不會(huì)受到影響。節(jié)點(diǎn)中的延遲、帶寬以及 VPN 擴(kuò)展性在這樣的設(shè)定中都有自然的提升,當(dāng)你想要使用 VPN 進(jìn)行多人游戲或者與許多朋友分享文件時(shí),這都是十分理想的。
開源的 P2P VPN 實(shí)現(xiàn)已經(jīng)有幾個(gè)了,比如 Tinc、peerVPN,以及 n2n。在本教程中,我將會(huì)展示如何在 Linux 上用 n2n 配置點(diǎn)對(duì)點(diǎn) VPN。
n2n 是一個(gè)開源(GPLv3)軟件,它允許你在用戶間構(gòu)建一個(gè)加密的 2/3 層點(diǎn)對(duì)點(diǎn) VPN。由 n2n 構(gòu)建的 VPN 是“對(duì) NAT 友好”的,也就是說,不同 NAT 路由器后方的兩個(gè)用戶可以通過 VPN 直接與對(duì)方通信。n2n 支持對(duì)稱的 NAT 類型,這是 NAT 中限制最多的一種。因此,n2n 的 VPN 數(shù)據(jù)流量是用 UDP 封裝的。
一個(gè) n2n VPN 由兩類節(jié)點(diǎn)組成:邊緣(edge)節(jié)點(diǎn)和超級(jí)(super)節(jié)點(diǎn)。一個(gè)邊緣節(jié)點(diǎn)是一臺(tái)連接到 VPN 的電腦,它可能在一個(gè) NAT 路由器后方。一個(gè)超級(jí)節(jié)點(diǎn)則是擁有一個(gè)可以公共訪問的 IP 地址的電腦,它將會(huì)幫助 NAT 后方的邊緣節(jié)點(diǎn)進(jìn)行初始通信。想要在用戶中創(chuàng)建一個(gè) P2P VPN 的話,我們需要至少一個(gè)超級(jí)節(jié)點(diǎn)。
在這篇教程中,我將會(huì)創(chuàng)建一個(gè)擁有 3 個(gè)節(jié)點(diǎn)的 P2P VPN:一個(gè)超級(jí)節(jié)點(diǎn)和兩個(gè)邊緣節(jié)點(diǎn)。唯一的要求是,邊緣節(jié)點(diǎn)需要能夠 ping 通超級(jí)節(jié)點(diǎn)的 IP 地址,而它們是否在 NAT 路由器之后則沒有什么關(guān)系。
若想用 n2n 構(gòu)建一個(gè) P2P VPN,你需要在每個(gè)節(jié)點(diǎn)上安裝 n2n,包括超級(jí)節(jié)點(diǎn)。
由于它非常精簡(jiǎn)的依賴需求,在大多數(shù) Linux 平臺(tái)上 n2n 都能被輕松編譯。
如前文所述,我們需要至少一個(gè)超級(jí)節(jié)點(diǎn),它將會(huì)作為一個(gè)初始化引導(dǎo)服務(wù)器。我們假設(shè)這個(gè)超級(jí)節(jié)點(diǎn)的 IP 地址是 1.1.1.1。
超級(jí)節(jié)點(diǎn):
在一個(gè)作為超級(jí)節(jié)點(diǎn)的電腦上運(yùn)行下面的命令。其中“-l ”指定超級(jí)節(jié)點(diǎn)的監(jiān)聽端口。運(yùn)行 supernode 并不需要 root 權(quán)限。
邊緣節(jié)點(diǎn):
在每個(gè)邊緣節(jié)點(diǎn)上,使用下面的命令來連接到一個(gè) P2P VPN。edge 守護(hù)程序?qū)?huì)在后臺(tái)運(yùn)行。
邊緣節(jié)點(diǎn) #1:
邊緣節(jié)點(diǎn) #2:
下面是對(duì)命令行的一些解釋:
“-d ”選項(xiàng)指定了由 edge 命令創(chuàng)建的 TAP 接口的名字。
“-a ”選項(xiàng)(靜態(tài)地)指定了分配給 TAP 接口的 VPN 的 IP 地址。如果你想要使用 DHCP,你需要在其中一臺(tái)邊緣節(jié)點(diǎn)上配置一臺(tái) DHCP 服務(wù)器,然后使用“-a dhcp:0.0.0.0”選項(xiàng)來代替。
“-c ”選項(xiàng)指定了 VPN 組的名字(最大長(zhǎng)度為 16 個(gè)字節(jié))。這個(gè)選項(xiàng)可以被用來在同樣一組節(jié)點(diǎn)中創(chuàng)建多個(gè) VPN。
“-u”和“-g”選項(xiàng)被用來在創(chuàng)建一個(gè) TAP 接口后降權(quán)放棄 root 權(quán)限。edge 守護(hù)進(jìn)程將會(huì)作為指定的用戶/組 ID 運(yùn)行。
“-k ”選項(xiàng)指定了一個(gè)由 twofish 加密的密鑰來使用。如果你想要將密鑰從命令行中隱藏,你可以使用 N2N_KEY 環(huán)境變量。
“-l ”選項(xiàng)指定了超級(jí)節(jié)點(diǎn)的監(jiān)聽 IP 地址和端口號(hào)。為了冗余,你可以指定最多兩個(gè)不同的超級(jí)節(jié)點(diǎn)(比如 -l -l )。
“-m ”給 TAP 接口分配了一個(gè)靜態(tài)的 MAC 地址。不使用這個(gè)參數(shù)的話,edge 命令將會(huì)隨機(jī)生成一個(gè) MAC 地址。事實(shí)上,為一個(gè) VPN 接口強(qiáng)制指定一個(gè)靜態(tài)的 MAC 地址是被強(qiáng)烈推薦的做法。否則,比如當(dāng)你在一個(gè)節(jié)點(diǎn)上重啟了 edge 守護(hù)程序的時(shí)候,其它節(jié)點(diǎn)的 ARP 緩存將會(huì)由于新生成的 MAC 地址而遭到污染,它們將不能向這個(gè)節(jié)點(diǎn)發(fā)送數(shù)據(jù),直到被污染的 ARP 記錄被消除。
至此,你應(yīng)該能夠從一個(gè)邊緣節(jié)點(diǎn)用 VPN IP 地址 ping 通另一個(gè)邊緣節(jié)點(diǎn)了。
故障排除
在調(diào)用 edge 守護(hù)程序的時(shí)候得到了如下錯(cuò)誤。
n2n[4405]: ERROR: ioctl() [Operation not permitted][-1]
注意 edge 守護(hù)進(jìn)程需要超級(jí)用戶權(quán)限來創(chuàng)建一個(gè) TAP 接口。因此需要確定用 root 權(quán)限來執(zhí)行,或者對(duì) edge 命令設(shè)置 SUID。之后你總是可以使用“-u”和“-g”選項(xiàng)來降權(quán)放棄 root 權(quán)限。
總結(jié)
n2n 可以成為對(duì)你來說非常實(shí)用的免費(fèi) VPN 解決方案。你可以輕松地配置一個(gè)超級(jí)節(jié)點(diǎn),無論是用你自己家里的網(wǎng)絡(luò),還是從云主機(jī)提供商購(gòu)買一個(gè)可以公共訪問的 VPS 實(shí)例。你不再需要把敏感的憑據(jù)和密鑰放在第三方 VPN 提供商的手里,使用 n2n,你可以在你的朋友中配置你自己的低延遲、高帶寬、可擴(kuò)展的 P2P VPN。