ospf-ibgp-generator

  1. all_node.yaml複製到 input 資料夾
  2. generate_config_func.py 複製到 input 資料夾
  3. 修改 input/all_node.yaml
  4. 執行 python3 generate_config.py
  5. 本專案不會對電腦系統做出任何變更。只是生成一大堆 wireguard 設定檔,需自行部屬去對應節點自己執行

使用說明

  1. up.sh 建立隧道。開機時執行
  2. update.sh 進行 DDNS 更新隧道 endpoint。需定時執行
  3. update_cost.py 測量隧道延遲,更新進 ospf 設定檔。需定時執行
  4. bird 設定檔裡面 include /output/xxxx/bird/*.conf 檔案
  5. down.sh 刪除所有隧道。關閉網路時執行

Known Issue

使用於公網隧道互聯,尚未實現隧道本身的路由表和 main 路由表分表的功能

一般情況下, bird 會寫入路由到 main 表。但是隧道也根據 main 表決定封包走向,會導致 loop
DN42 網路不影響,因為隧道 endpoint 是公網 IP,而 DN42 路由表和隧道 endpoint 絕對不會重疊
現行解決方案只能是 v6 only network 只使用 ipv4 打隧道,而 v4+v6 雙線只能自行打隧道,使用 phys 類型

  • wg: 需使用 fwmark + ip rule add fwmark xxx lookup xxx 實現 wg 隧道不走 main 表
  • gre: 指定 src ip + ip rule add from x.x.x.x lookup xxx 實現 gre 隧道本身不走 main 表

UDP 打洞

現行策略是雙邊都是 NAT ,兩邊就不會互連,需靠有公網的伺服器中轉。具體走哪台中轉就看 ospf 選路
理論上,使用 wg 是可以進行 udp 打洞的,過程如下:

  • 每分鐘進行一次 DDNS 更新
  • 每分鐘進行一次 update ,把 wg 指向對面的 endpoint
  • 雙方互相連向對方的 endpoint:port ,NAT 偵測到雙邊通訊以後,建立起 NAT entry 打洞成功

只是我暫時用不到,所以我沒有實現。 PR is welecome

all_node.yaml 說明

image

defaults: 預設值,這個數值會套用到所有節點上,除非在底下改寫

  • area_id: ospf area_id
  • port_base: 18000 分配外部端口的起始。 18000 18001 18002 這樣分配下去
  • port_base_i: 36000 分配內部端口的起始。 36000 36001 36002 ...
  • server_perf: 100 雙方都有公網IP的時候,成為server的傾向。數值大的成為server
  • tunnel:
    • -1: wg 和目標建立的隧道類型。 -1代表所有目標

內部端口: wg_udp2raw就需分配一個內部端口,讓wg和udp2raw連線。此端口無須暴露在外網,不用占去寶貴的port forward名額
外部端口: udp2raw和對面udp2raw連線的端口。此端口需要被port forward

tunnel

tunnel則是指定節點之間如何互聯。
?-所有人: 這個是在default裡面的值,意思是所有人-所有人使用wg互聯
image

紅色: 日本-美國之間使用openvpn互聯
黃色: 德國-南京之間不互聯
綠色: 南京-"-1",也就是南京-所有人所有人使用 wg_udp2raw 方式互聯
image

此時發生衝突, 1->12 使用wg, 12->1 使用wg_udp2raw。就會使用優先權高的wg_udp2raw

優先權定義在 generate_config_func.py 裡面,擺在越上面越優先
image

整體來說就是 美國-日本用openvpn,南京-其他人(跨GFW)用wg_udp2raw,德國-南京不連,剩下的使用wg互聯

server_perf

wg是點對點,沒有這個問題,但是openvpn/udp2raw都要一邊做server,一邊做client。
如果其中一邊是NAT,那就一定是另一邊做server。如果兩邊都是NAT,就不會建立連線
image
但如果兩邊都不是NAT,則由 server_perf 數值高的做server ,另一邊做client

  • udp2raw server不支援域名,必須使用IP
  • gre tunnel兩邊都必須使用IP,不能使用域名

AF

endpoint裡面有 -4-6 ,可以自訂義增加別的,或是只使用一個。相同AF之間會互相建立。
以我的例子來說,因為ipv4/ipv6延遲可能不一樣,所以節點間同時建立 ipv4 和 ipv6 連線,由 ospf 挑選延遲低的走

DDNS

見 Output章節

Output

生成的結果會放在output資料夾,用name區分每個節點的設定檔。
image 用github/gitee或是什麼方法同步到自己的節點上就可以了

裡面有3個重要的檔案

up.sh

裡面是建立tunnel的指令。請自行加入開機自啟動
image
以及igp_tunnels資料夾,包含了建立tunnel所需的設定檔。公鑰/私鑰/預共享金鑰都會自動生成
image

down.sh

image
用來一鍵關閉+刪除本腳本建立的tunnel

update.sh

還記得剛剛的 DDNS=True ,我說見 Output章節嗎,這個就是更新wg endpoint的腳本。
被標記成DDNS=True的節點,會出現在update.sh裡面。
內容是重新解析域名,指定到wg接口上。 自己把它放在crontab就可以了
image

generate_config_func.py 說明

隧道具體的建立方式,在這邊定義。我目前已經完成 None, "wg" , "wg_udp2raw" , "gre" , "openvpn"
image
get_gre / get_wg_udp2raw / get_wg / get_openvpn 四個function會回傳具體的設定檔,up/down腳本

非常歡迎自訂義新的tunnel種類
輸入長這樣:
image

返回值是 server 和 client 的設定檔,有 confs up down三個部分
image

可以去 test_func.ipynb 測試

Dependance

cd ~
apt install -y git wireguard-tools python3-pip net-tools libc-bin gawk ntp
systemctl enable ntp
systemctl start ntp
pip3 install -r requirement.txt
wget https://github.com/wangyu-/udp2raw/releases/download/20200818.0/udp2raw_binaries.tar.gz
tar -xvzf udp2raw_binaries.tar.gz -C udp2raw
mv udp2raw/udp2raw_amd64 /usr/bin/udp2raw