stevemorrislian 发表于 2018-10-10 22:11

RouterOS上的电信/移动双路由,按目标IP确定出口

本帖最后由 stevemorrislian 于 2019-3-15 17:02 编辑

基本设想是国外用移动线路优先,电信用电信出口优先,其他就随缘了

首先是下载2个路由表,一个国内IP地址表,一个电信地址表=>这里的关键是逻辑关系,想清楚与和非的关系,因为出口列表很难用两个 《非》来界定出口方向

GitHub的ChnRoutes路由表,以APNIC的独立系统号为标准,随时更新的
https://github.com/fivesheep/chnroutes/blob/master/chnroutes.py
是用python编写的,也可以直接下载读取的txt文件。或者rsc执行文件,可以放到ROS下去执行

在路由器中建立地址表Domestic,用ip->firewall->address list以后也可以添加这个表
IP -> routes下,修改0.0.0.0/0的移动出口网关,添加Routing Mark=CM

dst-address=0.0.0.0/0 gateway=192.168.100.1 gateway-status=192.168.100.1 reachable viapppoe-out1
      distance=1 scope=30 target-scope=10 routing-mark=CM
也就是说这个标签的会走192.168.100.1这个出口。

然后在IP->firewall->mangle下,建立prerouting的chain,在advance下设置条件dest. address list为"非"Domestic,方框的"!“表示非,domestic是下载的地址表
chain=prerouting action=mark-routing new-routing-mark=CM passthrough=yesdst-address-list=!Domestic
其中prerouting的数据链表示在路由前作标记,这样不在Domestic的表中的目标IP,就打了标记CM,路由将选择移动出口

但是国内除了电信,还有联通。而去联通目标也是移动更好。
所以第二选择是电信,方法差不多,就是电信的标记TeleCom,目标地址不用非,也就是没“!”号。
如果有第三,第四出口,都不能用!的地址表

最后还是把不打标记的路由0.0.0.0/0加上,免得数据出不去,实际上考虑的是3出口状态,你懂的!

在nat的配置下,每个方向都要做masquerade,看上去差不多了。考虑到电信,移动的MTU,MSS不同change mss,取最小的值。虽然估计1480也够
chain=forward action=change-mss new-mss=1460 passthrough=yes tcp-flags=syn protocol=tcp log=no log-prefix=""



后面讲我自己遇到的问题
1,原来想只打telecom的标记,因为打标记的路由是优先的,如果打电信路由,国外的就没有标记,想出国的数据就会走到国内(是的。逻辑混乱,但请另外理解),最后没有标记的还是会经过移动出口的

2,想先打移动(移动不肯给公网IP,固定的私网)而不是电信,发现用非电信+非国内打标记,那么国内的标记就会出现2次都打标记的情况(国外也是非电信,与逻辑混乱一个意义),对路由器而言会占用CPU,关键是还会走错地方

3,手贱,选择了自己路由器PPPoE的电信出口,这样就有一个公网IP可以测试用途了(比如voip的电话通过l2tp用来从家里打电话)。这引起了LOG大爆发,赶紧开防火墙
规则:
0    chain=input action=drop src-address-list=BlockIPs log=no log-prefix=""
1    chain=forward action=drop src-address-list=BlockIPs log=no log-prefix=""
2    chain=output action=drop dst-address-list=BlockIPs log=no log-prefix=""

建立黑名单,进出遇到BlockIPs表里的IP地址全部封杀,用mangle,因为黑客也是不固定IP的,就停掉5天,免得地址表太大
   chain=input action=add-src-to-address-list protocol=tcp src-address=!172.16.0.0/16 src-address-list=192.168.0.0/16address-list=BlockIPs address-list-timeout=5d port=21-25 log=no log-prefix=""

原来只想input的可能,发现log内还有很多port=23的试探,加了prerouting,
   chain=prerouting action=add-src-to-address-list protocol=tcp src-address=!192.168.0.0/16src-address-list=!172.16.0.0/16 address-list=BlockIPs address-list-timeout=5d port=21-25 log=no log-prefix=""

