V2EX 首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

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

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

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

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

你们有遇到这样的情况吗?
    25
kaiqiz89   2013-02-01 08:42:47 via Android
@darrenlee 求介绍,哪种比较快?
    26
shinwood   2013-02-01 09:08:17
楼主dropbox 链接中的样式不错,是原创还是?
DigitalOcean
Linode
关于   ·   FAQ   ·   我们的愿景   ·   IP 查询   ·   工作空间   ·   广告投放   ·   博客   ·   上网首页   ·   391 人在线   最高记录 631   ·  
创意工作者们的社区
Lovingly made by OLIVIDA
VERSION: 3.2.2 · 115ms · UTC 12:22 · PVG 20:22 · LAX 05:22 · JFK 08:22
♥ Do have faith in what you're doing.