V2EX 首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
AmazeUI
百姓网 App SDK
拉勾网
Coding.NET
100offer.com
BosonNLP
UnitedStack
学无止境
LeetCode
推荐书目
黑客与画家
REWORK 简体中文版
REWORK 精装原版
深入浅出设计模式 Head First Design Patterns
代码之美 Beautiful Code
数据之美 Beautiful Data
信息论、编码与密码学
Free as in Freedom
设计原本
精通正则表达式
JobDeer.com 竞鹿人才竞拍
V2EX  ›  程序员

使用 Obfsproxy+OpenVPN+Raspberry Pi 搭建无缝翻墙环境,插上一个RPi,全网即可翻墙

  •  
  •   blankwonder · 2013-01-09 13:14:47 +08:00 · 10929 次点击
    这是一个创建于 712 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有翻墙条件的童鞋可以到这里围观: https://dl.dropbox.com/u/6129727/obfsproxy%2Bopenvpn.html

    前言
    不久前,GFW升级导致OpenVPN、SSH Tunnel等一系列老牌翻墙方式纷纷阵亡,现在的翻墙手段已经开始从单纯的加密向流量混淆发展,这里介绍一种利用obfsproxy+OpenVPN进行翻墙的方式,目前情况下相当稳定快速。

    obfsproxy 是 Tor Project 的一个附属项目,采用流量混淆的方式专门用于突破互联网封锁。对用户的表现形式是一个TCP端口转发隧道,和 ssh -L 的功能完全一致。
    除了介绍obfsproxy+OpenVPN翻墙以外,本文还介绍了如何使用 Raspberry Pi 搭设翻墙网关实现无缝翻墙的方法。下文中B和C部分属于平行关系,任选其一配置即可。

    有任何建议和问题欢迎在Twitter上和我讨论: @blankwonder

    本文目标读者为有一定Linux和网络知识基础的用户,并没有把所有命令全部傻瓜话的列出,如果是小白请先准备技术支持老师一枚(别找我啊……)

    A. 服务器端配置
    OpenVPN配置

    首先,我们需要先安装配置OpenVPN,如果你不需要IPv6的话,直接用包管理安装就行。否则请到官网下载2.3版本的源码自行编译安装。(目前最新版本是2.3 RC2)

    Debian编译OpenVPN所需要的包有libssl-dev, libpam0g-dev, liblzo2-dev

    注:若是自行编译的OpenVPN,会缺少easy-rsa和init.d脚本,easy-rsa可以从OpenVPN官方的Github获得。init.d 脚本可以从各发行版的源码获得:

    Debian/Ubuntu 用户:下载这个文件包 http://ftp.de.debian.org/debian/pool/main/o/openvpn/openvpn_2.3~rc1-1.debian.tar.gz,解压后找到openvpn.init.d文件,将其放到/etc/init.d/openvpn
    Gentoo 用户: sudo wget http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-misc/openvpn/files/openvpn-2.1.init -O /etc/init.d/openvpn
    如果你没有修改安装prefix的话,OpenVPN会被安装到/usr/local/sbin/openvpn上,记得修改init.d脚本的相应内容。
    接下来,按照标准的OpenVPN部署流程,生成各种密钥和证书(CA, server, client)。Linode 的官方文档写的非常好,这里不再阐述。

    我使用的服务端配置(/etc/openvpn/openvpn.conf)如下:

    local 127.0.0.1
    port 40059
    proto tcp
    dev tun
    ca ca.crt
    cert server.crt
    key server.key
    dh dh1024.pem
    server 172.16.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt
    duplicate-cn
    keepalive 10 120
    comp-lzo
    persist-key
    persist-tun
    status openvpn-status.log
    log-append /var/log/openvpn.log
    verb 3
    mute 10
    由于我们需要使用obfsproxy进行二次混淆,所以这里让OpenVPN监听在127.0.0.1上。市面上的路由器默认的IPv4子网一般是192.168.X.X或者10.X.X.X,这里为了避免和原有网络冲突,我选择了172.16.0.0/24作为VPN的子网。

    接下来设置iptables进行NAT转换,这里省略了Linode文档中的安全部分(DROP),需要可自行补上。

    sudo iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE
    为了保证服务器重启后自动配置iptables,请需要将这条命令加入启动脚本

    Debian/Ubuntu 用户:启动脚本的路径为 /etc/rc.local
    Gentoo 用户:需要在/etc/local.d目录中创建一个后缀为.start的文件(如openvpn_iptables.start),将命令写在里面,同时记得使用chmod a+x。
    接下来启动内核的IPv4转发

    sudo sysctl -w net.ipv4.ip_forward=1
    为了保证重启后不需要人工干预,在/etc/sysctl.conf中加入net.ipv4.ip_forward=1,这样重新启动后就不再需要sysctl -w了。

    现在可以把OpenVPN跑起来了,命令如下

    sudo /etc/init.d/openvpn start
    obfsproxy配置

    现在开始编译安装obfsproxy,官方指导文档在这 https://www.torproject.org/projects/obfsproxy-instructions.html.en

    注:Gentoo用户在emerge libevent时请注意添加USE标记ssl。
    Debian/Ubuntu用户可以直接使用包管理安装

    sudo apt-get install obfsproxy
    安装配置完毕后,启动obfsproxy,命令如下:

    obfsproxy obfs2 --dest=127.0.0.1:40059 server 0.0.0.0:9132
    请记得使用screen,nohup或daemon的方式运行obfsproxy。daemon当然最好,我比较懒就直接跑在screen里面了。

    至此,服务端配置完毕。

    B. 客户端配置
    obfsproxy配置

    首先编译安装obfsproxy,文档同上。

    Mac用户可以用使用homebrew安装,请参照这里 https://github.com/mtigas/homebrew-tor/blob/master/README.md
    由于我们需要将所有流量重定向到OpenVPN,而由于使用了obfsproxy,OpenVPN不知道服务器IP是多少没办法对到OpenVPN服务器的流量进行特殊处理,所以我们需要手动将到服务器的路由固定下来,假设你的服务器IP为12.34.56.78,当前网络的网关地址是192.168.1.1:(路由修改的命令请根据自己的操作系统自行调整,此处以Mac OS X为例)

    sudo route add 12.34.56.78 192.168.1.1
    完成了之后,开始运行obfsproxy

    obfsproxy obfs2 --dest=12.34.56.78:9132 client 127.0.0.1:50443
    如果是Mac用户,可以使用我的脚本,稍微简便一些(需要sudo)

    #!/bin/bash

    SERVER_IP="12.34.56.78"
    GATEWAY=`netstat -nr | grep '^default' | grep -v 'tun' | sed 's/default *\([0-9\.]*\) .*/\1/'`

    /sbin/route add $SERVER_IP $GATEWAY
    /usr/local/bin/obfsproxy obfs2 --dest=${SERVER_IP}:9132 client 127.0.0.1:50443
    # Below line won't be excuted until obfsproxy exit
    /sbin/route delete $SERVER_IP $GATEWAY
    OpenVPN配置

    接下来选择你喜爱的OpenVPN客户端软件进行连接就可以了,我的配置式样例如下:

    remote 127.0.0.1 50443 tcp-client
    pull
    tls-client
    ns-cert-type server
    persist-key
    ca ca.crt
    redirect-gateway def1
    nobind
    persist-tun
    cert cert.crt
    comp-lzo adaptive
    dev tun
    key key.key
    dhcp-option DNS 8.8.8.8
    resolv-retry infinite
    log-append /var/log/openvpn.log
    好的,现在你又可以尽情享受OpenVPN的全局翻墙了,如有需要可以结合 chnroutes 区分国内外流量进行选择性翻墙。

    C. Raspberry Pi 翻墙网关配置
    整个网络结构图如下

    https://dl.dropbox.com/u/6129727/Graph.png

    使用 Raspberry Pi 作为翻墙网关有很多好处,一是不用再每次都手动连接VPN,二是一次配置所有设备通用,更奇妙的是结合chnroutes使用,客户端和 RPi 之间会自动使用ICMP Redirect修改客户端路由,下次再访问同一国内IP就不会再经过 RPi 了。

    警告:修改网络配置极有可能使得RPi无法联网,请在保证可以直接控制RPi的情况下操作。

    Raspberry Pi 使用 Debian wheezy 作为操作系统,其他操作系统也大同小异。

    首先,在RPi上安装OpenVPN和obfsproxy,同样,如果需要IPv6还是得自行编译安装OpenVPN。编译方法参照之前服务器部署部分,obfsproxy可以直接使用包管理安装。

    同样,我们还是需要启动内核的IPv4转发

    sudo sysctl -w net.ipv4.ip_forward=1
    记得同时修改/etc/sysctl.conf保证重启也有效。

    接下来我们需要让RPi的IP固定下来,修改/etc/network/interfaces文件,将eth0的相关部分改成这样,请参照自己的网络情况修改

    auto eth0
    iface eth0 inet static
    address 192.168.1.2
    netmask 255.255.255.0
    gateway 192.168.1.1
    dns-nameservers 8.8.8.8
    为了让interfaces文件可以设置DNS服务器,也就是让dns-nameservers 8.8.8.8这句话生效,我们需要再额外安装一个包

    sudo apt-get install resolvconf
    使用以下命令使得配置生效,直接重启也行

    sudo /etc/init.d/networking restart
    接下来,使用 chnroute 生成路由脚本,(这步可以在电脑上执行,然后将生成好的文件拷贝过来)

    python chnroutes.py -p linux
    得到两个文件ip-pre-up和ip-down,其中ip-pre-up开头如下,

    /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/vpn_oldgw ]; then
    echo $OLDGW > /tmp/vpn_oldgw
    fi

    route add -net 1.0.1.0 netmask 255.255.255.0 gw $OLDGW
    ...
    其中获得网关的命令我自己测试发现有问题不成功,修改为这样

    OLDGW=`ip route show | grep eth0 | grep '^default' | sed -e 's/default via \([^ ]\+\) dev eth0/\1/'`
    动态获得网关IP的方法有时会不太可靠,如果网络情况不常变化,可以考虑直接把网关IP写进去

    OLDGW="192.168.1.1"
    在RPi上执行sudo bash ./ip-pre-up,将国内IP的路由固定下来(没有必要等到OpenVPN链接后再固定,也不需要每次断开后就删除,除非网关地址变了,否则一直放着就好)。注意这个脚本可能要运行一段时间才能完成。

    和客户端部分一样,连接之前我们也需要先将到服务器的路由固定下来,一体化脚本如下(记得修改服务器IP)

    #!/bin/bash

    SERVER_IP="12.34.56.78"
    GATEWAY=`ip route show | grep eth0 | grep '^default' | sed -e 's/default via \([^ ]\+\) dev eth0/\1/'`

    /sbin/route add -host $SERVER_IP gw $GATEWAY

    /usr/local/bin/obfsproxy obfs2 --dest=${SERVER_IP}:9132 client 0.0.0.0:50443

    #/sbin/route delete -host $SERVER_IP gw $GATEWAY
    使用screen,nohup或daemon的方式将这个脚本运行起来(需要root权限),就可以开始进行OpenVPN的配置了

    将所需要的证书和密钥放到/etc/openvpn/目录下。配置文件和上文B部分一致,命名为openvpn.conf。启动openvpn:

    sudo /etc/init.d/openvpn start
    可以查看一下OpenVPN的日志,看看链接是否成功

    sudo tail /var/log/openvpn.log
    当看到“Initialization Sequence Completed”后,就表示我们已经基本上大功告成了。接下来测试一下。

    [root@blankwonder-rpi]openvpn # ping twitter.com
    PING twitter.com (199.59.149.230) 56(84) bytes of data.
    64 bytes from www4.twitter.com (199.59.149.230): icmp_req=1 ttl=247 time=631 ms
    64 bytes from www4.twitter.com (199.59.149.230): icmp_req=2 ttl=247 time=328 ms
    64 bytes from www4.twitter.com (199.59.149.230): icmp_req=3 ttl=247 time=477 ms
    64 bytes from www4.twitter.com (199.59.149.230): icmp_req=4 ttl=247 time=326 ms
    ^C
    --- twitter.com ping statistics ---
    5 packets transmitted, 4 received, 20% packet loss, time 4025ms
    rtt min/avg/max/mdev = 326.018/440.823/631.233/125.840 ms
    OK,RPi目前已处于翻墙状态了。接下来,让我们的设备也能翻墙。

    在RPi中启动iptables的NAT转换

    sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
    将需要翻墙的设备的IP地址设为手动,将网关地址设为RPi的地址(本文中为192.168.1.2),DNS服务器地址设为8.8.8.8,打开浏览器试一下,你是不是已经畅通无阻了?

    接下来为了使得以后使用不用再手动修改路由,到路由器上修改DHCP设置,将网关地址设置为RPi的地址,DNS改为8.8.8.8。如果你的路由不支持手动设置DHCP路由地址(比如我的Time Capsule……),那就把他的DHCP直接关了,在RPi上直接自建一个DHCP服务器(比如dnsmasq)。

    同样的原理我们还可以利用RPi为子网下所有设备提供原生的IPv6支持。但配置略微有些繁琐,请待下回分解……

    Version 1
    27 回复  |  直到 2013-04-21 21:53:42 +08:00
        1
    shuni9   2013-01-09 13:52:41 +08:00
    感谢分享, 最近为了稳定翻墙的耗费了无数心魂, 至今用着自己写的检测到block 就在几个vpn中间跳来跳去的脚本, 今晚试试你的方法 .
        2
    tristones   2013-01-09 15:08:56 +08:00
    openvpn 部分是否能用udp协议?
        3
    blankwonder   2013-01-09 15:15:35 +08:00
    @tristones 不能,obfsproxy只支持TCP
        4
    tristones   2013-01-09 15:16:59 +08:00
    哦,这样的话.速度总是个缺陷了...
        5
    zxsky1   2013-01-09 15:17:01 +08:00
    感谢分享。
        6
    thedevil5032   2013-01-09 15:20:41 +08:00
    好长. 没有代码高亮看着会晕的..
        7
    blankwonder   2013-01-09 15:24:58 +08:00   ♥ 1
    @tristones 我自己使用表示还算都很流程,直接ping的话延迟为90ms左右,加了这一套后变为170ms左右,下载速度可达1MB/s
        8
    blankwonder   2013-01-09 15:25:29 +08:00
    @thedevil5032 Dropbox版本有样式……
        9
    kaiqiz89   2013-01-09 15:32:21 +08:00 via Android
    马克,有时间折腾一下
        10
    goxofy   2013-01-09 15:56:22 +08:00
    不知道为啥,不咋喜欢vpn,我觉得是我自己的硬伤。。
        11
    darrenlee   2013-01-09 17:37:34 +08:00
    除了obfsproxy还有好几种TCP混淆的实现,,,,有速度飞快的
        12
    kavana   2013-01-09 17:40:34 +08:00
    马克,有时间折腾一下人
    看戏
        13
    adspe   2013-01-09 18:24:57 +08:00
    obfsproxy据说会降低速度。楼主速度受影响么。
        14
    blankwonder   2013-01-09 18:34:15 +08:00
    @adspe 见7楼的回复
        15
    ericFork   2013-01-09 19:55:54 +08:00
    @darrenlee 哦?求分享 XD
        16
    bwlinux   2013-01-10 00:01:27 +08:00   ♥ 1
    client端,应该加上obfsproxy client。应该是
    vpn client --> obfsproxy @ client --> obfsproxy server --> vpn server
    LZ的配置缺client obfsproxy。需要保护的部分是vpn client -->(需要保护) obfsproxy server, 这个部分不安全,受到干扰,LZ是直接的,obfsproxy转发vpn,没有保护,如果用vpn client -->(安全) obfsproxy @ client --> (不安全,所以用obfs保护)obfsproxy server-->(不受干扰,安全) vpn server --> (不受干扰)website
        17
    blankwonder   2013-01-10 11:08:56 +08:00
    @bwlinux 不好意思没太看懂…………我现在就是vpn client --> obfsproxy @ client --> obfsproxy @ server --> vpn server啊
        18
    jackyz   2013-01-10 11:30:01 +08:00
    mark,看来要入 raspberry pi 而不是 super router 。
        19
    yiyangde7   2013-01-10 17:00:43 +08:00
    我感觉死的不是爬墙方式而是服务器ip,g=ae用着还行
        20
    tingxueren   2013-01-10 17:13:58 +08:00
    暂时在自己的vps上弄好了,但是发现速度好慢啊,基本无法看youtube
        21
    bwlinux   2013-01-11 00:01:15 +08:00
    @blankwonder 是我看错了。Sorry。

    好象obfsproxy 可以直接用vpn client的conf来启动。不需要手工启动。
        22
    iwinux   2013-01-11 02:06:34 +08:00
    谢谢楼主分享,第一次看到 obfsproxy 的实际应用,看来这条路是可行的。

    但是我已经把服务端的 VPN 配置全删了,还换了个不支持 tap/tun 的 VPS (哭
        23
    lbright   2013-01-31 19:39:55 +08:00
    @darrenlee 请问还有哪个比较快的?
        24
    doskoi   2013-01-31 20:03:08 +08:00
    @blankwonder 我用obfsproxy 睡一觉就开始超高延时,比如10000. 用静态密钥的方法 睡一觉就开始丢包

    你们有遇到这样的情况吗?
        25
    kaiqiz89   2013-02-01 08:42:47 +08:00 via Android
    @darrenlee 求介绍,哪种比较快?
        26
    shinwood   2013-02-01 09:08:17 +08:00
    楼主dropbox 链接中的样式不错,是原创还是?
        27
    gissimo   53 天前
    @doskoi 我静态密钥 包倒是不丢,你是哪家vps?
    DigitalOcean
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   IP 查询   ·   工作空间   ·   广告投放   ·   博客   ·   上网首页   ·   897 人在线   最高记录 1065   ·  
    创意工作者们的社区
    Lovingly made by OLIVIDA
    VERSION: 3.5.6.1 · 39ms · UTC 01:29 · PVG 09:29 · LAX 17:29 · JFK 20:29
    ♥ Do have faith in what you're doing.