对voip盗打电话我比较痛恨,关15天,地址表里也分得清情况
   chain=prerouting action=add-src-to-address-list protocol=udp src-address=!192.168.0.0/16src-address-list=!172.16.0.0/16 address-list=BlockIPs address-list-timeout=2w1d port=5060-5061 log=no log-prefix=""

三天有680个IP被加入BlockIPs,其中1/10来自盗打电话的试探。以后看connections再加规则

4,一个动态路由的测试,为了保障移动出口到国外的带宽,大部分还是走电信出口,但遇到特殊需求时走移动口
开了一个192.168.88.0/24的DHCP,这个地址段中如果访问推文(或者开着这个窗口不关),以后所有数据就去移动,平常即使国外也走电信出口

先建立钩子,一旦访问目标在ToWatch这个List里,就把源IP放进去国外的临时表SourceTemp(过期时间1分钟),这个list内就是自己常看的电视,比如skynet,Bloomberg,twitter这些IP
chain=prerouting action=add-src-to-address-list protocol=tcp src-address=192.168.88.0/24dst-address-list=ToWatch address-list=SourceTemp address-list-timeout=1m log=no log-prefix=""
然后给源SourceTemp也打上第一个CM的标记就可以了,只要关掉相应的窗口,就回到最后不打标记的出口

5,路由器上同时做dns forward,这样路由器本身就要访问外网,并没有内网192.168.0.0/16作为源地址的连接。为了解决这个问题,另外建立chain=output,条件一样
同时又发现又有大量的dns访问,同样用mangle的input链,从PPPoE进来的外网IP都放入黑名单。
发现不能把forward的上线dns设置为8.8.8.8,因为它太著名,许多污染记录都是针对它,不如找个冷门的dns,只要不在国内,也不通过国内的接口去访问

6,终于找到了解决DNS的方法,不仅要躲在防火墙后,lookup也不能从正常的出口走。好在我本来就通过CAPsMAN管理着多个LAP,用LAP同步8.8.8.8

7,有些用了CDN的网站,被分流后无法正常访问,因为它本身就用了不同的IP,当来源属于不同的IP时就无法正常运作了。我看股票的网站就有这情况,解决方法就是先建立一个表,CDNSites,一旦访问这些IP,就把源IP加入NoCDN,对NoCDN的源暂时(30秒)不走打标记的路由。一旦手机把APP关掉,就恢复按目标IP分流,方法基本同4,只是反着来。



stevemorrislian 发表于 2018-10-15 22:03

本帖最后由 stevemorrislian 于 2018-10-15 22:07 编辑

168kingmu 发表于 2018-10-14 22:57
楼主实现了嘛?我和楼主一模一样,加一个QQ交流一下
我的dns解析次序是自己本地服务器的dnsmasq,然后是114.114.114.114,所以结果大多不是电信的,目标移动的最多。这是对sina的结果
/tool> traceroute www.sina.com
# ADDRESS                        LOSS SENT    LAST   AVG    BEST   WORST STD-DEV STATUS                                 
1 172.16.6.1                         0%    2   4.3ms   4.5   4.3   4.7   0.2                                       
2 ##########                  0%    298.4ms    87.4    76.3    98.4    11.1                                       
3###########                   0%    2   5.7ms       6   5.7   6.2   0.3                                       
4 172.18.27.1                        0%    240.4ms    42.4    40.4    44.3       2                                       
5 223.119.0.165                      0%    241.9ms    41.6    41.3    41.9   0.3                                       
6 223.118.18.161                     0%    2 245.5ms   245   244.4   245.5   0.6                                       
7 149.14.81.185                      0%    2 256.1ms   263.3   256.1   270.5   7.2                                       
8 130.117.2.13                     0%    2 264.4ms   264.4   264.4   264.4       0                                       
9 154.54.56.238                      0%    1 266.8ms   266.8   266.8   266.8       0                                       
10                                  100%    1 timeout                                                                        
11                                  100%    1 timeout                                                                        
12                                  100%    1 timeout                                                                        
13                                  100%    1 timeout                                                                        
14                                  100%    1 timeout                                                                        

