Skip to content
ashi009 edited this page Apr 11, 2013 · 25 revisions

Best Route Table

https://github.com/fivesheep/chnroutes 启发。

这一项目旨在生成最小化的路由表,同时确保这一路由表将一部分地址路由到默认网关, 另一部分地址路由到VPN网关。

相比之下,bestroutetb生成的路由表比chnroutes小70%(将美、英、港、日的地址路由到 VPN),若只将美国地址路由到VPN网关,则生成的路由表不到chnroutes路由表的2%大小。 虽然路由表大小的变化并不能直接反应在网络性能上,但是最小化的路由表节约了路由器上 宝贵的资源(不论是存储空间,还是空闲内存),同时提高了加载路由表的速度。即使您的 系统没有 IPROUTE2 套件(如 Windows、OS X 和部分 DDWrt 以及 openWRT), bestroutetb的路由表也可以在几秒内完成加载,而chnroutes的路由表需要数倍到数十倍的时间。

另外,由于bestroutetb的工作模式与chnroutes不同,所以一般数月更新一次即可,而无需每日更新。

若想了解更多,请查看翻墙 VPN 本地路由表的优化

依赖

该项目主要用 javascript 编写,同时也使用了部分 bash 代码,所以您需要使用 node.js 来运行 js 脚本。

bash 脚本相对简单,将来可能会重写为 Windows 支持的 batch 脚本。但是无论如何, 目前还是要使用 wget 下载最新的 IP 分配文件。

如何使用

快速入门

./generate.sh route_table > analysis_result

这将输出路由指令(OpenVPN 语法)到route_table文件,同时将路由评估报告输出到analysis_result

这一路由表中会把全部中国地址路由到默认网关,美国、英国、日本、香港管辖的地址路由 到VPN网关。

注意,源文件列表里routes是预先生成的路由表,routes-us是只将美国地址路由到 VPN网关的路由表。

如果您并无特别的需求,可以直接采用 routes-us 作为您的路由表。

使用此脚本的语法:

./generate.sh 输出文件名 [选项]

其中

  • 输出文件名输出路由表的路径。
  • 选项 将被重定向给 minifier.js 以及 formatter.js

玩点儿更有意思的

node minifier.js [--net=规则] [--vpn=规则]

其中

  • --net 用于指定的国家缩写和IP子网列表。这些地址都会被路由到默认网关。默认为 CN
  • --vpn 用于指定的国家缩写和IP子网列表。这些地址都会被路由到VPN网关。默认为 US,GB,JP,HK
  • 规则 为国家缩写或a.b.c.d/mask形式的IP块、IP列表,或者一个规则文件的地址, 以半角逗号(,)分割。注意:国家缩写可以在countries.res中查找,规则文件中 的地址将不会再被解析。

该脚本将会用 JSON 格式输出路由规则文件到 stdout,统计信息会输出到 stderr ,所以请将 stdout 重定向到文件中。推荐直接使用 generate.sh

JSON 格式:

[
  Rule,
  ...
]

Rule 结构:

{
  "prefix": "dest",
  "mask": "netmask",
  "length", netmaskLength,
  "gw": "net|vpn"
}

示例:

node minifier.js --net=128.8.0.0/16 --vpn=specs

其中 specs 文件包含:

# 国家列表(没错,可以用注释)
GB
# IP 列表
8.0.0.0/8
123.4.5.6 # 这是一个主机地址

输出:

[{
  "prefix": "0.0.0.0",
  "mask": "0.0.0.0",
  "length": 0,
  "gw": "vpn"
}, {
  "prefix": "128.0.0.0",
  "mask": "255.240.0.0",
  "length": 12,
  "gw": "net"
}]
Total: 2 rules

格式化规则文件

node formatter.js [规则文件] [--profile=PROFILE]
    [--header=HEADER] [--footer=FOOTER]
    [--format=FORMAT] [--netgw=NETGW] [--vpngw=VPNGW]
    [--nodefaultgw=1]
    [--groupgw=GROUPGW]
    [--groupheader=GROUPHEADER] [--groupfooter=GROUPFOOTER]
    [arguments]

其中

  • 规则文件 是生成的规则文件的地址,若忽略则使用 stdin
  • --profile 格式化档案,可以选择预制的 openvpnroute_uproute_downiproute_upiproute_downwin_upwin_downppp_ip_up,以及自定义 custom。 默认为 openvpn.
  • --header 输出文件的文件头。
  • --footer 输出文件的文件尾。
  • --format 在指定 --profile=custom 时所使用的规则格式化字符串。您可以使用 %prefix%mask%length%gw 代表 Rule 中的对应项。 同时您还可以使用arguments传入的其他字段(%[a-zA-Z]\w*)。
  • --netgw使用 --profile=openvpn 时针对 "gw": "net" 规则的 %gw 替代。
  • --vpngw使用 --profile=openvpn 时针对 "gw": "vpn" 规则的 %gw 替代。
  • --nodefaultgw 不输出默认路由规则(0.0.0.0/0)。
  • --groupgw 将规则按照网关分组。当希望规则输出为两部分时十分有用,比如为每个端口 编写对应的ip-up函数时。当设置 --profile=ppp_ip_up 时默认为 1,其余情况为 0。
  • --netgroupname--groupgw=1 时针对 "gw": "net" 规则的 %name 替代。
  • --vpngroupname--groupgw=1 时针对 "gw": "vpn" 规则的 %name 替代。
  • --groupheader 组头。主意,这里可以用 %name 指代组名。
  • --groupfooter 组尾。主意,这里可以用 %name 指代组名。
  • arguments 提供 format 使用的参数 (如添加 --var="value",则可以在 --format 中使用 %var 指代 value。)

