首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
V2EX  ›  分享创造

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

  •  6
     
  •   liuchen9586 · 2015-03-29 09:55:37 +08:00 · 19074 次点击
    这是一个创建于 1576 天前的主题,其中的信息可能已经有所发展或是发生改变。
    实验是我在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 嘿,你要的教程,我写好了。
    第 1 条附言  ·  2015-03-29 22:03:52 +08:00
    感谢@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 回复  |  直到 2018-04-04 15:22:54 +08:00
        1
    jasontse   2015-03-29 09:58:29 +08:00 via iPad
    理论上是 PPTP 的 GRE 封装比 UDP 快
        2
    liuchen9586   2015-03-29 10:00:03 +08:00
    @jasontse 是的,但是我测试了十几个用户,都说OpenVPN的UDP封装比PPTP的速度快得多,玩游戏也是OpenVPN UDP性能更优秀。
    所以我感觉,按照实际上来比较好。
        3
    hadoop   2015-03-29 10:09:25 +08:00
    感谢lz,改天试试。
        4
    pwinner   2015-03-29 10:54:29 +08:00 via Android
    pptp怎么优化至今还没搞定,自己的Linode跑pptp能看网页但是速度奇慢,只有不到0.5Mbps,楼主方案是一个很不错的解决办法啊。(用Debian残念的看着你
        5
    liuchen9586   2015-03-29 10:57:42 +08:00
    @pwinner 命令都是差不多的(认真
    命令可以翻译成不同版本的。
        6
    pwinner   2015-03-29 10:59:58 +08:00 via Android
    @liuchen9586 这个我也知道啦:p
    顺便我发现国内中转好像也没什么优势嘛,自己的杭州阿里云ping我的日本linode丢包,延迟还不如自己家。。。
        7
    hjc4869   2015-03-29 11:08:14 +08:00
    感谢楼主。已收藏,等我搞到靠谱的我朝服务器后试试。
        8
    laincat   2015-03-29 11:24:26 +08:00
    好文,留个记号以后用。
        9
    liuchen9586   2015-03-29 12:07:18 +08:00
    @pwinner 日本啊,我是从台湾走的=0=
    现在直连日本根本没什么优势,延迟100多,还疯狂丢包orz
    从台湾走延迟只有80ms
        10
    zk8802   2015-03-29 12:11:50 +08:00
    祝贺楼主成功完成了配置!
        11
    bugmenott   2015-03-29 12:20:48 +08:00
    @pwinner 国内中转也有很多种搭配,比阿里云+linode好的也不是没有
        12
    datou   2015-03-29 12:33:31 +08:00
    玩东南亚csgo匹配的话,办个移动宽带比啥都强

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

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

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

    这个是不是因为走国内的线路并没有对数据包进行NAT抓换造成的?
        41
    liuchen9586   2015-04-06 23:51:13 +08:00
    @loca1h0st chnroute下一跳写物理网卡出接口。
        42
    loca1h0st   2015-04-07 08:33:33 +08:00
    @liuchen9586 物理网卡是eth0...
        43
    liuchen9586   2015-04-07 09:53:18 +08:00
    @loca1h0st 知道,Chnroute下一跳写eth0,default gw写ShadowVPN的interface
        44
    loca1h0st   2015-04-07 09:56:58 +08:00
    @liuchen9586 不是特别懂这个意思。。
    default gw是指ip route add default dev tun0?
    ip rule抓取的流量只能匹配自定义路由表呀
        45
    liuchen9586   2015-04-07 10:00:01 +08:00
    @loca1h0st ip rule抓的流量是让它强制使用这个路由表,真正控制数据包走向还是靠路由表里面的路由条目。
    default gw就是你写的这个。
    chnroute下一跳写eth0就是指明它直接走物理网卡。
    然后补上一条NAT语句:
    iptables -t nat -A POSTROUTING -s [你的openvpn源地址段] -j SNAT --to-source [你的eth0 IP]
    NAT Translation只有在数据包到达接口的时候才会触发。
        46
    kacong   2015-04-07 11:36:56 +08:00
    终极解决方案之一,只要出国网络还通,就有希望ok,谢谢。
        47
    loca1h0st   2015-04-07 19:49:43 +08:00
    @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

    访问国内的网站还是出现网络防火墙或代理错误
        48
    loca1h0st   2015-04-07 19:58:20 +08:00
    @liuchen9586 按如上的配置完成之后本地访问的同时对网卡进行抓包。
    出现的是10.7.0.2(shadowvpn的interface ip)发出的arp报文,报文内容为ARP, Request who-has a.b.c.d tell 10.7.0.2, length 28
        49
    liuchen9586   2015-04-07 21:51:05 +08:00
    @loca1h0st chnroute的路由条目放到vpn路由表内
        50
    loca1h0st   2015-04-07 21:56:01 +08:00
    @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之后达到目标。。。
        51
    KCheshireCat   2015-04-27 10:55:26 +08:00   ♥ 1
    其实还有个隧道选项 走UDP的静态l2tpV3,比较新的内核直接就支持。
    然后3.18内核开始还有个foo over udp的新静态隧道。
    UDP的好处是可以穿ISP的NAT。
        52
    1nt   2015-05-22 11:45:58 +08:00
    @liuchen9586

    想请教一下楼主用的境内服务器是哪家的?
    我试过阿里云的杭州和深圳节点,出国线路都好慢,
    连 Krypt SGP 只能跑到 10 多 Mbps 的带宽呢。
        53
    liuchen9586   2015-05-22 13:38:54 +08:00   ♥ 1
    @1nt 我用的是Ustack,30Mbps能跑到28Mbps,还可以
        54
    g552656   2015-06-08 16:10:55 +08:00
    @liuchen9586 愿意有偿咨询几个问题,可否给个联系方式?
        55
    liuchen9586   2015-06-08 17:01:21 +08:00
    @g552656 其实我对linux不太熟悉
    你可以发邮件到我[email protected]邮箱
        56
    NickLiulol   2015-07-03 00:04:33 +08:00
    @liuchen9586 太感谢了,AZURE北京+日本某机房成功配置,但是北京机房ping还是丢包,所以买了个softlayer香港的机房试试
        57
    NickLiulol   2015-07-03 23:41:39 +08:00

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