改用 Script 更新 Routing Lists

前一天試著用 /etc/ppp/ip-up 在連上 VPN 後自動加入 white list routing,目前有兩個缺點:

  1. 完整性不夠。因為 Facebook 用了 CDN,除了自家的還有 Akamai 的,不論是用 dig, ping, nslookup, traceroute 等等工具,都沒辦法查出完整的 ip 區段,所以常常會發生讀不出資料、破圖的現象。
  2. 因為網段是寫死在裡頭的,如果哪天這些 CDN 做了修改,或是擴充新的網域,沒辦法去回溯,要除錯也有些困難。

所以還是想要找個方法來解決這些問題。

Google 了一下,雖然有人也整理出 Facebook 在某個國家內的 CDN list,但一樣有完整性不足的問題。另外有人問了 google 的 CDN,結果是透過 BGP AS Prefixes 來查詢註冊在該公司下的網域,所以只要把 Facebook 和 Akamai 的網域都查出來加入就夠完整了。

就 Facebook 公司的區段 (AS32934) 來說是不多(30~40 筆上下),大部分在之前也查得差不多了,但 Akamai 就 了(800~900 筆),要我每一條都手動加入太耗工程,還是得弄個 script 出來,不只省得加入,還可以解決寫死在裡頭的問題。

查了一下,沒有 BGP 的 API 可以運用,所以只好轉向網站去擷取,一開始鎖定的是 Hurricane Electric BGP Toolkit,不過因為一開始沒發現 wget 不送出 User-Agent,它就不給資料(會傳回 403 Forbidden),所以轉向 dan (看起來像個個人網站),結果沒抓幾次資料,它就說我超過單日 query 上限了。@_@

所以在發現 wget 要送出 User-Agent 後,擷取網頁的 script 如下:

/usr/local/bin/wget -qO- -U Safari http://bgp.he.net/AS32934

為了把資料抓出來,用 grep 搭配 regular expression:

/usr/bin/egrep "/net/[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/[[:digit:]]{1,2}"

抓出來後還要用 sed 裁切:

/usr/bin/sed 's/^.*">\(.*\)<.*$/\1/'

之後用 xargs 把參數餵給 route

/usr/bin/xargs -I % /sbin/route add % -interface ppp0

因為要放在 /etc/ppp/ip-up 裡面使用,所以把 ppp0 改用 $1 替代。綜合起來:

/usr/local/bin/wget -qO- -U Safari http://bgp.he.net/AS32934 | /usr/bin/egrep "/net/[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/[[:digit:]]{1,2}" | /usr/bin/sed 's/^.*">\(.*\)<.*$/\1/' | /usr/bin/xargs -I % /sbin/route add % -interface $1

其中的 AS32934 是 Facebook 公司,如果要涵蓋 Akamai 則加入 AS21399 和 AS20940, 同理,也可以把 Yahoo 等等想涵蓋的公司加進去,AS number 就不附上了。

雖然 Facebook 應該只是 Akamai 眾多客戶其中之一,把該公司所有的網域全部涵蓋有點浪費,但這也是寧可錯殺一百也不願放過一個的折衷辦法了。