找回密码
 加入我们
搜索
      
查看: 27749|回复: 39

[网络] 基于路由协议的ip分流(RouterOS为例)

[复制链接]
发表于 2022-8-22 13:16 | 显示全部楼层 |阅读模式
我的例子里做到的效果是(本文以分流中国大陆IP/非中国大陆IP为例)
1. 正常状态: ip分流,DNS无污染,中国大陆直连出去,除了少量特殊配置比如icloud啥的强制直连,剩下的走隧道
2. 异常状态: 自动切换到全部直连,DNS有污染
3. 故障恢复: 自动恢复到正常状态

实际上通过多个tun设备分别连接不同的隧道出口+细化的路由表,是可以做到更细粒度的控制的
比如亚太方向流量走HK的隧道,美洲方向流量走LA隧道,欧洲走荷兰隧道等等
如有需要请自行研究,大体框架和下面的是一样的

这个和基于L7或者Address Lists分流方案的主要区别有两点
1. 性能: 通过路由器最擅长的路由来处理,因为直接网段/接口隔离不需要使用mangle来给流量打标,且不使用L7识别,不需要破坏硬件加速转发特性
2. 故障波及范围小: 假设隧道故障,大陆IP不受影响,且未被墙的非大陆IP会在短时间后快速变为直连状态(尽管也可以通过script处理,但是如果你体验过大批量导入/删除Address Lists的卡卡卡卡卡,我猜你是不会这么选的)

前提,你要收一份对应的路由表
方法1. 参考BakaCai的博客《在家也要玩BGP 之 Mikrotik Fan Boy版》自己收全表过滤出来
方法2. 利用nchnroutes项目跑一份出来
方法3. 直接拿别人跑好的,比如我用GitHub action定时跑的这个项目
方法4. 其他现成的地址段配置转换

接下来需要一台支持路由协议(BGP/OSPF等)的主路由,和一台可以运行clash等隧道+bird的隧道端点机(openwrt或者debian等常见linux发行版都可以)
我这边的环境如下

设备及系统版本
- 主路由MikroTik AC^2(ros 6.48.6 lt)
- 隧道端点NUC5(debian 11.3)

网段
- PC/WLAN等需要透明网关的(lan桥): 192.168.1.0/24
- 直通(ether5): 192.168.255.0/24

这边把ether5这个口踢出lan桥,单独给分配192.168.255.1/24,lan桥分配192.168.1.1/24
端点机分配192.168.255.254/24
路由配置打通两个网段

  1. /ip route
  2. add distance=1 gateway=pppoe-out routing-mark=bypass
  3. add distance=1 dst-address=10.0.0.0/8 gateway=lan routing-mark=bypass
  4. add distance=1 dst-address=169.254.0.0/16 gateway=lan routing-mark=bypass
  5. add distance=1 dst-address=172.16.0.0/12 gateway=lan routing-mark=bypass
  6. add distance=1 dst-address=192.168.0.0/16 gateway=lan routing-mark=bypass
  7. add distance=1 dst-address=224.0.0.0/4 gateway=lan routing-mark=bypass
  8. add distance=1 dst-address=255.255.255.255/32 gateway=lan routing-mark=bypass
  9. /ip route rule
  10. add interface=lan table=main
  11. add interface=ether5 table=bypass
复制代码

两边互ping一下确认是否ok(windows防火墙可能会拦截icmp)

接下来给lan配一个dns劫持,还有dns自动切换

  1. /ip firewall nat
  2. add action=dst-nat chain=dstnat comment="Hijacking for DNS" dst-port=53 protocol=udp src-address=192.168.1.0/24 to-addresses=192.168.1.1 to-ports=53
  3. /system script
  4. add dont-require-permissions=yes name=use-default-dns owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/ip dns set allow-remote-requests=yes servers=119.29.29.29,223.5.5.5 \r\n/ip dns cache flush"
  5. add dont-require-permissions=yes name=use-sgw-dns owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/ip dns set allow-remote-requests=yes servers=192.168.255.254\r\n/ip dns cache flush"
复制代码

