mirror of
https://github.com/KusakabeShi/EtherGuard-VPN.git
synced 2025-02-16 15:29:15 +01:00
Update README_zh.md
This commit is contained in:
parent
d8f7cb1b60
commit
c27695063d
1
Makefile
1
Makefile
@ -20,7 +20,6 @@ etherguard-go: $(wildcard *.go) $(wildcard */*.go)
|
||||
go mod download && \
|
||||
go mod tidy && \
|
||||
go mod vendor && \
|
||||
patch -p0 -i govpp_remove_crcstring_check.patch && \
|
||||
go build -v -tags novpp -o "$@"
|
||||
|
||||
vpp:
|
||||
|
37
README.md
37
README.md
@ -1,16 +1,37 @@
|
||||
### Requirement
|
||||
# Etherguard
|
||||
[中文](README_zh.md)
|
||||
|
||||
Install VPP and Go
|
||||
WIP
|
||||
|
||||
## Build
|
||||
|
||||
### No-vpp version
|
||||
|
||||
#### Dependency
|
||||
Go 1.16
|
||||
```bash
|
||||
echo "deb [trusted=yes] https://packagecloud.io/fdio/release/ubuntu focal main" > /etc/apt/sources.list.d/99fd.io.list
|
||||
curl -L https://packagecloud.io/fdio/release/gpgkey | sudo apt-key add -
|
||||
add-apt-repository ppa:longsleep/golang-backports
|
||||
apt-get -y update
|
||||
apt-get install vpp vpp-plugin-core python3-vpp-api vpp-dbg vpp-dev libmemif libmemif-dev wireguard-tools golang-go build-essential golang-go
|
||||
apt-install -y wireguard-tools golang-go build-essential
|
||||
```
|
||||
#### Build
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
### Build
|
||||
### VPP version
|
||||
|
||||
#### Dependency
|
||||
|
||||
VPP and libemif is requires
|
||||
|
||||
```
|
||||
echo "deb [trusted=yes] https://packagecloud.io/fdio/release/ubuntu focal main" > /etc/apt/sources.list.d/99fd.io.list
|
||||
curl -L https://packagecloud.io/fdio/release/gpgkey | sudo apt-key add -
|
||||
apt-get -y update
|
||||
apt-get install -y vpp vpp-plugin-core python3-vpp-api vpp-dbg vpp-dev libmemif libmemif-dev
|
||||
```
|
||||
#### Build
|
||||
```bash
|
||||
export CGO_CFLAGS="-I/usr/include/memif"
|
||||
make
|
||||
make vpp
|
||||
```
|
143
README_zh.md
Normal file
143
README_zh.md
Normal file
@ -0,0 +1,143 @@
|
||||
|
||||
# Etherguard
|
||||
一個從wireguard-go改來的Full Mesh Layer2 VPN.
|
||||
|
||||
OSPF能夠根據cost自動選路
|
||||
但是實際上,我們偶爾會遇到去程/回程不對等的問題
|
||||
之前我就在想,能不能根據單向延遲選路呢?
|
||||
例如我有2條線路,一條去程快,一條回程快。就自動過去回來各自走快的?
|
||||
|
||||
所以我就想弄一個這種的VPN了,任兩節點會測量單向延遲,並且使用[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法)演算法找出任兩節點間的最佳路徑
|
||||
來回都會是最佳的。有2條線路,一條去程快,一條回程快,就會自動各走各的
|
||||
|
||||
擔心時鐘不同步,單向延遲測量不正確?
|
||||
沒問題的,證明可以看這邊: [https://www.kskb.eu.org/2021/08/rootless-routerpart-3-etherguard.html](https://www.kskb.eu.org/2021/08/rootless-routerpart-3-etherguard.html)
|
||||
|
||||
## Usage
|
||||
```
|
||||
Usage of ./etherguard-go-vpp:
|
||||
-config string
|
||||
設定檔路徑
|
||||
-example
|
||||
印一個範例設定檔
|
||||
-help
|
||||
Show this help
|
||||
-mode string
|
||||
運作模式,有兩種模式 super/edge
|
||||
solve是用來解 Floyd Warshall的,Static模式會用到
|
||||
-no-uapi
|
||||
不使用UAPI。使用UAPI,你可以用wg命令看到一些連線資訊(畢竟是從wireguard-go改的)
|
||||
-version
|
||||
顯示版本
|
||||
```
|
||||
|
||||
## Mode
|
||||
|
||||
1. Static 模式: 類似於原本的wireguard。
|
||||
* 沒有自動選路,沒有握手伺服器
|
||||
一切都要提前配置好
|
||||
* 參見: [example_config/static_mode/README_zh.md](example_config/static_mode/README_zh.md)
|
||||
2. Super 模式: 受到[n2n](https://github.com/ntop/n2n)的啟發,分為super node和edge node兩種節點
|
||||
* 全部節點會和supernode建立連線
|
||||
藉由supernode交換其他節點的資訊,以及udp打洞
|
||||
由supernode執行[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法),並把計算結果分發給全部edge node
|
||||
* 參見: [example_config/super_mode/README_zh.md](example_config/super_mode/README_zh.md)
|
||||
3. P2P 模式: 受到[tinc](https://github.com/gsliepen/tinc)的啟發
|
||||
* 每個節點都類似super node
|
||||
會定期廣播自己所有已連線節點的連線ip:port,公鑰和preshared key
|
||||
每個節點都自己執行[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法)
|
||||
並且廣播收到的單向延遲資訊讓其他節點也能計算
|
||||
* 參見: [example_config/p2p_mode/README_zh.md](example_config/p2p_mode/README_zh.md)
|
||||
## Common Config Paramater
|
||||
有些設定檔對應某些運作模式,這邊針對共同部分的設定做說明
|
||||
### Edge config
|
||||
邊緣節點是實際執行VPN的節點
|
||||
|
||||
1. `interface`
|
||||
1. `itype`: 裝置類型,意味著收到的封包要丟去哪
|
||||
1. `dummy`: 收到的封包直接丟棄,也不發出任何封包。作為中繼節點可以用
|
||||
2. `stdio`: 收到的封包丟stdout,stdin進來的資料丟入vpn網路
|
||||
需要參數: `macaddrprefix`,`l2headermode`
|
||||
2. `udpsock`: 收到的封包用udp丟到某個網路位置,監聽port進來的資料丟去vpn網路
|
||||
需要參數: `macaddrprefix`,`recvaddr`,`sendaddr`
|
||||
2. `vpp`: 使用libmemif使vpp加入VPN網路
|
||||
需要參數: `name`,`vppifaceid`,`vppbridgeid`,`macaddrprefix`,`mtu`
|
||||
2. `tap`: Linux的tap設備。讓linux加入VPN網路
|
||||
需要參數: `name`,`macaddrprefix`,`mtu`
|
||||
2. `name` : 裝置名稱
|
||||
3. `vppifaceid`: VPP 的 interface ID。一個VPP runtime內不能重複
|
||||
4. `vppbridgeid`: VPP 的網橋ID。不使用VPP網橋功能的話填0
|
||||
5. `macaddrprefix`: MAC地址前綴。真正的MAC地址=[前綴]:[vppifaceid]。如果填了6格長度就忽略`vppifaceid`
|
||||
2. `nodeid`: 節點ID。節點之間辨識身分用的,同一網路內節點ID不能重複
|
||||
3. `nodename`: 節點名稱
|
||||
4. `privkey`: 私鑰,和wireguard規格一樣
|
||||
5. `listenport`: 監聽的udp埠
|
||||
6. `loglevel`: 紀錄log
|
||||
1. `loglevel`: wireguard原本的log紀錄器的loglevel。
|
||||
有`debug`,`error`,`slient`三種程度
|
||||
2. `logtransit`: 轉送封包,也就是起點/終點都不是自己的封包的log
|
||||
3. `logcontrol`: Control Message的log
|
||||
4. `lognormal`: 收發普通封包,起點是自己or終點是自己的log
|
||||
5. `logntp`: NTP 同步時鐘相關的log
|
||||
7. `dynamicroute`: 動態路由相關的設定。時間類設定單位都是秒
|
||||
1. `sendpinginterval`: 發送Ping訊息的間隔
|
||||
2. `dupchecktimeout`: 重複封包檢查的timeout。完全相同的封包收第二次會被丟棄
|
||||
3. `conntimeout`: 鄰居應該要發Ping過來,超過就視為鄰居掛了
|
||||
4. `savenewpeers`: 是否把下載來的鄰居資訊存到本地設定檔裡面
|
||||
5. `supernode`: Super模式相關的設定,參見[example_config/super_mode/README_zh.md](example_config/super_mode/README_zh.md)
|
||||
6. `p2p` P2P模式相關的設定,參見 [example_config/p2p_mode/README_zh.md](example_config/p2p_mode/README_zh.md)
|
||||
7. `ntpconfig`: NTP 相關的設定
|
||||
1. `usentp`: 是否使用ntp同步時鐘
|
||||
2. `maxserveruse`: 一次對多連線幾個NTP伺服器
|
||||
第一次會全部連一遍測延遲,之後每次都取延遲前n低的來用
|
||||
3. `synctimeinterval`: 多久同步一次
|
||||
4. `ntptimeout`: 多久算是超時
|
||||
5. `servers`: NTP伺服器列表
|
||||
8. `nexthoptable`: 轉發表。只有Static模式會用到,參見 [example_config/super_mode/README_zh.md](example_config/super_mode/README_zh.md)
|
||||
9. `resetconninterval`: 如果對方是動態ip就要用這個。每隔一段時間就會重新解析domain。
|
||||
10. `peers`: 和wireguard一樣的peer資訊
|
||||
1. `nodeid`: 對方的節點ID
|
||||
2. `pubkey`: 對方的公鑰
|
||||
3. `pskey`: 對方的預共享金鑰。但是目前沒用(因為不能設定自己的),之後會加
|
||||
4. `endpoint`: 對方的連線地址。如果roaming會覆寫設定檔
|
||||
5. `static`: 設定成true的話,每隔`resetconninterval`秒就會重新解析一次domain,與此同時也不會被roaming覆寫
|
||||
|
||||
### Super config
|
||||
參見 [example_config/super_mode/README_zh.md](example_config/super_mode/README_zh.md)
|
||||
|
||||
|
||||
## Build
|
||||
|
||||
### No-vpp version
|
||||
編譯沒有VPP libmemif的版本。可以在一般linux電腦上使用
|
||||
|
||||
#### Dependency
|
||||
安裝 Go 1.16
|
||||
```bash
|
||||
add-apt-repository ppa:longsleep/golang-backports
|
||||
apt-get -y update
|
||||
apt-install -y wireguard-tools golang-go build-essential
|
||||
```
|
||||
#### Build
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
### VPP version
|
||||
編譯有VPP libmemif的版本。
|
||||
|
||||
用這個版本的話你的電腦要有libmemif.so才能run起來
|
||||
|
||||
#### Dependency
|
||||
|
||||
安裝 VPP 和 libemif
|
||||
```
|
||||
echo "deb [trusted=yes] https://packagecloud.io/fdio/release/ubuntu focal main" > /etc/apt/sources.list.d/99fd.io.list
|
||||
curl -L https://packagecloud.io/fdio/release/gpgkey | sudo apt-key add -
|
||||
apt-get -y update
|
||||
apt-get install -y vpp vpp-plugin-core python3-vpp-api vpp-dbg vpp-dev libmemif libmemif-dev
|
||||
```
|
||||
#### Build
|
||||
```bash
|
||||
make vpp
|
||||
```
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
0
example_config/p2p_mode/README.md
Normal file
0
example_config/p2p_mode/README.md
Normal file
69
example_config/p2p_mode/README_zh.md
Normal file
69
example_config/p2p_mode/README_zh.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Etherguard
|
||||
P2P Mode的[範例配置檔](./)的說明文件
|
||||
在了解Super Mode的運作之前,建議您先閱讀[Super Mode的運作](../super_mode/README_zh.md)方法,再閱讀本篇會比較好
|
||||
|
||||
## P2P Mode
|
||||
受到[tinc](https://github.com/gsliepen/tinc)的啟發
|
||||
|
||||
和[Super模式運作](../super_mode/README_zh.md)有點相似,不過也有點修改
|
||||
|
||||
### ControlMsg
|
||||
|
||||
P2P模式又引入一種新的 `終點ID` 叫做 `ControlMsg`
|
||||
和 Static 模式下的Boardcast非常相似。只不過 `Boardcast` 會盡量避免重複發送
|
||||
`ControlMsg` 才不管,只要收到一律轉發給剩餘的全部節點
|
||||
你可以當成廣播有2種,一種是**普通廣播**,會查看轉發表,不會重複發送
|
||||
另一種是**flood廣播**,不查看轉發表,盡量發給全部的節點
|
||||
|
||||
所以P2P模式的 `ControlMsg` 會額外引入一個**Dup檢查**。
|
||||
所有進來的 `ControlMsg` 都會算一遍CRC32,並儲存在一個有timeout的dictionary裡面
|
||||
只要有一模一樣CRC32就會被丟棄。計算時只考慮封包內容,不考慮src/dst/TTL之類的標頭
|
||||
所以一樣的內容收2遍,第二個一定會被丟棄
|
||||
|
||||
### Ping
|
||||
首先和Super模式一樣,會定期向所有節點廣播`Ping`,TTL=0 所以不會被轉發
|
||||
只會抵達可以直連的節點
|
||||
但是收到Ping以後產生的`Pong`不會回給Super,而是傳給其他所有的節點
|
||||
|
||||
### Pong
|
||||
Pong封包是一種`ControlMsg`,使用**flood廣播**盡量讓每個節點都收到
|
||||
因為是P2P模式,每人都維護自己的 Distance Matrix
|
||||
收到Pong封包的時候,就更新自己的 Distance Matrix
|
||||
更新完以後,就跑[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法)更新自己的轉發表
|
||||
|
||||
### QueryPeer
|
||||
是一種`ControlMsg`,使用**flood廣播**盡量讓每個節點都收到
|
||||
剛加入網路的節點會廣播這個封包,要求其他節點提供他們的peer訊息
|
||||
如果收到了`QureyPeer` 封包,就會開始發送 `BoardcastPeer` 封包
|
||||
每個BoardcastPeer只能攜帶一個peer的訊息,所以自己有幾個peer就會發送幾遍
|
||||
|
||||
### BoardcastPeer
|
||||
是一種`ControlMsg`,使用**flood廣播**來發送,盡量讓每個節點都收到
|
||||
裡面包含了 NodeID,PubKey,PSKey,Endpoint,queryID,這五種資料
|
||||
每個節點都**定期**把自己全部的peer廣播一遍,其中queryID填入0
|
||||
但是共同擁有的節點,因為內容都長一樣(NodeID/PubKey等等),會觸發`ControlMsg`的**Dup檢查**
|
||||
所以流量不會爆炸
|
||||
|
||||
還有一種情況
|
||||
節點只要收到`QueryPeer`,也會把自己全部的peer廣播發送一遍,而且queryID填入請求者的NodeID
|
||||
因為NodeID不是0了,就不會和前面的定期廣播長一樣,就不會觸發Dup檢查
|
||||
保證新加入的節點能立刻拿到其他所有節點的資訊
|
||||
|
||||
收到`BoardcastPeer`時,會先檢查自己有沒有這個Peer,若沒有就新增Peer
|
||||
如果已經有了,再檢查Peer是不是離線。
|
||||
如果已經離線,就用收到的Endpoint覆蓋掉自己原本的Endpoint
|
||||
|
||||
## Config Paramaters
|
||||
|
||||
P2P模式也有幾個參數
|
||||
1. usep2p: 是否啟用P2P模式
|
||||
1. sendpeerinterval: 廣播BoardcastPeer的間格
|
||||
1. peeralivetimeout: 每次收到封包就重置,超過時間沒收到就視為該peer離線
|
||||
1. graphrecalculatesetting: 一些和[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法)相關的參數
|
||||
1. jittertolerance: 抖動容許誤差,收到Pong以後,一個37ms,一個39ms,不會觸發重新計算
|
||||
1. jittertolerancemultiplier: 一樣是抖動容許誤差,但是高ping的話允許更多誤差
|
||||
https://www.desmos.com/calculator/raoti16r5n
|
||||
1. nodereporttimeout: 收到的`Pong`封包的有效期限。太久沒收到就變回Infinity
|
||||
1. recalculatecooldown: Floyd-Warshal是O(n^3)時間複雜度,不能太常算。設個冷卻時間
|
||||
|
||||
**最後,P2P模式我還沒有大規模測試過,穩定性不知如何。PR is welecome**
|
0
example_config/static_mode/README.md
Normal file
0
example_config/static_mode/README.md
Normal file
183
example_config/static_mode/README_zh.md
Normal file
183
example_config/static_mode/README_zh.md
Normal file
@ -0,0 +1,183 @@
|
||||
# Etherguard
|
||||
Static Mode的[範例配置檔](./)的說明文件
|
||||
|
||||
## Static Mode
|
||||
|
||||
沒有自動選路,沒有握手伺服器
|
||||
|
||||
十分類似原本的wireguard,一切都要提前配置好
|
||||
|
||||
但是除了peer以外,還要額外配置轉發表,所有人共用一份轉發表
|
||||
|
||||
設定檔裡面的`nexthoptable`部分,只有此模式會生效
|
||||
|
||||
這個模式下,不存在任何的Control Message,斷線偵測甚麼的也不會有
|
||||
請務必保持提前定義好的拓樸。不然如果存在中轉,中轉節點斷了,部分連線就會中斷
|
||||
|
||||
這份[範例配置檔](./)的網路拓樸如圖所示
|
||||
|
||||
!["Topology"](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/static_mode/Example_static.png)
|
||||
|
||||
發出封包時,會設定起始ID=自己的Node ID,終點ID則是看Dst Mac Address。
|
||||
如果Dst MacAddr是廣播地址,或是不在自己的對應表裡面,就會設定終點=Boardcast
|
||||
|
||||
收到封包的時候,如果`dst==自己ID`,就會收下,不轉給任何人。
|
||||
同時還會看它的 Src Mac Address 和 Src NodeID ,並加入對應表
|
||||
這樣下次傳給他就可以直接傳給目標,而不用廣播給全節點了
|
||||
|
||||
所以設定檔中的轉發表如下表。格式是yaml的巢狀dictionary
|
||||
轉發/發送封包時,直接查詢 `NhTable[起點][終點]=下一跳`
|
||||
就知道下面一個封包要轉給誰了
|
||||
|
||||
```
|
||||
nexthoptable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
```
|
||||
|
||||
### Boardcast
|
||||
比較特別的是`終點ID=Boardcast`的情況。
|
||||
|
||||
假設今天的狀況:我是4號,我收到`起點ID = 1,終點ID=boardcast`的封包
|
||||
我應該只轉給6號就好,而不會轉給3號。
|
||||
因為3號會收到來自2號的封包,自己就不用重複遞送了
|
||||
|
||||
因此我有設計,如果`終點ID = Boardcast`,就會檢查Src到自己的所有鄰居,會不會經過自己
|
||||
**1 -> 6** 會經過自己: [1 2 4 6]
|
||||
**1 -> 3** 不會: [1 2 3]
|
||||
2號是封包來源跳過檢查
|
||||
就能知道我應該把封包轉送給6號,而不轉送給3號
|
||||
|
||||
|
||||
### 小工具
|
||||
|
||||
如果懶的手算轉發表,本工具也能幫你算算
|
||||
|
||||
請先準備好一個txt檔,就叫他path.txt吧
|
||||
標記任2節點之間的單向延遲。`Inf`代表不可直連
|
||||
|
||||
```
|
||||
X 1 2 3 4 5 6
|
||||
1 0 0.5 Inf Inf Inf Inf
|
||||
2 0.5 0 0.5 0.5 Inf Inf
|
||||
3 Inf 0.5 0 0.5 0.5 Inf
|
||||
4 Inf 0.5 0.5 0 Inf 0.5
|
||||
5 Inf Inf 0.5 Inf 0 Inf
|
||||
6 Inf Inf Inf 0.5 Inf 0
|
||||
```
|
||||
|
||||
之後用這個指令就能輸出用Floyd Warshall算好的轉發表了,填入設定檔即可
|
||||
```
|
||||
./etherguard-go -config example_config/static_mode/path.txt -mode slove
|
||||
|
||||
NextHopTable:
|
||||
1:
|
||||
2: 2
|
||||
3: 2
|
||||
4: 2
|
||||
5: 2
|
||||
6: 2
|
||||
2:
|
||||
1: 1
|
||||
3: 3
|
||||
4: 4
|
||||
5: 3
|
||||
6: 4
|
||||
3:
|
||||
1: 2
|
||||
2: 2
|
||||
4: 4
|
||||
5: 5
|
||||
6: 4
|
||||
4:
|
||||
1: 2
|
||||
2: 2
|
||||
3: 3
|
||||
5: 3
|
||||
6: 6
|
||||
5:
|
||||
1: 3
|
||||
2: 3
|
||||
3: 3
|
||||
4: 3
|
||||
6: 3
|
||||
6:
|
||||
1: 4
|
||||
2: 4
|
||||
3: 4
|
||||
4: 4
|
||||
5: 4
|
||||
```
|
||||
|
||||
程式還會額外輸出一些資訊,像是路徑表。
|
||||
會標示所有的起點終點組合的封包路徑,還有行經距離
|
||||
```
|
||||
Human readable:
|
||||
src dist path
|
||||
1 -> 2 0.500000 [1 2]
|
||||
1 -> 3 1.000000 [1 2 3]
|
||||
1 -> 4 1.000000 [1 2 4]
|
||||
1 -> 5 1.500000 [1 2 3 5]
|
||||
1 -> 6 1.500000 [1 2 4 6]
|
||||
2 -> 1 0.500000 [2 1]
|
||||
2 -> 3 0.500000 [2 3]
|
||||
2 -> 4 0.500000 [2 4]
|
||||
2 -> 5 1.000000 [2 3 5]
|
||||
2 -> 6 1.000000 [2 4 6]
|
||||
3 -> 1 1.000000 [3 2 1]
|
||||
3 -> 2 0.500000 [3 2]
|
||||
3 -> 4 0.500000 [3 4]
|
||||
3 -> 5 0.500000 [3 5]
|
||||
3 -> 6 1.000000 [3 4 6]
|
||||
4 -> 1 1.000000 [4 2 1]
|
||||
4 -> 2 0.500000 [4 2]
|
||||
4 -> 3 0.500000 [4 3]
|
||||
4 -> 5 1.000000 [4 3 5]
|
||||
4 -> 6 0.500000 [4 6]
|
||||
5 -> 1 1.500000 [5 3 2 1]
|
||||
5 -> 2 1.000000 [5 3 2]
|
||||
5 -> 3 0.500000 [5 3]
|
||||
5 -> 4 1.000000 [5 3 4]
|
||||
5 -> 6 1.500000 [5 3 4 6]
|
||||
6 -> 1 1.500000 [6 4 2 1]
|
||||
6 -> 2 1.000000 [6 4 2]
|
||||
6 -> 3 1.000000 [6 4 3]
|
||||
6 -> 4 0.500000 [6 4]
|
||||
6 -> 5 1.500000 [6 4 3 5]
|
||||
```
|
||||
|
||||
接下來你就能了解一下[Super Mode的運作](../super_mode/README_zh.md)
|
BIN
example_config/super_mode/EGS01.png
Normal file
BIN
example_config/super_mode/EGS01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
example_config/super_mode/EGS02.png
Normal file
BIN
example_config/super_mode/EGS02.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
example_config/super_mode/EGS03.png
Normal file
BIN
example_config/super_mode/EGS03.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
BIN
example_config/super_mode/EGS04.png
Normal file
BIN
example_config/super_mode/EGS04.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
example_config/super_mode/EGS05.png
Normal file
BIN
example_config/super_mode/EGS05.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.3 KiB |
0
example_config/super_mode/README.md
Normal file
0
example_config/super_mode/README.md
Normal file
114
example_config/super_mode/README_zh.md
Normal file
114
example_config/super_mode/README_zh.md
Normal file
@ -0,0 +1,114 @@
|
||||
# Etherguard
|
||||
Super Mode的[範例配置檔](./)的說明文件
|
||||
在了解Super Mode的運作之前,建議您先閱讀[Static Mode的運作](../static_mode/README_zh.md)方法,再閱讀本篇會比較好
|
||||
|
||||
## Super Mode
|
||||
|
||||
Super Mode是受到[n2n](https://github.com/ntop/n2n)的啟發
|
||||
分為super node和edge node兩種節點
|
||||
|
||||
全部節點都會和supernode建立連線
|
||||
藉由supernode交換其他節點的資訊,以及udp打洞
|
||||
由supernode執行[Floyd-Warshall演算法](https://zh.wikipedia.org/zh-tw/Floyd-Warshall算法),並把計算結果分發給全部edge node
|
||||
|
||||
在super mode模式下,設定檔裡面的`nexthoptable`以及`peers`是無效的。
|
||||
這些資訊都是從super node上面下載
|
||||
|
||||
|
||||
### SuperMsg
|
||||
|
||||
但是比起Static mode,Super mode引入了一種新的 `終點ID` 叫做 `SuperMsg`。
|
||||
所有送往Super node的封包都會是這種類型。
|
||||
這種封包不會在edge node之間傳播,收到也會不會轉給任何人,如同`終點ID == 自己`一般
|
||||
|
||||
### Register
|
||||
|
||||
具體運作方式類似這張圖
|
||||
![EGS01](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS01.png)
|
||||
首先edge node發送regiater給super node
|
||||
super node收到以後就知道這個edge的endpoint IP和埠號。
|
||||
更新進資料庫以後發布`UpdatePeerMsg`。
|
||||
其他edge node收到以後就用HTTP API去下載完整的peer list。並且把自己沒有的peer通通加到本地
|
||||
|
||||
### Ping/Pong
|
||||
有了peer list以後,接下來的運作方式類似這張圖
|
||||
![EGS02](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS02.png)
|
||||
Edge node 會嘗試向其他所有peer發送`Ping`,裡面會攜帶節點自己的時間
|
||||
`Ping` 封包的TTL=0 所以不會被轉發,只會抵達可以直連的節點
|
||||
收到`Ping`,就會產生一個`Pong`,並攜帶時間差。這個時間就是單向延遲
|
||||
但是他不會把`Pong`送回給原節點,而是送給Super node
|
||||
|
||||
### 轉發表
|
||||
Super node收到節點們傳來的Pong以後,就知道他們的單向延遲了。接下來的運作方式類似這張圖
|
||||
![image](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS03.png)
|
||||
Super node收到Pong以後,就會更新它裡面的`Distance matrix`,並且重新計算轉發表
|
||||
如果有變動,就發布`UpdateNhTableMsg`
|
||||
其他edge node收到以後就用HTTP API去下載完整的轉發表
|
||||
|
||||
### HTTP API
|
||||
為什麼要用HTTP額外下載呢?直接`UpdateXXX`夾帶資訊不好嗎?
|
||||
因為udp是不可靠協議,能攜帶的內容量也有上限。
|
||||
但是peer list包含了全部的peer資訊,長度不是固定的,可能超過
|
||||
所以這樣設計,`UpdateXXX`單純只是告訴edge node有資訊更新,請速速用HTTP下載
|
||||
|
||||
而且`UpdateXXX`本身不可靠,說不定根本就沒抵達edge node。
|
||||
所以`UpdateXXX`這類資訊都帶了`state hash`。用HTTP API的時候要帶上
|
||||
這樣super node收到HTTP API看到`state hash`就知道這個edge node確實有收到`UpdateXXX`了。
|
||||
不然每隔一段時間就會重新發送`UpdateXXX`給該節點
|
||||
|
||||
### Guest API
|
||||
HTTP還有一個API
|
||||
`http://127.0.0.1:3000/api/peerstate?Password=passwd`
|
||||
可以給前端看的,用來顯示現在各節點之間的單向延遲狀況
|
||||
之後可以用來畫力導向圖。
|
||||
|
||||
這個json下載下來有一個叫做`infinity`的欄位,值應該永遠是99999
|
||||
因為json沒辦法表達無限大。所以大於這個數值的就是無限大,不可達的意思
|
||||
這個數值是編譯時決定的,一般不會動。但說不定你想改code,改成999呢?
|
||||
所以有這個欄位,前端顯示時看到數值大於這個,就視為不可達,不用畫線了
|
||||
|
||||
接下來你就能了解一下[P2P Mode的運作](../p2p_mode/README_zh.md)
|
||||
|
||||
## Config Paramaters
|
||||
|
||||
### Super mode的edge node有幾個參數
|
||||
1. `usesupernode`: 是否啟用Super mode
|
||||
1. `connurlv4`: Super node的IPv4連線地址
|
||||
1. `pubkeyv4`: Super node的IPv4工鑰
|
||||
1. `connurlv6`: Super node的IPv6連線地址
|
||||
1. `pubkeyv6`: Super node的IPv6工鑰
|
||||
1. `apiurl`: Super node的HTTP(S) API連線地址
|
||||
1. `supernodeinfotimeout`: Supernode Timeout
|
||||
|
||||
### Super node本身的設定檔
|
||||
|
||||
1. nodename: 節點名稱
|
||||
1. privkeyv4: ipv4用的私鑰
|
||||
1. privkeyv6: ipv6用的私鑰
|
||||
1. listenport: 監聽udp埠號
|
||||
1. statepassword: Guest API 的密碼
|
||||
1. loglevel: 參考 [README_zh.md](../README_zh.md)
|
||||
1. repushconfiginterval: 重新push`UpdateXXX`的間格
|
||||
1. graphrecalculatesetting:
|
||||
1. jittertolerance: 抖動容許誤差,收到Pong以後,一個37ms,一個39ms,不會觸發重新 計算
|
||||
1. jittertolerancemultiplier: 一樣是抖動容許誤差,但是高ping的話允許更多誤差
|
||||
https://www.desmos.com/calculator/raoti16r5n
|
||||
1. nodereporttimeout: 收到的`Pong`封包的有效期限。太久沒收到就變回Infinity
|
||||
1. recalculatecooldown: Floyd-Warshal是O(n^3)時間複雜度,不能太常算。設個冷卻時間
|
||||
1. peers: Peer列表,參考 [README_zh.md](../README_zh.md)
|
||||
1. nodeid: 1
|
||||
1. pubkey: ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=
|
||||
1. endpoint: 127.0.0.1:3001
|
||||
1. static: true
|
||||
|
||||
## V4 V6 兩個公鑰
|
||||
為什麼要分開IPv4和IPv6呢?
|
||||
因為有這種情況:
|
||||
|
||||
![OneChannel](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS04.png)
|
||||
|
||||
這樣的話SuperNode就不知道Node02的ipv4地址,就不能幫助Node1和Node2打洞了
|
||||
|
||||
![TwoChannel](https://raw.githubusercontent.com/KusakabeSi/EtherGuard-VPN/master/example_config/super_mode/EGS05.png)
|
||||
|
||||
所以要像這樣,V4和V6都建立一條通道,才能讓V4和V6同時都被處理到
|
@ -100,7 +100,13 @@ func printExampleEdgeConf() {
|
||||
Peers: []config.PeerInfo{
|
||||
{
|
||||
NodeID: 2,
|
||||
PubKey: "NuYJ/3Ght+C4HovFq5Te/BrIazo6zwDJ8Bdu4rQCz0o=",
|
||||
PubKey: "ZqzLVSbXzjppERslwbf2QziWruW3V/UIx9oqwU8Fn3I=",
|
||||
EndPoint: "127.0.0.1:3001",
|
||||
Static: true,
|
||||
},
|
||||
{
|
||||
NodeID: 2,
|
||||
PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=",
|
||||
EndPoint: "127.0.0.1:3002",
|
||||
Static: true,
|
||||
},
|
||||
|
@ -35,6 +35,7 @@ var (
|
||||
|
||||
type HttpState struct {
|
||||
PeerInfo map[config.Vertex]string
|
||||
Infinity float64
|
||||
Edges map[config.Vertex]map[config.Vertex]float64
|
||||
NhTable config.NextHopTable
|
||||
Dist config.DistTable
|
||||
@ -130,6 +131,7 @@ func get_info(w http.ResponseWriter, r *http.Request) {
|
||||
hs := HttpState{
|
||||
PeerInfo: make(map[config.Vertex]string),
|
||||
NhTable: http_graph.GetNHTable(false),
|
||||
Infinity: path.Infinity,
|
||||
Edges: http_graph.GetEdges(),
|
||||
Dist: http_graph.GetDtst(),
|
||||
}
|
||||
|
@ -142,12 +142,15 @@ func (g *IG) UpdateLentancy(u, v config.Vertex, dt time.Duration, recalculate bo
|
||||
if _, ok := g.edges[u]; !ok {
|
||||
g.edges[u] = make(map[config.Vertex]Latency)
|
||||
}
|
||||
g.edgelock.Unlock()
|
||||
should_update := g.ShouldUpdate(u, v, w)
|
||||
g.edgelock.Lock()
|
||||
g.edges[u][v] = Latency{
|
||||
ping: w,
|
||||
time: time.Now(),
|
||||
}
|
||||
g.edgelock.Unlock()
|
||||
if g.ShouldUpdate(u, v, w) && recalculate {
|
||||
if should_update && recalculate {
|
||||
changed = g.RecalculateNhTable(checkchange)
|
||||
}
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user