/tool> traceroute www.sina.com.cn
# ADDRESS                        LOSS SENT    LAST   AVG    BEST   WORST STD-DEV STATUS                                 
1 192.168.100.1                      0%    4   0.2ms   1.2   0.2   4.1   1.7                                       
2 100.75.0.1                         0%    4   7.3ms   7.8       7   8.9   0.7                                       
3 #########                   0%    4   7ms    13.4   5.8    33.2    11.4                                       
4*************                  25%    4    47ms      22   7.6      47    17.7                                       
5##########                  0%    4   7ms   7.2       7   7.3   0.1                                       
6                                  100%    4 timeout                                                                        
7 221.183.55.33                     50%    4 timeout    10.3   9.9    10.6   0.4                                       
8 223.120.22.6                     0%    458.9ms    59.4    58.9    60.3   0.7                                       
9 223.120.2.1                        0%    340.1ms      40    39.9    40.1   0.1                                       
10 223.120.2.54                     0%    3    40ms    41.2      40      42   0.9                                       
11 123.255.90.36                      0%    341.2ms    42.2    41.2    43.7   1.1                                       
12 218.189.124.194                  0%    351.6ms    49.8    48.6    51.6   1.3                                       
13                                  100%    3 timeout                                                                        
14 36.51.254.37                     0%    341.9ms    42.3    41.9    43.1   0.5                                       


> server 202.96.209.133
默认服务器:ns-pd.online.sh.cn
Address:202.96.209.133

> www.sina.com.cn
服务器:ns-pd.online.sh.cn
Address:202.96.209.133

非权威应答:
名称:    spool.grid.sinaedge.com
Address:202.102.94.124
Aliases:www.sina.com.cn

>




/tool> traceroute 202.102.94.124
# ADDRESS                        LOSS SENT    LAST   AVG    BEST   WORST STD-DEV STATUS                                 
1 ##########                     0%   12   3.9ms   4.9   1.9   7.2   1.8                                       
2 ##########                        0%   12   4.7ms   6.6   3.1    10.7   2.2                                       
3 ##########                     0%   12   3.4ms   4.3       3   9.4   2.2                                       
4 202.97.29.110                      0%   12   8.9ms   8.6   7.4    10.7   0.8                                       
5 61.160.140.46                      0%   12   8.2ms   7.7   6.8   8.2   0.4                                       
6 202.102.73.194                     0%   1211.4ms    14.3    11.4    25.6   3.7                                       
7 180.97.12.62                     0%   1213.5ms    27.4    11.5    60.2    15.5                                       
8                                  100%   12 timeout                                                                        
9 202.102.94.124                     0%   11   7.8ms   7.9   7.6   8.2   0.2   

stevemorrislian 发表于 2018-10-21 12:41

本帖最后由 stevemorrislian 于 2018-10-21 12:46 编辑

做了点修改,产生的是适合ROS用的,最后一列是时间,可以用excel之类的表格软件排序,这样可以添加到原来的list中

#!/usr/bin/env python

import re
import urllib2
import sys
import argparse
import math
import textwrap


def generate_ovirtual**(metric):
    results = fetch_ip_data()
    rfile=open('routes.txt','w')
    for ip,datenum,mask2 in results:
      route_item="add list=domesticList address=%s/%s \t %s \n"%(ip,mask2,datenum)
      rfile.write(route_item)
    rfile.close()
    print "Usage: Append the content of the newly created routes.txt to your openvirtual** config file," \
          " and also add 'max-routes %d', which takes a line, to the head of the file." % (len(results)+20)