注意netwatch要在隧道端点的dns服务启动后再加(比如这个例子里的clash),或者添加后先disable,最后再回来enable,不然就半断网了(解析不了dns)
  1. /tool netwatch
  2. add down-script=use-default-dns host=192.168.255.254 interval=5s up-script=use-sgw-dns
复制代码


接下来是路由协议的配置,我之前使用7.x版本的ros+ospf,不是很稳定,时不时有一些小毛病,这里就回退到6.x的LT版本上用bgp来跑,截至目前没有发现不正常的地方
不管是BGP还是OSPF在这个场景上作用都是一样的,就是把端点机上宣过来的路由加到main表里,如果使用OSPF需要在防火墙放行ospf协议和组播(或者使用点对点模式),bgp的话有上面的路由规则就可以了

  1. /routing bgp instance
  2. set default router-id=192.168.255.1
  3. /routing bgp peer
  4. add multihop=yes name=sgw remote-address=192.168.255.254 remote-as=65531
复制代码


然后是debian的配置
软件选择bird2来跑路由协议,clash premium跑隧道(自带tun和dns,可以省下tun2socks和smartdns)

替换你的clash订阅地址,按需修改external-controller/external-ui
/etc/clash/config.yaml
  1. dns:
  2.   enable: true
  3.   ipv6: true
  4.   listen: 0.0.0.0:53
  5.   enhanced-mode: redir-host
  6.   use-hosts: true
  7.   default-nameserver:
  8.     - 119.29.29.29
  9.     - 223.5.5.5
  10.   nameserver:
  11.     - 119.29.29.29
  12.     - 223.5.5.5
  13.   fallback:
  14.     - https://dns.google/dns-query
  15.     - https://cloudflare-dns.com/dns-query
  16.     - https://1.1.1.1/dns-query
  17.     - https://8.8.8.8/dns-query
  18.     - https://8.8.4.4/dns-query
  19.   fallback-filter:
  20.     geoip: true
  21.     ipcidr:
  22.       - 240.0.0.0/4
  23. tun:
  24.     enable: true
  25.     stack: system
  26.     auto-detect-interface: true
  27. port: 7890
  28. socks-port: 7891
  29. redir-port: 7893
  30. allow-lan: true
  31. mode: Rule
  32. log-level: silent
  33. external-controller: '0.0.0.0:8080'

  34. proxy-groups:
  35.   - name: PROXY
  36.     type: select
  37.     use:
  38.       - subscribe

  39. proxy-providers:
  40.   subscribe:
  41.     type: http
  42.     url: 替换成你的clash订阅地址
  43.     interval: 86400
  44.     path: ./proxy/subscribe.yaml
  45.     health-check:
  46.       enable: false
  47.       interval: 600
  48.       # lazy: true
  49.       url: http://www.gstatic.com/generate_204

  50. rule-providers:
  51.   icloud:
  52.     type: http
  53.     behavior: domain
  54.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/icloud.txt"
  55.     path: ./ruleset/icloud.yaml
  56.     interval: 86400

  57.   apple:
  58.     type: http
  59.     behavior: domain
  60.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/apple.txt"
  61.     path: ./ruleset/apple.yaml
  62.     interval: 86400

  63.   google:
  64.     type: http
  65.     behavior: domain
  66.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt"
  67.     path: ./ruleset/google.yaml
  68.     interval: 86400

  69.   proxy:
  70.     type: http
  71.     behavior: domain
  72.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt"
  73.     path: ./ruleset/proxy.yaml
  74.     interval: 86400

  75.   direct:
  76.     type: http
  77.     behavior: domain
  78.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/direct.txt"
  79.     path: ./ruleset/direct.yaml
  80.     interval: 86400

  81.   private:
  82.     type: http
  83.     behavior: domain
  84.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/private.txt"
  85.     path: ./ruleset/private.yaml
  86.     interval: 86400

  87.   telegramcidr:
  88.     type: http
  89.     behavior: ipcidr
  90.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/telegramcidr.txt"
  91.     path: ./ruleset/telegramcidr.yaml
  92.     interval: 86400

  93.   cncidr:
  94.     type: http
  95.     behavior: ipcidr
  96.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt"
  97.     path: ./ruleset/cncidr.yaml
  98.     interval: 86400

  99.   lancidr:
  100.     type: http
  101.     behavior: ipcidr
  102.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/lancidr.txt"
  103.     path: ./ruleset/lancidr.yaml
  104.     interval: 86400

  105.   applications:
  106.     type: http
  107.     behavior: classical
  108.     url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/applications.txt"
  109.     path: ./ruleset/applications.yaml
  110.     interval: 86400

  111. rules:
  112.   - PROCESS-NAME,clash,DIRECT
  113.   - RULE-SET,applications,DIRECT
  114.   - RULE-SET,private,DIRECT
  115.   - RULE-SET,icloud,DIRECT
  116.   - RULE-SET,apple,DIRECT
  117.   - RULE-SET,google,DIRECT
  118.   - RULE-SET,proxy,PROXY
  119.   - RULE-SET,direct,DIRECT
  120.   - RULE-SET,lancidr,DIRECT
  121.   - RULE-SET,cncidr,DIRECT
  122.   - RULE-SET,telegramcidr,PROXY
  123.   - GEOIP,LAN,DIRECT
  124.   - GEOIP,CN,DIRECT
  125.   - MATCH,PROXY
