linux 下使用 dnsmasq + (nftables)iptables + ipset 可以完美解决
dnsmasq 的配置如下
server=/
facebook.net/8.8.8.8#53nftset=/
facebook.net/4#inet#wgcross#crs_dstserver=/
163.net/223.5.5.5#53nftset=/
163.net/4#inet#wgcross#cnserver 和 nftset 是 dnsmasq 的两个配置项,server 项的作用是收到 dns 请求后进行匹配(可按照域名级别进行匹配),比如上面例子中*.facebook.net 的域名都被转发给 8.8.8.8 解析,并且将解析的 ip 写入 nftables 中的 wgcross 表的 crs_dst set 进行存储,然后路由表当然也要设置,我的例子如下
chain PREROUTING { # handle 2
type nat hook prerouting priority filter; policy accept;
ip daddr { 23.95.146.49, 65.49.219.226, 193.22.152.174 } accept # handle 4
ip daddr { 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0-255.255.255.255 } accept # handle 6
ip daddr @
cn accept # handle 8
ip daddr @
crs_dst counter name "cnt_cross" meta mark set 0x00000009 accept # handle 10
}
最后两个路由条目,cn set 针对国内的路由,命中这个 set 中的路由就返回上级 chain(及走国内线路),而另一个 crs_dst set 会 mark 0x9 ,然后在 ip route 中挑出来走海外线路
这个技术路线,必须 DNS\route gateway 的功能集中在一台设备上。