爱意满满的作品展示区。
liuchen9586

Linux 策略路由: Linux 下使用基于源地址的策略路由来实现 VPN 隧道流量转接功能

  •  6
     
  •   liuchen9586 · Mar 29, 2015 · 26725 views
    This topic created in 4248 days ago, the information mentioned may be changed or developed.
    实验是我在CentOS 6.5 x86_64上做的,现在已经投入到生产环境中。
    网络一直很稳定,带10个人一起玩东南亚CSGO毫无压力。
    拓扑是这样的:


    其他发行版的Linux可以把命令翻译下,原理是一模一样的。

    需要工具:
    1、OpenVPN (UDP封装速度快,效率高。玩游戏必备。PPTP VPN也行,但是速度没那么快。)
    2、ShadowVPN (虽然是Beta状态,使用的效率还是很高的。因为无状态,所以不被干扰。)
    3、IP rule
    4、iptables

    步骤:

    ------先做好基本环境配置------

    0、更新生产环境(因为我是在纯净的系统上做的)

    sudo yum -y groupinstall "Development Tools"
    yum -y install openssl*

    1、打开ipv4转发功能。

    vim /etc/sysctl.conf
    net.ipv4.ip_forward = 0 修改成 net.ipv4.ip_forward = 1
    sysctl -p

    2、添加epel源,直接从源安装openvpn,让用户通过openvpn接入国内中转服务器。

    我使用的是中科大的源(因为我就在合肥所以速度快 :P)
    wget http://mirrors.ustc.edu.cn/epel/6/x86_64/epel-release-6-8.noarch.rpm
    rpm -ivh epel-release-6-8.noarch.rpm
    yum makecache
    yum -y install openvpn

    签发证书的教程:
    http://blog.chinaunix.net/uid-29746173-id-4351133.html
    做完后记得打开openvpn使用的端口。

    3、安装ShadowVPN,使用ShadowVPN将国内中转服务器和国外服务器对接起来

    项目地址: https://github.com/clowwindy/ShadowVPN/

    wget https://github.com/clowwindy/ShadowVPN/releases/download/0.1.6/shadowvpn-0.1.6.tar.gz
    tar zxvf shadowvpn-0.1.6.tar.gz
    ./configure --enable-static --sysconfdir=/etc
    make && sudo make install

    记得打开ShadowVPN用的端口,不然隧道起不来。

    记得清除掉ShadowVPN client_up.sh中的一段命令:

    # change routing table
    echo changing default route
    if [ pppoe-wan = "$old_gw_intf" ]; then
    route add $server $old_gw_intf
    else
    route add $server gw $old_gw_ip
    fi
    route del default
    route add default gw 10.7.0.1
    echo default route changed to 10.7.0.1

    不然ShadowVPN up后,你所有的流量都从ShadowVPN隧道走了。

    测试隧道通信是否成功:
    sudo route add -host 8.8.8.8 dev tunX (tunX是你ShadowVPN的interface)
    然后nslookup twitter.com 8.8.8.8
    如果返回的地址是无污染的IP,说明隧道已经UP了。

    OpenVPN这块,如果签发证书后接入成功,且能ping通网关地址,就没问题。

    ------再开始做流量的对接------

    我这里的ShadowVPN interface IP使用的是10.20.0.1(境外服务器),10.20.0.2(境内服务器)
    OpenVPN使用的IP段是10.200.0.0/24,请各位写iptables规则的时候替换成你们正在使用的IP段。

    1、首先先定义自定义的路由表,不然写路由条目的时候会写到主路由表,那就会导致选路错乱了。

    vim /etc/iproute2/rt_tables
    添加一行
    200 netgamesg
    然后保存,退出。
    编号是可以自己自定义的,名字也是可以自定义的,我这里为了好记所以写了这个。
    (编号不可以和系统路由表编号重复)

    2、添加静态默认路由。

    ip route add default dev tunX (你的ShadowVPN interface) table netgamesg

    这里是在netgamesg这张路由表里面添加一个默认路由,默认网关出口是shadowvpn的接口。

    3、给用户接入进来的地址打上标记,然后强制打上标记的数据使用netgamesg这张路由表。

    iptables -A PREROUTING -t mangle -s 10.200.0.0/24 -j MARK --set-mark 3
    ip rule add fwmark 3 table netgamesg

    4、使用ip rule来根据源地址来使用路由表。

    ip rule add from 10.200.0.0/24 table netgamesg

    这里是规定源地址为10.200.0.0/24的IP数据包使用netgamesg这张路由表。

    5、最后一步,设置iptables转发。

    iptables -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的ShadowVPN interface IP]

    6、刷新路由表。

    ip route flush cache

    7、添加脚本,让它开机启动自动执行即可。

    vim route.sh

    shadowvpn -c /etc/shadowvpn/client.conf -s start
    ip route add default dev tun10 table netgamesg
    ip rule add fwmark 3 table netgamesg
    ip rule add from 10.200.0.0/24 table netgamesg

    这样就大功告成了。拨入中国的服务器,你访问ip.cn会显示的是外国的IP,原理就是中国服务器无条件将你的数据转发到国外服务器了。

    这个模型里面不需要考虑MTU的问题,至少我这边做了3次是没出现因为MTU问题导致的数据不通。如果数据不通的话看看哪一步没做对。

    如果有什么地方写的不对,敬请批评指正。

    感谢@zk8802 @gamexg 的点拨。
    @hjc4869 嘿,你要的教程,我写好了。
    Supplement 1  ·  Mar 29, 2015
    感谢@rainy3636 指出文中的一个bug:

    原文中 “ iptables -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的ShadowVPN interface IP] ”

    这里少了个 -t nat,debian 下提示iptables: No chain/target/match by that name.

    因为我是直接从/etc/sysconfig/iptables里面把config拷贝出来的,所以出了点差错。对此感到十分的抱歉。

    正确命令是 这样的:

    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的ShadowVPN interface IP]

    这个命令OVZ和XEN,KVM通用。

    再次表示感谢。
    73 replies  •  2018-04-04 15:22:54 +08:00
    jasontse
    jasontse
    Mar 29, 2015 via iPad
    1
    理论上是 PPTP 的 GRE 封装比 UDP 快
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015
    2
    @jasontse 是的,但是我测试了十几个用户,都说OpenVPN的UDP封装比PPTP的速度快得多,玩游戏也是OpenVPN UDP性能更优秀。
    所以我感觉,按照实际上来比较好。
    hadoop
    hadoop
    Mar 29, 2015
    3
    感谢lz,改天试试。
    pwinner
    pwinner
    Mar 29, 2015 via Android
    4
    pptp怎么优化至今还没搞定,自己的Linode跑pptp能看网页但是速度奇慢,只有不到0.5Mbps,楼主方案是一个很不错的解决办法啊。(用Debian残念的看着你
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015
    5
    @pwinner 命令都是差不多的(认真
    命令可以翻译成不同版本的。
    pwinner
    pwinner
    Mar 29, 2015 via Android
    6
    @liuchen9586 这个我也知道啦:p
    顺便我发现国内中转好像也没什么优势嘛,自己的杭州阿里云ping我的日本linode丢包,延迟还不如自己家。。。
    hjc4869
    hjc4869
    Mar 29, 2015
    7
    感谢楼主。已收藏,等我搞到靠谱的我朝服务器后试试。
    laincat
    laincat
    Mar 29, 2015
    8
    好文,留个记号以后用。
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015
    9
    @pwinner 日本啊,我是从台湾走的=0=
    现在直连日本根本没什么优势,延迟100多,还疯狂丢包orz
    从台湾走延迟只有80ms
    zk8802
    zk8802
    Mar 29, 2015
    10
    祝贺楼主成功完成了配置!
    bugmenott
    bugmenott
    Mar 29, 2015
    11
    @pwinner 国内中转也有很多种搭配,比阿里云+linode好的也不是没有
    datou
    datou
    Mar 29, 2015
    12
    玩东南亚csgo匹配的话,办个移动宽带比啥都强

    0loss,70ms左右的延迟
    guojing
    guojing
    Mar 29, 2015
    13
    @liuchen9586 对linux不是太熟悉,可能理解错。看你配置的步骤感觉有重复:步骤2,5重复,步骤3,4重复。能说明一下吗?谢谢
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015❤️1
    14
    @guojing iptables 和ip rule要配合工作的,缺少一样都跑不起来。
    2和5真没重复,一个是NAT翻译,改变source IP的,一个是规定路由表,没routing table数据包是不知道怎么走的。
    Yien
    Yien
    Mar 29, 2015
    15
    感谢楼主分享!
    treo
    treo
    Mar 29, 2015
    16
    为啥要这么折腾,server端多开几个shadowvpn,让客户端直接运行shadowvpn不就行了
    需要墙内服务器中转的,就由墙内服务器直接转发udp包到墙外server端
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015
    17
    @treo 那你是没玩过高级策略路由特性。粗暴的端口转发方式,稍微高级点的路由特性都不支持,比如多重转接。
    welsmann
    welsmann
    Mar 29, 2015
    18
    先收藏+感谢,得空来试试
    XiaoxiaoPu
    XiaoxiaoPu
    Mar 29, 2015
    19
    步骤 3 和 4 确实重复了,只要 4 就够了。iptables 的 mark 和 ip rule 配合适合用来做不同端口走不同路由。
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015
    20
    @XiaoxiaoPu 嗯,不过既然能用而且能起到控制路由走向,就木有问题啦。
    (其实我想说我这个CentOS 6.x,3和4步骤缺一不可……不知道为啥)
    XiaoxiaoPu
    XiaoxiaoPu
    Mar 29, 2015
    21
    @liuchen9586 我自己的没用 iptables 的 mark,一点问题也没有(archlinux 大法好)
    rainy3636
    rainy3636
    Mar 29, 2015
    22
    转发不该是这个吗?
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的ShadowVPN interface IP]
    没有-t nat的话
    debian 下提示iptables: No chain/target/match by that name.
    AMST
    AMST
    Mar 29, 2015
    23
    @rainy3636
    @liuchen9586
    而且非ovz下应该是iptables -t nat -A POSTROUTING -s [源地址段] -o tunX (你的ShadowVPN interface) -j MASQUERADE
    AMST
    AMST
    Mar 29, 2015
    24
    @liuchen9586 特别感谢,周五还在发帖询问相关方案
    rainy3636
    rainy3636
    Mar 29, 2015
    25
    @Leafove
    这2种效果一样的

    @liuchen9586
    shadowvpn貌似没法在配置文件中指定dns?
    liuchen9586
    liuchen9586
    OP
    Mar 29, 2015
    26
    @rainy3636 额,抱歉,好像是少了个-t nat
    我是直接在/etc/sysconfig/iptables里面拷贝的

    @Leafove 非OVZ的VPS用我那个方法也是可以的,我KVM的就是这些命令。
    Sagiri
    Sagiri
    Mar 29, 2015
    27
    收藏 感谢分享
    free1
    free1
    Mar 29, 2015 via iPhone
    28
    感谢分享,标记一下~
    phoenixlzx
    phoenixlzx
    Mar 29, 2015 via Android
    29
    我一直是 chnroutes + ip rule,国内节点正好当BGP加速解决跨运营商访问慢
    hzqim
    hzqim
    Mar 29, 2015
    30
    感觉比 shadowsocks 麻烦一些,请问 openvpn 比 shadowsocks 胜在哪里?
    nlzy
    nlzy
    Mar 30, 2015
    31
    感谢分享,不过这好麻烦,,,我打CSGO匹配用奇游80ping,已经很满足了=A=
    yy1984
    yy1984
    Mar 30, 2015
    32
    我感觉不需要openvpn,只要shadowvpn一个就足够了。
    我目前就是用shadowvpn+ipset+dnsmasq-full+gfwlist智能翻墙,唯一的麻烦在于shadowvpn与MWAN3多拨不兼容。
    liuchen9586
    liuchen9586
    OP
    Mar 30, 2015
    33
    @yy1984 我这个不是翻墙的……我这个是策略路由,而且并不是在家用路由器上面做的QAQ
    lhuiwu6
    lhuiwu6
    Mar 30, 2015
    34
    犀利的楼主。有时间再瞧瞧。
    yy1984
    yy1984
    Mar 30, 2015
    35
    @liuchen9586 智能翻墙就是用策略路由实现的,也是iptables设置mask,然后ip rule分流。
    家用路由器上的openwrt也是linux,本质上跟你的方法没区别。
    所以我觉得openvpn或shadowvpn有点多余,留一个就行
    liuchen9586
    liuchen9586
    OP
    Mar 30, 2015
    36
    @yy1984 我服务器是放在公网的,根本不是家用路由器啊
    给人玩东南亚游戏加速用的
    loca1h0st
    loca1h0st
    Apr 6, 2015
    37
    @liuchen9586
    我按照你的教程确实已经配置成功了,非常感谢。
    但现在有一个想法,拉入chnroutes在整个网络拓扑内。
    我尝试在国内的跳板机上配置根据目的地地址的ip rule策略,达到国内的流量走国内的跳板机的目的。
    但是现在配置完成之后国内的地址就无法访问了,我估计是因为iptables把我openvpn的地址转成shadowvpn的了?
    想问问楼主你对这个问题有没有什么好的看法?
    liuchen9586
    liuchen9586
    OP
    Apr 6, 2015
    38
    @loca1h0st chnroute给的下一跳地址是eth0?如果不是那就没法访问的。
    表要打入对应编号的路由表内,不然也不行
    loca1h0st
    loca1h0st
    Apr 6, 2015 via iPad
    39
    @liuchen9586 我是写的openvpn的网卡as0t1,如果写eth0不会因为nat的原因数据包无法转发么?
    loca1h0st
    loca1h0st
    Apr 6, 2015 via iPad
    40
    @liuchen9586 你好,我刚刚尝试了如下操作。
    添加自定义路由表china
    然后设置ip route add default dev eth0 table china
    ip rule from openvpn to chnroutes table china
    然后测试访问国内的网站发现Chrome的提示是因防火墙或代理错误无法访问。

    这个是不是因为走国内的线路并没有对数据包进行NAT抓换造成的?
    liuchen9586
    liuchen9586
    OP
    Apr 6, 2015
    41
    @loca1h0st chnroute下一跳写物理网卡出接口。
    loca1h0st
    loca1h0st
    Apr 7, 2015
    42
    @liuchen9586 物理网卡是eth0...
    liuchen9586
    liuchen9586
    OP
    Apr 7, 2015
    43
    @loca1h0st 知道,Chnroute下一跳写eth0,default gw写ShadowVPN的interface
    loca1h0st
    loca1h0st
    Apr 7, 2015
    44
    @liuchen9586 不是特别懂这个意思。。
    default gw是指ip route add default dev tun0?
    ip rule抓取的流量只能匹配自定义路由表呀
    liuchen9586
    liuchen9586
    OP
    Apr 7, 2015
    45
    @loca1h0st ip rule抓的流量是让它强制使用这个路由表,真正控制数据包走向还是靠路由表里面的路由条目。
    default gw就是你写的这个。
    chnroute下一跳写eth0就是指明它直接走物理网卡。
    然后补上一条NAT语句:
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的eth0 IP]
    NAT Translation只有在数据包到达接口的时候才会触发。
    kacong
    kacong
    Apr 7, 2015
    46
    终极解决方案之一,只要出国网络还通,就有希望ok,谢谢。
    loca1h0st
    loca1h0st
    Apr 7, 2015
    47
    @liuchen9586 刚刚测试了下还是不行。。
    默认情况:
    ip route add default dev tun0 table vpn
    ip rule add from openvpn table vpn
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的tun0 IP]

    chnroutes
    ip route add default dev eth0 table china
    ip rule add from openvpn to chnroutes table china
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的eth0 IP]

    ip route flush cache

    访问国内的网站还是出现网络防火墙或代理错误
    loca1h0st
    loca1h0st
    Apr 7, 2015
    48
    @liuchen9586 按如上的配置完成之后本地访问的同时对网卡进行抓包。
    出现的是10.7.0.2(shadowvpn的interface ip)发出的arp报文,报文内容为ARP, Request who-has a.b.c.d tell 10.7.0.2, length 28
    liuchen9586
    liuchen9586
    OP
    Apr 7, 2015
    49
    @loca1h0st chnroute的路由条目放到vpn路由表内
    loca1h0st
    loca1h0st
    Apr 7, 2015
    50
    @liuchen9586 已经解决了,非常谢谢指导。

    记录下解决方案,也许会对别人有帮助

    1.把两条SNAT的命令修改成如下:
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -o tun[x] -j SNAT --to-source [你的tun0 IP]
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -o eth[x] -j SNAT --to-source [你的eth0 IP]

    然后再抓包发现还是有ARP报文,但是IP地址从10.7.0.2变成了eth0的IP地址。
    这里是感到奇怪的一点,明明有子网掩码的计算了,不应该出现ARP,应该就去找网关地址了。
    2.然后修改自定义路由表的默认网关信息。
    由ip route add default dev eth0 table china修改为:
    ip route add default via [gw_ip] dev eth0 table china

    ip route flush cache之后达到目标。。。
    KCheshireCat
    KCheshireCat
    Apr 27, 2015❤️1
    51
    其实还有个隧道选项 走UDP的静态l2tpV3,比较新的内核直接就支持。
    然后3.18内核开始还有个foo over udp的新静态隧道。
    UDP的好处是可以穿ISP的NAT。
    1nt
    1nt
    May 22, 2015
    52
    @liuchen9586

    想请教一下楼主用的境内服务器是哪家的?
    我试过阿里云的杭州和深圳节点,出国线路都好慢,
    连 Krypt SGP 只能跑到 10 多 Mbps 的带宽呢。
    liuchen9586
    liuchen9586
    OP
    May 22, 2015❤️1
    53
    @1nt 我用的是Ustack,30Mbps能跑到28Mbps,还可以
    g552656
    g552656
    Jun 8, 2015
    54
    @liuchen9586 愿意有偿咨询几个问题,可否给个联系方式?
    liuchen9586
    liuchen9586
    OP
    Jun 8, 2015
    55
    @g552656 其实我对linux不太熟悉
    你可以发邮件到我ID@google邮箱
    NickLiulol
    NickLiulol
    Jul 3, 2015
    56
    @liuchen9586 太感谢了,AZURE北京+日本某机房成功配置,但是北京机房ping还是丢包,所以买了个softlayer香港的机房试试
    NickLiulol
    NickLiulol
    Jul 3, 2015
    57

    IP是pmang黑色沙漠游戏服务器,国内是ping不通的,现在是武汉电信+香港CN2+日本ConoHa,原本ConoHa机房是丢包之王不用看,其他的KDDI/NTT/IIJ机房半夜不丢包稳定下来也70左右。
    另外我不知道为什么用OPENVPN会莫名其妙200+ms,以为是干扰,但是XOR PATCH也没有用,就索性改了PPTP+shadowvpn的组合,把MTU改成1396,之后就成功了。
    多谢楼主,简直是完美解决我玩日服的难题。
    liuchen9586
    liuchen9586
    OP
    Jul 4, 2015
    58
    @NickLiulol 我现在都已经淘汰了这种双重NAT的方案了……直接在内网跑个BGP路由,添加删除服务器更方便,而且还能自动愈合自动切换
    NickLiulol
    NickLiulol
    Jul 4, 2015 via iPhone
    59
    @liuchen9586 这应该就很接近/就是很多网游加速器的做法了吧,
    liuchen9586
    liuchen9586
    OP
    Jul 4, 2015
    60
    @NickLiulol 这个嘛,就不知道了
    因为BGP方便,没双重NAT那么死板,加一台服务器/一个网段只要一条命令就够了
    zixia
    zixia
    Jul 20, 2015
    61
    @NickLiulol 我最近一直在找 XOR PATCH ,可不可以帮忙推荐一些资料?
    NickLiulol
    NickLiulol
    Jul 21, 2015
    62
    macdovell
    macdovell
    Aug 25, 2015
    63
    你好,我想请问下,除了 shadowvpn ,中间的桥接过程还有别的替代方案吗?
    liuchen9586
    liuchen9586
    OP
    Aug 25, 2015
    64
    @macdovell openvpn-statickey l2tpv3 都行
    macdovell
    macdovell
    Aug 26, 2015
    65
    @liuchen9586 楼主你好,我照着你的方案配置了一下,但是最后一步的 SNAT 中始终没有包,请问这有可能是哪里的问题呢
    liuchen9586
    liuchen9586
    OP
    Aug 26, 2015
    66
    @macdovell 没包可能是你 snat 网卡 IP 写错了
    macdovell
    macdovell
    Aug 26, 2015
    67
    @liuchen9586 嗯, ip 没错,包都走到了 MASQUERADE 去了,是之前加的规则,我删除后, SNAT 中有包,但还是没网络,准备下班了去抓包看
    ultimate010
    ultimate010
    Sep 11, 2015
    68
    按照你的方法 work 了,请教有没有方法让目的地是国内的 ip ,直接在国内 server 上转发,不跑去香港。
    liuchen9586
    liuchen9586
    OP
    Sep 12, 2015❤️1
    69
    @ultimate010 chnroute
    ultimate010
    ultimate010
    Sep 12, 2015
    70
    @liuchen9586 在国内的 vpn 服务器上设置 chnroute ?我的目的是客户端不需要任何设置,国内流量从国内 vpn 服务器走,国外从国外服务器走,有好的实现吗?话说我用 shadowvpn ,因为基于 udp ,阿里云到香港跑满了才 400k ,而 tcp 的直接 http 测试,可以达到 7mb ,中转了一路不如直接连 tcp 快。
    lc19920108
    lc19920108
    Jun 8, 2017
    71
    楼主你好,请问可以一台国内服务器同时中转多个国外服务器么,像现在的各种加速器一样
    liuchen9586
    liuchen9586
    OP
    Jun 9, 2017
    72
    @lc19920108 自己写路由表,根据源地址来走不同策略表或者根据目标地址走不同隧道。
    Damaidaner
    Damaidaner
    Apr 4, 2018
    73
    收藏感谢!!
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1647 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 94ms · UTC 00:29 · PVG 08:29 · LAX 16:29 · JFK 19:29
    ♥ Do have faith in what you're doing.