复制代码

最好用yacd之类接进去确认一下GLOBAL是不是direct
如果有smartdns或者dnsmasq会变得很麻烦,需要解决端口冲突问题改成解析链,再加上对应的PROCESS-NAME DIRECT规则,总之不建议开这些

/etc/bird/bird.conf
  1. log syslog all;

  2. router id 192.168.255.254;

  3. protocol device {
  4.         scan time 60;
  5. }

  6. protocol kernel {
  7.         ipv4 {
  8.               import none;
  9.               export all;
  10.         };
  11. }

  12. protocol static {
  13.         ipv4;
  14.         include "routes4.conf";
  15. }

  16. protocol bgp {
  17.         local as 65531;
  18.         neighbor 192.168.255.1 as 65530;
  19.         source address 192.168.255.254;
  20.         ipv4 {
  21.                 import none;
  22.                 export all;
  23.         };
  24. }
复制代码

crontab添加2条定时刷新路由

  1. 0 2 * * * curl -s https://api.xn--7ovq92diups1e.com/ncr?device=utun -o /etc/bird/routes4.conf
  2. 0 3 */1 * * /etc/init.d/bird reload
复制代码

手动执行一次初始化

  1. curl -s https://api.xn--7ovq92diups1e.com/ncr?device=utun -o /etc/bird/routes4.conf
复制代码

就可以启动clash和bird2的服务了(以及使能前面的netwatch)

再加一个健康检查脚本,访问Google异常并且重试失败后关闭bird和icmp响应,触发ros自动切换

