Arthor: Archean Zhang
Email: zephyr422@gmail.com
Version: 1.0.1
Date: 2013/8/16
长期被GFW困扰, 我终于忍不住动手了: 把家里的Raspberry Pi和与自由世界的主机建立OpenVPN over Stunnel的链路, 根据大中华3000条路由来匹配, 国外网站自动走OpenVPN出去以实现翻墙.
以下文章是基于一台Linux服务器(CentOS 6.4)撰写的, 将下面Router
的换成Raspberry Pi也一样.
1
. 准备硬件:
1台位于自由世界的Linux服务器 (Server)
1台位于本地的Linux服务器 (Router)
客户端 (Client)
软件:
拓扑图:
2
. Server端配置安装好Linux系统后(Red hat或CentOS), 同步服务器时间(非常重要):
2.1
OpenVPN下载安装OpenVPN, 生成服务器端证书, OpenVPN依赖lzo, 需要一同安装:
1 2 # yum install lzo openvpn
服务器端配置文件/etc/openvpn/server.conf
, 范例及说明如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 local 127.0.0.1 #监听本地接口 port 4443 #监听端口 proto tcp #协议 dev tap ca /etc/openvpn/keys/ca.crt #证书 cert /etc/openvpn/keys/server.crt #证书 dh /etc/openvpn/keys/dh1024.pem #证书 server 172.31.189.0 255.255.255.0 #网段 client-to-client duplicate-cn keepalive 10 120 comp-lzo persist-key persist-tun status openvpn-status.log #状态日志 log-append openvpn.log #执行日志 verb 3
启动openvpn:
1 # openvpn --config /etc/openvpn/server.conf --deamon
观察日志, 如果出现“Initialization Sequence Completed”
则代表启动成功.
2.2
StunnelOpenvpn的Server端只监控本地接口, 就是为了用Stunnel将流量加密, 在Local端安全的链接, 达到加密, 混淆流量的作用, 以绕开GFW的监控.
下载安装stunnel
安装过程中会生成服务器证书stunnel.pem
, 按照提示来即可.
编辑配置文件/usr/bin/etc/stunnel.conf
, 如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cert = /usr/local/etc/stunnel/stunnel.pem CAfile = /usr/local/etc/stunnel/stunnel.pem socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 pid = /tmp/stunnel.pid verify = 3 setuid = stunnel setgid = stunnel compression = zlib delay = no sslVersion = TLSv1 fips=no debug = 7 syslog = no output = /usr/local/etc/stunnel/stunnel.log [s-openvpn] accept = 13579 #监听端口 connect = 127.0.0.1:4443 #OpenVPN端口
启动stunnel:
查看OpenVPN和Stunnel是否正确执行, 检查相应端口:
1 2 3 4 5 6 7 8 9 10 11 # netstat -ntwla Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:13579 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:4443 127.0.0.1:50223 ESTABLISHED # lsof -i:4443 -n COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME openvpn 25290 root 5u IPv4 2982393 0t0 TCP *:pharos (LISTEN) openvpn 25290 root 8u IPv4 3361561 0t0 TCP 127.0.0.1:pharos->127.0.0.1:50223 (ESTABLISHED) stunnel 26801 stunnel 10u IPv4 3361560 0t0 TCP 127.0.0.1:50223->127.0.0.1:pharos (ESTABLISHED)
看到端口均已正确监听, 至此Server端配置完成
3
. Router配置安装好Linux系统后(Red hat或CentOS), 同步服务器时间(非常重要):
1 2 # ntpdate time.nist.gov
3.1
安装StunnelRouter端需要首先安装Stunnel, 在本地开启加密链路, 透传OpenVPN加密端口4443, 然后OpenVPN才能开始接入:
将Server端Stunnel证书传过来, 以便验证:
1 # scp root@server:/usr/local/etc/stunnel.pem root@router:/usr/local/etc/stunnel.pem
开始进行stunnel配置, 配置文件/usr/local/etc/stunnel.conf
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 pid = /tmp/stunnel.pid cert = /usr/local/etc/stunnel/stunnel.pem socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 verify = 3 CAfile = /usr/local/etc/stunnel/stunnel.pem client=yes compression = zlib ciphers = AES256-SHA delay = no failover = prio sslVersion = TLSv1 output = /root/bin/logs/stunnel.log [s-openvpn] accept = 127.0.0.1:4443 connect = server.ip.address:13579
启动stunnel:
3.2
安装OpenVPN下载安装OpenVPN, OpenVPN依赖lzo, 需要一同安装:
1 # yum install lzo openvpn
配置Router端配置文件/etc/openvpn/hk.ovpn
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 dev tap #设备模式 port 65530 #本地监听端口 proto tcp #协议 client #服务模式:client tls-client #加密客户端 ns-cert-type server remote 127.0.0.1 4443 #Server端口, 由于使用Stunnel加密透传, 所以连接本地端口 ca /etc/openvpn/ca/ca.crt #证书 key /etc/openvpn/ca/client1.key #证书 cert /etc/openvpn/ca/client1.crt #证书 persist-key persist-tun #route-method exe #route-delay 2 comp-lzo status /etc/openvpn/openvpn-status.log #状态日志 log-append /etc/openvpn/ca.log #执行日志 verb 3
启动OpenVPN:
1 # openvpn --daemon --config /etc/openvpn/hk.ovpn
观察日志, 如果出现“Initialization Sequence Completed”
则代表启动成功.
检查隧道:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # ip addr 11: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100 link/ether 06:10:50:e5:e5:2c brd ff:ff:ff:ff:ff:ff inet 172.31.188.2/24 brd 172.31.188.255 scope global tap0 inet6 fe80::410:50ff:fee5:e52c/64 scope link valid_lft forever preferred_lft forever # ping 172.31.188.1 PING 172.31.188.1 (172.31.188.1) 56(84) bytes of data. 64 bytes from 172.31.188.1: icmp_seq=1 ttl=64 time=67.3 ms 64 bytes from 172.31.188.1: icmp_seq=2 ttl=64 time=67.1 ms ^C --- 172.31.188.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1588ms rtt min/avg/max/mdev = 67.183/67.284/67.386/0.278 ms
链路通畅
3.3
安装DNSmasqRouter若要进行翻墙, 需要使用国外DNS, 而浏览国内网站时, 如果使用国外DNS, 会造成将访问导向国外站点, 造成访问速度变慢, 所以此方案使用DNSmasq解决此问题.
同时DNSmasq也是一个轻量级DHCP服务器, 非常方便好用.
安装DNSmasq:
编辑DNSmasq配置文件/etc/dnsmasq.conf
, 假设Router本地IP是10.2.166.10, 本地分发网段是10.2.166.0/24, 则配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # DHCP config expand-hosts domain=archean.me # DHCP Range dhcp-range=10.2.166.50,10.2.166.150,12h #DHCP地址池 # DHCP route dhcp-option=3,10.2.166.10 #路由 # Apple ntp server dhcp-option=option:ntp-server,10.3.1.233 #ntp时间服务器 # DNS server no-resolv no-poll server=8.8.8.8 server=8.8.4.4 conf-dir=/etc/dnsmasq.d # AppleTV trailers address=/trailers.apple.com/180.153.225.136 # Static IPs # dhcp-host=xx:xx:xx:xx:xx:xx,10.2.166.121
配置分类解析配置文件/etc/dnsmasq.d/china.conf
, 以使常用域名走国内DNS解析, 举例如下, 根据自身情况更改:
1 2 3 4 5 6 7 8 9 10 11 # server=/domain.name/dns.server server=/115.com/114.114.114.114 server=/123u.com/114.114.114.114 server=/126.com/114.114.114.114 server=/126.net/114.114.114.114 server=/163.com/114.114.114.114 server=/17173.com/114.114.114.114 server=/17cdn.com/114.114.114.114 server=/51.la/114.114.114.114 server=/6rooms.com/114.114.114.114 server=/91.com/114.114.114.114
至此准备工作完成, 可以启动路由器了
3.4
启动路由器思路
默认路由为OpenVPN Server端私网IP, chnroute生成的3000条国内路由 走国内链路, 以达到分流/翻墙的目的.
步骤:
启动Stunnel, 启动DNSmasq
开启linux内核转发功能
启动OpenVPN
增加3000条国内路由(点这里下载 )
增加默认路由, 增加下一跳为OpenVPN Server端私网IP
将步骤编写成脚本, 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #!/bin/sh # Stunnel up /usr/bin/stunnel /usr/sbin/dnsmasq # date ntp time ntpdate ntp.server.name /sbin/route add -net 10.0.0.0/8 gw 10.2.166.1 /sbin/route add -host server.ip.address gw 10.2.166.1 # iptables NAT /sbin/iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE sysctl -w net.ipv4.ip_forward=1 # start Openvpn killall openvpn /usr/local/sbin/openvpn --daemon --config /etc/openvpn/hk.ovpn sleep 5 # Chnrouters for i in `cat /root/bin/CN` ; do /sbin/route add -net $i gw 10.2.166.1 ; done /sbin/route del default /sbin/route add default gw 10.2.166.1 /sbin/route add default gw 172.31.188.1
启动脚本, Router环境搭建完成, 国外网络访问测试:
1 2 3 4 5 6 7 8 9 10 11 # tracert 8.8.8.8 traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets 1 172.31.188.1 (172.31.188.1) 68.963 ms 68.913 ms 68.914 ms 2 103.30.4.1 (103.30.4.1) 109.650 ms 109.651 ms 109.645 ms 3 172.16.0.2 (172.16.0.2) 109.410 ms 109.454 ms 109.448 ms 4 gi1-26.br02.hkg04.pccwbtn.net (63.218.241.1) 109.384 ms 109.384 ms 109.465 ms 5 72.14.196.197 (72.14.196.197) 109.415 ms 109.381 ms 109.344 ms 6 209.85.241.56 (209.85.241.56) 109.368 ms 209.85.241.58 (209.85.241.58) 105.488 ms 149.385 ms 7 216.239.43.17 (216.239.43.17) 108.792 ms 68.841 ms 209.85.253.69 (209.85.253.69) 69.430 ms 8 * * * 9 google-public-dns-a.google.com (8.8.8.8) 108.102 ms 107.936 ms 107.819 ms
可以看到直接走OpenVPN私网IP出去, 国内网络访问测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # traceroute www.baidu.com traceroute to www.baidu.com (115.239.210.26), 30 hops max, 60 byte packets 1 10.2.166.1 (10.2.166.1) 2.267 ms 2.470 ms 2.623 ms 2 10.2.255.254 (10.2.255.254) 2.180 ms 2.492 ms 2.648 ms 3 * * * 4 * * * 5 * * * 6 123.125.40.254 (123.125.40.254) 2.714 ms 2.634 ms 2.883 ms 7 61.49.44.65 (61.49.44.65) 1.459 ms 1.448 ms 1.521 ms 8 61.148.160.5 (61.148.160.5) 1.443 ms 1.466 ms 1.459 ms 9 124.65.60.77 (124.65.60.77) 3.258 ms 5.805 ms 5.790 ms 10 123.126.0.85 (123.126.0.85) 3.392 ms 3.202 ms 3.245 ms 11 123.126.0.85 (123.126.0.85) 3.214 ms 5.487 ms 3.913 ms 12 219.158.35.90 (219.158.35.90) 71.347 ms 71.338 ms 71.337 ms
国内链路则直接走原本的网络环境出去.
3.5
配置监控脚本由于国际出口不一定稳定, OpenVPN有可能会间歇性断掉, 如果发生此情况, 则会造成默认路由不可达, 从而导致国内网站浏览也会出现问题, 所以配置监控脚本, 一旦国际链路抽风, 则立刻将路由切换至国内.
脚本内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #!/bin/bash ip="172.31.188.1" i=-1 j=-1 while : ; do ping $ip -c 5 -w 30 if [ $? -ge "1" ]; then route del default gw $ip j=-1 i=$((i+1)) txt=`date +%F" "%X`" Ping $ip timed out." (($i%30==0)) && echo $txt >> /root/bin/logs/checkip.log (($i%30==0)) && echo $txt | mailx -s "VPN disconnected" admin@domain.com else route add default gw $ip i=-1 j=$((j+1)) txt=`date +%F" "%X`" Ping $ip OK." (($j%30==0)) && echo $txt >> /root/bin/logs/checkip.log (($j%100000==0)) && echo $txt | mailx -s "VPN OK." admin@domain.com fi sleep 10 done
后台启动此脚本, 则会每10秒监控一次出国链路, 如果断掉, 将会把路由切至国内, 不影响正常上网; 如果出国链路长期无法恢复, 则每5分钟给管理员发送一封告警邮件.
4
. Client客户端接入路由器所在交换机后, 配置为自动获取IP地址, 即可进行翻墙.