def generate_linux(metric):
    results = fetch_ip_data()
    upscript_header=textwrap.dedent("""\
    #!/bin/bash
    export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
   
    OLDGW=`ip route show | grep '^default' | sed -e 's/default via \\([^ ]*\\).*/\\1/'`
   
    if [ $OLDGW == '' ]; then
      exit 0
    fi
   
    if [ ! -e /tmp/virtual**_oldgw ]; then
      echo $OLDGW > /tmp/virtual**_oldgw
    fi
   
    """)
   
    downscript_header=textwrap.dedent("""\
    #!/bin/bash
    export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
   
    OLDGW=`cat /tmp/virtual**_oldgw`
   
    """)
   
    upfile=open('ip-pre-up','w')
    downfile=open('ip-down','w')
   
    upfile.write(upscript_header)
    upfile.write('\n')
    downfile.write(downscript_header)
    downfile.write('\n')
   
    for ip,mask,_ in results:
      upfile.write('route add -net %s netmask %s gw $OLDGW\n'%(ip,mask))
      downfile.write('route del -net %s netmask %s\n'%(ip,mask))

    downfile.write('rm /tmp/virtual**_oldgw\n')


    print "For p p t p only, please copy the file ip-pre-up to the folder/etc/ppp," \
          "and copy the file ip-down to the folder /etc/ppp/ip-down.d."

def generate_mac(metric):
    results=fetch_ip_data()
   
    upscript_header=textwrap.dedent("""\
    #!/bin/sh
    export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
   
    OLDGW=`netstat -nr | grep '^default' | grep -v 'ppp' | sed 's/default *\\(*\\) .*/\\1/' | awk '{if($1){print $1}}'`

    if [ ! -e /tmp/p p t p_oldgw ]; then
      echo "${OLDGW}" > /tmp/p p t p_oldgw
    fi
   
    dscacheutil -flushcache

    route add 10.0.0.0/8 "${OLDGW}"
    route add 172.16.0.0/12 "${OLDGW}"
    route add 192.168.0.0/16 "${OLDGW}"
    """)
   
    downscript_header=textwrap.dedent("""\
    #!/bin/sh
    export PATH="/bin:/sbin:/usr/sbin:/usr/bin"
   
    if [ ! -e /tmp/p p t p_oldgw ]; then
            exit 0
    fi
   
    ODLGW=`cat /tmp/p p t p_oldgw`

    route delete 10.0.0.0/8 "${OLDGW}"
    route delete 172.16.0.0/12 "${OLDGW}"
    route delete 192.168.0.0/16 "${OLDGW}"
    """)
   
    upfile=open('ip-up','w')
    downfile=open('ip-down','w')
   
    upfile.write(upscript_header)
    upfile.write('\n')
    downfile.write(downscript_header)
    downfile.write('\n')
   
    for ip,_,mask in results:
      upfile.write('route add %s/%s "${OLDGW}"\n'%(ip,mask))
      downfile.write('route delete %s/%s ${OLDGW}\n'%(ip,mask))
   
    downfile.write('\n\nrm /tmp/p p t p_oldgw\n')
    upfile.close()
    downfile.close()
   
    print "For p p t p on mac only, please copy ip-up and ip-down to the /etc/ppp folder," \
          "don't forget to make them executable with the chmod command."

def generate_win(metric):
    results = fetch_ip_data()

    upscript_header=textwrap.dedent("""@ECHO off
    for /F "tokens=3" %%* in ('route print ^| findstr "\\<0.0.0.0\\>"') do set "gw=%%*"
   
    """)
   
    upfile=open('virtual**up.bat','w')
    downfile=open('virtual**down.bat','w')
   
    upfile.write(upscript_header)
    upfile.write('\n')
    upfile.write('ipconfig /flushdns\n\n')
   
    downfile.write("@echo off")
    downfile.write('\n')
   
    for ip,mask,_ in results:
      upfile.write('route add %s mask %s %s metric %d\n'%(ip,mask,"%gw%",metric))
      downfile.write('route delete %s\n'%(ip))
   
    upfile.close()
    downfile.close()
   
