GNB是一個開源的去中心化的具有極致內網穿透能力的通過P2P進行三層網絡交換的VPN。
本文以 Linux 為環境作為測試環境,macOS和Windows10環境類似,Windows10環境需要安裝虛擬網卡驅動。
快速部署
執行 gnb_initkey_linux_x86_64.sh
會根據conf_tpl
中的模板在 conf/ 目錄下生成三個預先設置好的節點 1001 1002 1003
,節點1001在配置文件里被設為index節點與forward節點(index與forward節點的相關概念在下文中有詳細描述)
通過修改conf/1002
和 conf/1003 address.conf
,設置好1001
節點 在實際運行環境中的ip地址,就可以通過執行sh目錄下的腳本啟動節點。
例如,在Linux下啟動節點1001就執行
./gnb_linux_x86_64.sh start 1001
如果要關閉節點1001,就執行
./gnb_linux_x86_64.sh stop 1001
詳細配置說明
如果打算自行配置節點,則需要仔細閱讀下面的說明。
每個接入GNB網絡的設備都是一個GNB節點,每個節點擁有唯一的UUID,被稱為nodeid,這是一個32bit無符號整型數字,可以由人工分配,必須保證每個節點的nodeid在整個GNB網絡中是唯一的。
GNB節點的配置文件集中存放在一個目錄下,一般情況下,每個節點的配置目錄作為一個子目錄放在 conf 目錄下,可以用節點的nodeid來命名。
例如有 1001、1002、1003 三個節點,那么 conf/ 應該存在以下三個目錄
conf/1001
conf/1002 conf/1003
目錄下有幾個配置文件 node.conf route.conf address.conf
node.conf
:
以下是 node.conf 一個例子:
nodeid 1001
lisen 9001
node.conf
用於存放節點的配置信息,格式如下
nodeid $nodeid
lisen $lisen_port
route.conf
: GNB網絡里所有的節點共享的一張路由表,配置文件是route.conf
以下是 route.conf
一個例子:
1001|10.1.0.1|255.255.255.0
1002|10.1.0.2|255.255.255.0 1003|10.1.0.3|255.255.255.0
配置文件中的每一行是一個節點的描述,格式如下
$nodeid|$tun_ipv4|$tun_netmask
每個配置項的含義是這樣 nod
tun_ipv4 虛擬網卡的IPV4地址 $tun_netmask 虛擬網卡的IPV4地址的子網掩碼
如果gnb運行兩個網絡的網關上,通過配置 route.conf
可以讓兩個ipv4子網內的設備進行互訪,即使這些設備上沒有運行gnb。 要注意的是,目前仍然需要自行在出口網關上設定路由 例如有一個虛擬ip為 10.1.0.2 的GNB節點,節點所在的內網是 192.168.0.0/24,想要在本地主機(沒有運行GNB服務)上訪問直接訪問 192.168.0.0/24 里的主機,那么位於出口網關的GNB配置route.conf
應該包含這兩項配置
1002|10.1.0.2|255.255.255.0
1002|192.168.0.0|255.255.255.0
在出口網關上加一條路由
ip route add 192.168.0.0/24 via 10.1.0.2
為了讓對端 192.168.0.0/24 子網中的機器能夠訪問到本地主機,在對端虛擬ip 為 10.1.0.2 的GNB節點上也需要為到達本地設一條路由。
這些路由指令可以在 script/if_up_linux.sh
中預設好,GNB啟動時會調用這些腳本。
address.conf
用於配置節點的屬性和公網ip地址及端口
以下是 address.conf
一個例子:
i|0|a.a.a.a|9001
if|1001|b.b.b.b|9001 n|1002|c.c.c.c|9001
其中,a.a.a.a b.b.b.b c.c.c.c 代表公網ip地址,需要根據實際情況填寫
配置文件中的每一行是一個地址 的描述,格式如下
$attrib|$nodeid|$ipv4/$ipv6|$port
attrib節點的屬性,用一組字符來表示,i表示這個節點是ind
nodeid 節點的ID,與 route.conf 中的nodipv6 GNB節點的IPV6地址 ipv4GN
port GNB節點的服務端口
如果一個節點同時擁有ipv4和ipv6地址,這就需要分兩行配置項,GNB會通過 ping-pong 協議方式去測量該節點哪個ip地址有更低的延時,在發送ip分組數據的時候自動發往低延時的地址。
index節點的作用類似於DNS,如果一組相互之間不知道對方ip地址和端口的GNB節點都向同一個index節點提交自身的ip地址和端口,那這些GNB節點就可以通過對端節點的公鑰向index查詢對端節點的ip地址和端口。 GNB index 協議允許在提交和查詢節點ip地址端口過程中不驗證報文的數字簽名,即index節點允許對提交和查詢ip的報文不驗證數字簽名,普通節點對index節點響應查詢ip的報文不驗證數字簽名。 index節點可以不綁定nodeid,不需要在 route.conf 配置文件中描述,對於不綁定nodeid的index節點被定義為 public gnb index node 並在 address.conf 中把 $nodeid 這一列設置成0。
forward節點可以為無法直接互訪的GNB節點中轉ip分組,這些節點通常部署在內網中且沒有固定公網ip,並且用盡了所有的辦法都無法實現nat穿透實現點對點通訊,forward節點並不能解密兩個節點之間的通信的內容。 出於安全考慮,forward節點必須綁定 nodeid 作為配置項出現在 route.conf
中,與 gnb forward 協議相關的報文都要發送驗證節點的數字簽名,即要求forward節點和通過forward節點轉發報文的普通節點都必須相互交換了公鑰。
在 address.conf
中 index節點和forward節點可以有多項,包括可以有多項 $nodeid設為0的 public gnb index node。 一旦配置了多個index節點或forward節點, 就可以使用GNB的index和forward服務的負載均衡和容錯模式。
GNB節點通過非對稱加密來交換通訊的密鑰,這是GNB節點通信的基礎,因此需要為每個GNB節點創建一組公私鑰,兩個節點需要交換公鑰才能進行通訊。
公私鑰的命名分別是以節點的UUID為文件名 .private 和 .public 為文件的后綴名,以UUID為1001的節點公私鑰文件應為 1001.public
1001.private
GNB 提供了一個名為 gnb_crypto 命令行工具,用於生成公私鑰,
./gnb_crypto -c -p 1001.private -k 1001.public
本節點的公私鑰存放在 conf/$uuid32/security/
目錄下,其他節點的公鑰存放 conf/$uuid32/ed25519/
以UUID為1001的節點為例
conf/1001/security/
目錄下應該有 1001.private
1001.public
conf/1001/ed25519/
目錄下有 1002.public
1003.public
script/目錄下存放了一組腳本 if_up_linux.sh
是在虛擬網卡啟動之后調用的腳本,用於用戶自定義設置路由,防火牆的指令 if_down_linux.sh
是在虛擬網卡將要關閉時調用的腳本
如果打算自行實現GNB的啟動腳本,以下是一個例子
以啟動UUID為1001的節點為例:
在 sh
目錄下創建一個腳本 1001.sh,內容為
killall -9 gnb
nohup ../bin/gnb -i LinuxTun1001 -c ../conf/1001 >/dev/null 2>&1 &
在Linux下節點啟動后,可以用 ip addr 查看虛擬網卡是否啟動成功,並嘗試用 ping 測試 各節點的虛擬 ip 是否能夠ping通。
gnb的命令行參數
執行gnb -h
可以看到gnb在當前平台所支持的參數,由於 gnb ver 1.2 還有一些細節在調整,這里只對一些已經明確固定下來的參數進行解釋
gnb ver 1.2 的開發還在進行中
參數 | 說明 | 明細 |
---|---|---|
-c, --conf | config path | 指定gnb node的目錄,這個在啟動gnb時參數是必須的,不可少的 |
-d, --daemon | daemon | 作為daemon進程啟動,Windows不支持這個選項 |
-i, --ifname | TUN Device NAME | 指定虛擬網卡的的名字,這在macOS和windows上是無效的,這些系統對虛擬網卡的命名有自己的規則 |
-4, --ipv4-only | Use IPv4 Only | 禁用ipv6,gnb將不通過ipv6地址收發數據,gnb開啟的虛擬網卡不會綁定ipv6地址,由於禁用了ipv6,因此gnb可以設置小於1280的mtu,對於一些限制比較多的網絡環境可以利用這個特性嘗試使用更小的mtu |
-6, --ipv6-only | Use IPv6 Only | 禁用ipv4,gnb將不通過ipv4地址收發數據,gnb開啟的虛擬網卡不會綁定ipv4地址 |
--log-file-path | log file path | 指定輸出文件日志的路徑,如果不指定將不會產生日志文件,當前gnb的日志系統可定制化程度不高 |
--mtu | TUN Device MTU ipv4 532, ipv6 1280 | 虛擬網卡的mtu,在比較糟糕的網絡環境下ipv4可以設為532,ipv6不可小於1280 |
--crypto | ip frame crypto 'xor' or 'rc4' or 'none' default is 'xor' | 設定gnb傳輸數據的加密算法,選擇'none'就是不加密,默認是xor使得在CPU運算能力很弱的硬件上也可以有較高的數據吞吐能力。未來會支持aes算法。兩個gnb節點必須保持相同的加密算法才可以正常通訊。 |
--crypto-key-update-interval | 'hour' or 'minute' or none default is 'none' | gnb的節點之間可以通過時鍾同步變更密鑰,這依賴與節點的時鍾必須保持較精確的同步,由於考慮到實際環境中一些節點時鍾可能2無法及時同步時間,因此這個選項默認是不啟用,如果運行gnb的節點能夠保證同步時鍾,可以考慮選擇一個同步更新密鑰的間隔,這可以提升一點通訊的安全性。關於加密的部分,將來會有專門的文章介紹 |
--multi-index-type | 'simple-fault-tolerant' or 'simple-load-balance' default is 'simple-fault-tolerant' | 如果設置了多個index節點,那么可以選擇一個選取index節點的方式,負載均衡或在容錯模式,這個選項目前還不完善,容錯模式只能在交換了通訊密鑰的節點之間進行 |
--multi-forward-type | 'simple-fault-tolerant' or 'simple-load-balance' default is 'simple-fault-tolerant' | 如果有多個forward節點,可以選擇一個forward節點的方式,負載均衡或在容錯模式 |
--set-socket-if-name | example: 'eth0', 'eno1', only for unix-like os | 在unix-like系統上可以讓gnb的數據通過指定物理網卡發送,這里需要用戶輸入物理網卡的名字,Windows不支持這個特性,也看不到該選項 |
--set-if-dump | 'dump the interface data frame 'on' or 'off' default is 'off' | 把經過gnb開啟的虛擬網卡的ip分組在日志中輸出,這樣方便調試系統 |
--disabled-tun | disabled TUN Device, index node only | 不啟動虛擬網卡,僅作為gnb index服務啟動,由於沒有啟動虛擬網卡,因此設了這個選項時不需要用root權限去啟動gnb |
--disabled-keyless-fwd | disabled keyless forward | 禁用未經交換公鑰轉發分組的特性 |
--pid-file | pid file | 指定保存gnb進程id的文件,方便通過腳本去kill進程,如果不指定這個文件,pid文件將保存在當前節點的配置目錄下 |
--node-cache-file | node address cache file | gnb會定期把成功連通的節點的ip地址和端口記錄在一個緩存文件中,gnb進程在退出后,這些地址信息不會消失,重新啟動進程時會讀入這些數據,這樣新啟動gnb進程就可能不需通過index 節點查詢曾經成功連接過的節點的地址信息 |