/root/check.sh
  1. #!/usr/bin/bash
  2. COUNT=0
  3. MAX_COUNT=3
  4. while [ $COUNT -lt $MAX_COUNT ]
  5. do
  6.         SER=0
  7.         NET=0
  8.         if [ $(curl --connect-timeout 5 --interface utun -w "%{http_code}" -s https://www.google.com/generate_204) -eq 204 ];then
  9.                 NET=1
  10.         fi
  11.         if /etc/init.d/bird status|grep Active|grep -q running;then
  12.                 SER=1
  13.         fi
  14.         if [ $NET -eq 1 ] && [ $SER -eq 0 ];then
  15.                 /etc/init.d/bird start
  16.                 echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_all
  17.                 exit 0
  18.         fi
  19.         if [ $NET -eq 0 ] && [ $SER -eq 1 ];then
  20.                 let COUNT+=1
  21.                 if [ $COUNT -eq $MAX_COUNT ];then
  22.                         /etc/init.d/bird stop
  23.                         echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all
  24.                 fi
  25.                 continue
  26.         fi
  27.         exit 0
  28. done
复制代码

crontab添加规则

  1. * * * * * /root/check.sh
复制代码

测试一下
111.png
可见访问国外ip和国内ip已经不一样了,分流完成
发表于 2022-8-22 13:46 | 显示全部楼层
还是mangle灵活一点,可以指定端口爬梯,这样只翻80  443 953之类的,不用担心bt和游戏之类的流量乱跑
发表于 2022-8-22 13:51 | 显示全部楼层
有哭的时候。
发表于 2022-8-22 14:42 来自手机 | 显示全部楼层
最近也想研究下,先mark
 楼主| 发表于 2022-8-22 14:46 | 显示全部楼层
老饭 发表于 2022-8-22 13:46
还是mangle灵活一点,可以指定端口爬梯,这样只翻80  443 953之类的,不用担心bt和游戏之类的流量乱跑 ...

主要是mangle开了之后NAT的硬件加速就寄了,端口规则可以加到clash里,只对特定DST-PORT,其他direct就可以了
发表于 2022-8-22 14:47 来自手机 | 显示全部楼层
不推荐用nchnroutes,用ASN分流
 楼主| 发表于 2022-8-22 14:54 | 显示全部楼层
Darcychiu 发表于 2022-8-22 14:47
不推荐用nchnroutes,用ASN分流

有条件自己收表ASN过滤肯定是最稳的,但是其他论坛看其实还有不少人是一周一更新的状态....
nchnroutes起码不至于滞后这么多
发表于 2022-8-22 14:57 | 显示全部楼层
mark下。学习下。
发表于 2022-8-22 16:00 | 显示全部楼层
Ryo_ 发表于 2022-8-22 14:46
主要是mangle开了之后NAT的硬件加速就寄了,端口规则可以加到clash里,只对特定DST-PORT,其他direct就可以 ...

我是CHR,没有nat硬件加速
发表于 2022-8-22 17:45 | 显示全部楼层
不懂搞成这样的意义,尤其是用了Clash的情况下
 楼主| 发表于 2022-8-22 19:03 | 显示全部楼层
XHY 发表于 2022-8-22 17:45
不懂搞成这样的意义,尤其是用了Clash的情况下

你要是不嫌吵,主路直接用一台Juniper SRX的防火墙(比如比较入门便宜的240),可以配出来和这个一样的组网
这种组网下网络的稳定性可靠性可以做的很高,隧道炸了影响也小
发表于 2022-9-1 22:59 | 显示全部楼层
本帖最后由 xenosccc 于 2022-9-2 14:34 编辑

小白请教下“proxy-groups:
  - name: PROXY
    type: select
    use:
      - subscribe

proxy-providers:
  subscribe:
    type: http
    url: 替换成你的clash订阅地址
    interval: 86400
    path: ./proxy/subscribe.yaml
    health-check:
      enable: false
      interval: 600
      # lazy: true
      url: http://www.gstatic.com/generate_204
发表于 2022-9-2 10:05 | 显示全部楼层
高手高手
发表于 2022-9-2 11:03 | 显示全部楼层
学习下ros的ip分流方法,收藏
 楼主| 发表于 2022-9-2 14:12 | 显示全部楼层
xenosccc 发表于 2022-9-1 22:59
小白请教下“proxy-groups:
  - name: PROXY
    type: select

订阅 就是yaml的链接,顺便最近最好别在CHH讨论这个...你看下版头锁定贴
发表于 2022-9-2 14:35 | 显示全部楼层
本帖最后由 xenosccc 于 2022-9-2 15:03 编辑
Ryo_ 发表于 2022-9-2 14:12
订阅 就是yaml的链接,顺便最近最好别在CHH讨论这个...你看下版头锁定贴


已编辑了。
发表于 2022-9-5 13:49 | 显示全部楼层
来学习 不知道如何是好 各种分流都折腾过了 各种问题 后来改用option来指定网关和dns了
发表于 2022-9-5 15:22 | 显示全部楼层
Darcychiu 发表于 2022-8-22 14:47
不推荐用nchnroutes,用ASN分流

如果没有喂到嘴里的教程,可能需要考完ccnp才能折腾吧~
 楼主| 发表于 2022-9-5 15:56 | 显示全部楼层
tunluan 发表于 2022-9-5 15:22
如果没有喂到嘴里的教程,可能需要考完ccnp才能折腾吧~

其实细化ASN分流如果把隧道端点换成ISP接入点, 不就是 IDC 机房 BGP 多线接入那套东西吗
发表于 2022-9-17 14:24 | 显示全部楼层
我那个ospf,还没搞定apple系列的问题
具体表现为:
1. appstore有时候进不去
2. homekit 在外面无法使用

dns用的smartdns,默认配置。。。。不知掉咋设置
发表于 2022-9-17 15:15 | 显示全部楼层
我这边就是死活无法放行openwrt的流量
openwrt也是单独和ros另外一个网卡连的
添加了bypass放行的表,但是就是出不去,一直进入死循
发表于 2022-9-17 15:43 | 显示全部楼层
本帖最后由 guitengyue 于 2022-9-17 15:49 编辑

/ip route
add distance=1 gateway=pppoe-out routing-mark=bypass
我这条一加,整个系统就不能fq了
而且这条应该是这样的吧?dst-address必须要添加?
add distance=1 dst-address=0.0.0.0/0 gateway=pppoe-out routing-mark=bypass
 楼主| 发表于 2022-9-18 23:08 | 显示全部楼层
guitengyue 发表于 2022-9-17 15:43
/ip route
add distance=1 gateway=pppoe-out routing-mark=bypass
我这条一加,整个系统就不能fq了

完整展开应该是
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=pppoe-out pref-src=0.0.0.0 routing-table=bypass scope=30 suppress-hw-offload=no target-scope=10

正常不写应该也会自动给你加的
发表于 2022-9-18 23:11 | 显示全部楼层
Ryo_ 发表于 2022-9-18 23:08
完整展开应该是
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=pppoe-out pref-src=0.0.0.0 ...

嗯,就是这样的,加了就直接不行了,你博客里面也留言了,搞不定
今天整回去用了ip分流方案
 楼主| 发表于 2022-9-18 23:58 | 显示全部楼层
guitengyue 发表于 2022-9-18 23:11
嗯,就是这样的,加了就直接不行了,你博客里面也留言了,搞不定
今天整回去用了ip分流方案 ...

建议尝试一下通过socks5接clash能不能正常访问,确认下是clash出去的方向有问题还是main表收到的路由有问题,如果ospf在ros报错可能是组播的毛病,可以试着把ospf换成点对点模式或者直接bgp来跑
发表于 2022-9-19 21:13 | 显示全部楼层
Ryo_ 发表于 2022-9-18 23:58
建议尝试一下通过socks5接clash能不能正常访问,确认下是clash出去的方向有问题还是main表收到的路由有问 ...

我用的是ros+openwrt(bird+passwall)
clash没用过,用你博客教程照抄后,ubuntu中的bird运行后提示这个,ospf1: Bad HELLO packet from nbr 192.168.1.1 on ens192 - prefix length mismatch (23)
弄不下去了。。。牺牲0.1s的体验算了,还是用回ip分流了
发表于 2022-9-28 01:49 | 显示全部楼层
Mark,我先在虚拟机里模拟部署一遍再上真机。
发表于 2022-10-13 17:33 | 显示全部楼层
请问下,pt网站怎么处理,都是国外ip,还都是变化的?
 楼主| 发表于 2022-10-21 16:10 | 显示全部楼层
chengwanyu 发表于 2022-10-13 17:33
请问下,pt网站怎么处理,都是国外ip,还都是变化的?

我目前是对特定端口进来的流量直接走另一个路由表放行出去,然后把下载机之类的挂在这个端口下
这么别扭的做法主要是为了保留ROS的NAT加速,如果不是因为这个的话直接在mangle表按照原地址打route marking就可以了
发表于 2022-10-21 21:30 | 显示全部楼层
直接在mangle表按照原地址打route marking就可以了  这个求解 怎么做的,,不太懂
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

Archiver|手机版|小黑屋|Chiphell ( 沪ICP备12027953号-5 )沪公网备310112100042806 上海市互联网违法与不良信息举报中心

GMT+8, 2024-9-19 23:14 , Processed in 0.017019 second(s), 6 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2007-2024 Chiphell.com All rights reserved.

快速回复 返回顶部 返回列表