示例:

node formatter.js rules.json
# or node minifier.js --vpn=us | node formatter.js

输出:

Total: 99 rules
route 0.0.0.0 0.0.0.0 vpn_gateway
route 0.0.0.0 254.0.0.0 net_gateway
route 1.0.16.0 255.255.240.0 vpn_gateway
route 1.0.64.0 255.255.192.0 vpn_gateway
route 1.1.64.0 255.255.192.0 vpn_gateway
route 1.5.0.0 255.255.0.0 vpn_gateway
route 1.16.0.0 255.248.0.0 vpn_gateway
route 1.32.0.0 255.248.0.0 vpn_gateway
route 1.64.0.0 255.252.0.0 vpn_gateway
route 1.72.0.0 255.248.0.0 vpn_gateway
route 1.112.0.0 255.252.0.0 vpn_gateway
...

生成 OpenWRT 所用路由表的实例

分析一个路由表

路由表的分析工具可以显示出当前路由表处理APNIC及非APNIC地址的情况,它会按照国别和网关对地址进行统计。

node evaluator.js [规则文件] [--verbose=1] [--defaultgw=默认网关]

其中

  • 规则文件 是生成的规则文件的地址,若忽略则使用 stdin
  • --verbose 将输出所有地址块的路由结果。默认情况下关闭。
  • --default 设置默认网关,即0.0.0.0/0所使用的网关,默认为default

输出:

net_gateway:
    澳大利亚  53.65%  25626880
    中国  100.00% 329991424
    泰国  49.02%  4196352
    印度  74.76%  26023936
    马来西亚  43.92%  2784000
    韩国(南) 63.61%  71394048
    越南  86.02%  13377024
    台湾  65.80%  23288320
    印尼  75.64%  13171712
    巴布亚新几内亚 24.53%  13312
    尼泊尔 76.99%  364800
    新加坡 36.93%  2241280
    阿富汗 30.95%  33280
    柬埔寨 38.45%  89088
...

更新 IP 分配文件

rm -f data/*
./generate.sh

使用路由表

OpenVPN

推荐 bestroutetb产生的路由表为OpenVPN格式,使用时最为方便。一般情况下,只需要将产生的路由表 复制到配置文件的结尾即可。但是有几点需要注意:

  • OpenVPN 默认只支持100条路由指令,一般需要使用max-routes指令扩大容量。

    这一指令需要放在路由指令前,格式为max-routes: 路由指令数量,指令数量应为产生 路由表时输出的路由数量加10,以方便服务器推送路由命令。

    如生成路由表时输出Total: 1096 rules,则需要设置max-routes: 1106

    小心,如果你的OpenVPN配置文件中含有redirect-gateway指令,则一定要在 这一指令前设置max-routes,否则指令不会生效。

  • OpenVPN 的工作方式可能和生成的路由表不兼容。

    你的OpenVPN服务提供商可能在配置文件中确定了工作模式:

    修改默认路由使用VPN网关;
    保留默认路由的网关设置,增加128.0.0.0/0和128.0.0.0/1使用VPN网关。
    

    这时候你需要手动调整路由表以满足具体的情况。如在生成的路由表中的默认路由0.0.0.0/0 使用了本地网关(net_gateway,)此时你需要配置OpenVPN不修默认改网关设置,只增加 到VPN服务器的路由项:route remote_host 255.255.255.255 net_gatway。同时 还需要去掉生成的路由表中的0.0.0.0项。

  • 其他问题请查看文档,或者在issue中提出。

Linux 通用

如果你在使用OpenVPN,请尽可能的将路由配置嵌入配置文件,这样可以提供不少方便。

在Linux环境一般使用up.shdown.sh来修改路由表,由于bestroutetb产生的路由表需要 知道默认网关的地址,所以up.sh脚本需要在VPN连接建立后使用,使用pre-up.sh来记录默认网关。

下边的代码没有测试过,如有问题请在issue中提出

pre-up.sh 示例

#!/bin/bash

read target dummy netgw dummy <<< $(ip route get 8.8.8.8)
echo $netgw > /tmp/net_gateway

up.sh

使用 `generate.sh up.sh --profile=route_up` 生成的代码。

down.sh

使用 `generate.sh down.sh --profile=route_down` 生成的代码

Windows

Windows环境的路由表加载比较慢,而且Windows的路由表个性强大,所以会比较麻烦。所以为 Windows用户提供了setroutes.js工具来加载路由表(直接在cmd中运行就可以,无需node.js。)

这一脚本使用了WMI界面加载/卸载路由表,相比使用route.exe程序和批处理命令,至少有 两倍的性能提升。脚本会尽可能的猜测默认网关和VPN网关的地址,如果失败请手动指定。

如有问题请在issue中提出。

注意 ,请在具有管理员权限的窗口中运行下列指令。

使用时语法如下:

cscript setroutes.js (up|down) RouteFile [/netgw:IP] [/vpngw:IP]

其中

  • up|down 分别表示加载和卸载路由表。
  • RouteFile 为生成的OpenVpn格式路由表。
  • /netgw:IP 用于指定本地网关IP。
  • /vpngw:IP 用于指定VPN网关IP。

例如:

cscript setroutes.js up routes /netgw:192.168.1.1

如果为了方便可以另外新建两个批处理文件避免输入指令。

up.bat 示例

@echo off
cscript setroutes.js up routes

down.bat 示例

@echo off
cscript setroutes.js down routes