#    up_vbs_wrapper=open('virtual**up.vbs','w')
#    up_vbs_wrapper.write('Set objShell = CreateObject("Wscript.shell")\ncall objShell.Run("virtual**up.bat",0,FALSE)')
#    up_vbs_wrapper.close()
#    down_vbs_wrapper=open('virtual**down.vbs','w')
#    down_vbs_wrapper.write('Set objShell = CreateObject("Wscript.shell")\ncall objShell.Run("virtual**down.bat",0,FALSE)')
#    down_vbs_wrapper.close()
   
    print "For p p t p on windows only, run virtual**up.bat before dialing to virtual**," \
          "and run virtual**down.bat after disconnected from the virtual**."

def generate_android(metric):
    results = fetch_ip_data()
   
    upscript_header=textwrap.dedent("""\
    #!/bin/sh
    alias nestat='/system/xbin/busybox netstat'
    alias grep='/system/xbin/busybox grep'
    alias awk='/system/xbin/busybox awk'
    alias route='/system/xbin/busybox route'
   
    OLDGW=`netstat -rn | grep ^0\.0\.0\.0 | awk '{print $2}'`
   
    """)
   
    downscript_header=textwrap.dedent("""\
    #!/bin/sh
    alias route='/system/xbin/busybox route'
   
    """)
   
    upfile=open('virtual**up.sh','w')
    downfile=open('virtual**down.sh','w')
   
    upfile.write(upscript_header)
    upfile.write('\n')
    downfile.write(downscript_header)
    downfile.write('\n')
   
    for ip,mask,_ in results:
      upfile.write('route add -net %s netmask %s gw $OLDGW\n'%(ip,mask))
      downfile.write('route del -net %s netmask %s\n'%(ip,mask))
   
    upfile.close()
    downfile.close()
   
    print "Old school way to call up/down script from openvirtual** client. " \
          "use the regular openvirtual** 2.1 method to add routes if it's possible"


def fetch_ip_data():
    #fetch data from apnic
    print "Fetching data from apnic.net, it might take a few minutes, please wait..."
    url=r'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest'
    data=urllib2.urlopen(url).read()
   
    cnregex=re.compile(r'apnic\|cn\|ipv4\|+\|+\|+\|a.*',re.IGNORECASE)
    cndata=cnregex.findall(data)
   
    results=[]

    for item in cndata:
      unit_items=item.split('|')
      starting_ip=unit_items
      num_ip=int(unit_items)
      datenum=unit_items
      
      imask=0xffffffff^(num_ip-1)
      #convert to string
      imask=hex(imask)
      mask=*4
      mask=imask
      mask=imask
      mask=imask
      mask=imask
      
      #convert str to int
      mask=[ int(i,16 ) for i in mask]
      mask="%d.%d.%d.%d"%tuple(mask)
      
      #mask in *nix format
      mask2=32-int(math.log(num_ip,2))
      
      results.append((starting_ip,datenum,mask2))
         
    return results


if __name__=='__main__':
    parser=argparse.ArgumentParser(description="Generate routing rules for virtual**.")
    parser.add_argument('-p','--platform',
                        dest='platform',
                        default='openvirtual**',
                        nargs='?',
                        help="Target platforms, it can be openvirtual**, mac, linux,"
                        "win, android. openvirtual** by default.")
    parser.add_argument('-m','--metric',
                        dest='metric',
                        default=5,
                        nargs='?',
                        type=int,
                        help="Metric setting for the route rules")
   
    args = parser.parse_args()
   
    if args.platform.lower() == 'openvirtual**':
      generate_ovirtual**(args.metric)
    elif args.platform.lower() == 'linux':
      generate_linux(args.metric)
    elif args.platform.lower() == 'mac':
      generate_mac(args.metric)
    elif args.platform.lower() == 'win':
      generate_win(args.metric)
    elif args.platform.lower() == 'android':
      generate_android(args.metric)
    else:
      print>>sys.stderr, "Platform %s is not supported."%args.platform
      exit(1)

168kingmu 发表于 2018-10-22 10:54

