MikroTik RouterOS 基于 BGP 的策略路由
基于 IP 路由的分流可谓是最简单粗暴的实现境内外路由分流的二层流量分流方式。
目前,已有多种引入路由的方式:
使用如 cn-routefeed 等基于 WHOIS 信息的工具。该工具将定时拉去 APNIC 的 WHOIS 信息,当 country 项匹配 CN 时则通过 BGP 分发。
缺点在于部分 IP 前缀的 WHOIS 信息存在虚标,如 45.125.18.0/23 的 WHOIS 中 country 项为 CN,但实则为在香港进行宣告。因此按该方式分流的准确性相对较低,
使用如 misakaio/chnroute2 等第三方整理好的同样基于 BGP 的中国大陆路由信息。
缺点在于需要定期拉取并导入路由表,且自定义空间低。
使用 BGP 接受全表并过滤出来自中国大陆的路由信息。这正是本文要介绍的方法。
好处在于 BGP 路由表实时更新;且 BGP 属性中携带路径信息,十分好用。基于中国大陆路由的 Transit 仅限于中国电信、联通和移动三家运营商,我们可以很容易地通过 AS Path 过滤出在中国大陆宣告的 IP 段。
环境介绍
目前我的家庭网络主网关为一台 MikroTik RouterOS 设备,接入有一条中国电信宽带 (pppoe-ct)、一条中国移动宽带 (pppoe-cm) 和一条 WireGuard 隧道 (wg0)。
我的网络规划为:
1 | 1) 添加一条默认路由 0.0.0.0/0 指向 WireGuard 对端 IP 作为出口。 |
我已在一台 Debian 机器上通过 BIRD2 接收了来自供应商 Vultr 的全表并进行了初步的必要过滤。这意味着你可能需要首先向 RIR (APNIC, RIPE, ARIN, etc.) 申请一个 ASN。
预处理
BIRD2 十分轻量,高效且内存占用极低。实测在 BIRD2 存储 996k 个前缀、1960k 个路由条目并导入到 Linux 内核路由表时,仅占用不足 550MB 内存。
因此,为了防止弱小的 RouterOS 路由器 CPU 时间或内存爆炸,我们先在远端运行 BIRD2 接受供应商全表的机器上进行预处理,使其仅导出中国大陆的路由条目。同时按需添加 BGP Large Community (或 BGP Community 也可),便于后续 RouterOS 端分流,当然直接根据 AS Path 分流也可。
1 | export filter { |
如此处理后,实测约导出 47k 条路由。这些路由仍包含 AS Path 信息,使得我们后续可以在 RouterOS 端继续进行细致化分流。
建立 BGP 会话
MikroTik RouterOS 设备与远端 BIRD2 机器建立 BGP 会话时,由于我们仅接受路由而无需使用 BIRD2 机器作为路由器进行路由转发,我们既可以通过公网直接连接,亦可以在隧道之上建立会话。本文为在 WireGuard 之上建立会话,若通过公网则需将 direct;
改为 multihop;
。
远端 BIRD2 机器的部分配置如下。
1 | protocol bgp ibgp_cn_can1_v4 { # 按需替换协议名, 可自定义 |
MikroTik RouterOS 设备的 BGP 在 Winbox 中的 Routing - BGP
进行配置,Connection 的部分配置如下。
配置 RouterOS 端过滤器
RouterOS 执行过滤器的逻辑为从第 0 条规则开始向后执行,即按 0 -> 1 -> 2 -> …… 的顺序。
以下过滤器均基于 RouterOS v7,在 RouterOS v6 上由于语法不同可能会导致错误的结果,请按需修改。
1 | /routing/filter/rule add chain=handle_import_te rule="if (bgp-large-communities includes 114514:0:1) { set gw %pppoe-ct; }" |
-> 旨在为打上 114514:0:1 社区 (社区含义为从 pppoe-ct 出站) 的路由指向 pppoe-ct 接口。
1 | /routing/filter/rule add chain=handle_import_te rule="if (bgp-large-communities includes 114514:0:2) { set gw %pppoe-cm; }" |
-> 旨在为打上 114514:0:2 社区 (社区含义为从 pppoe-cm 出站) 的路由指向 pppoe-cm 接口。
1 | /routing/filter/rule add chain=handle_import_te rule="accept;" |
-> 处理后的路由全部接受。因我们已经在 BIRD2 机器上进行了必要过滤和预处理,故无需再进行其他的过滤。
最后在 BGP 的 Connection
设置中的 Filter - Input Filter
项选择 handle_import_te
即可完成。