#      DST-ADDRESS      PREF-SRC      GATEWAY            DISTANCE
0 A S0.0.0.0/0                        pppoe-out2                1
1 ADS0.0.0.0/0                        10.126.128.1            0
2DS0.0.0.0/0                        116.8.216.1               0
3 ADC10.126.128.1/32    10.126.216.244pppoe-out2                0
4 ADC116.8.216.1/32   116.8.216.16    pppoe-out1                0
5 ADC192.168.14.0/24    192.168.14.1    bridge                  0

stevemorrislian 发表于 2018-10-10 22:26

有空接着写,主要是遇到的问题

168kingmu 发表于 2018-10-14 22:57

楼主实现了嘛?我和楼主一模一样,加一个QQ交流一下

stevemorrislian 发表于 2018-10-15 21:54

168kingmu 发表于 2018-10-14 22:57
楼主实现了嘛?我和楼主一模一样,加一个QQ交流一下

总有些细节不尽如人意,但是给出的这些都是成功测试的

168kingmu 发表于 2018-10-16 11:22

stevemorrislian 发表于 2018-10-15 22:03
我的dns解析次序是自己本地服务器的dnsmasq,然后是114.114.114.114,所以结果大多不是电信的,目标移动 ...

我的dns是一台lede,所有流量都会经过软件中心的$$,他解析出来后经过ros出去,Facebook可能没有,微信有么,或者tg?不行的话我回去申请一下fb,不过fb要审核本人头像?可能需要一点时间

168kingmu 发表于 2018-10-16 14:58

telegram....我申请fb了

168kingmu 发表于 2018-10-16 21:17

我邮箱私聊你了

168kingmu 发表于 2018-10-20 12:11

本帖最后由 168kingmu 于 2018-10-20 12:46 编辑



这是我现在的拓扑图
ROS(IP:192.168.14.1)负责DHCP和拨号
LEDE(IP:192.168.14.2)作为DNS和网关负责梯子和去广告


https://static.chiphell.com/forum/201708/15/170209gcbcgvct1y3c6wtn.png
PPPOE-OUT2是移动宽带,我去网上下载的大陆IP列表名称是no未批恩,创建的桥接名称是bridge,需要所有lan口和局域网IP的国外网站进出都走移动,你看我这个设置对没有,特别是这个general-src.add和in.interface和add type选择了local并且取反,这些地方你教程好像都没有说,但是我按照了其他教程设置上去了




168kingmu 发表于 2018-10-20 12:14

本帖最后由 168kingmu 于 2018-10-20 12:57 编辑

最后怎么测试设置成功了,非大陆走移动 大陆走电信呢



我好像设置不对,刚刚看了一下流量,我在看优酷和斗鱼流量都走移动去了没有走电信PPPoE-out1都没有流量,全是out2的移动流量,。。。

168kingmu 发表于 2018-10-20 13:08

是我设置错了还是我移动是内网IPV4+内网IPV6的地址,电信是IP是公网的IPV4地址,流量都从IPV6走了?但是我访问的地址已经都是IPV4的吧

168kingmu 发表于 2018-10-20 13:38

是不是要在下载一个电信的ipv4列表来设置???

stevemorrislian 发表于 2018-10-20 22:42

168kingmu 发表于 2018-10-20 12:11
这是我现在的拓扑图
ROS(IP:192.168.14.1)负责DHCP和拨号
LEDE(IP:192.168.14.2)作为DNS和网关 ...

没看懂你的桥接是啥功能,请说清楚

stevemorrislian 发表于 2018-10-20 22:45

168kingmu 发表于 2018-10-20 12:14
最后怎么测试设置成功了,非大陆走移动 大陆走电信呢




根据目标IP做traceroute测试,我把结果贴出来就是这个意思

stevemorrislian 发表于 2018-10-20 22:52

168kingmu 发表于 2018-10-20 13:08
是我设置错了还是我移动是内网IPV4+内网IPV6的地址,电信是IP是公网的IPV4地址,流量都从IPV6走了?但是我 ...

terminal下,命令:
IP - Routes - print

路由怎么设置的?
页: [1] 2
查看完整版本: RouterOS上的电信/移动双路由,按目标IP确定出口