Friday, 14. April 2006, 03:54:00
由于这边防火墙进行了很变态的封锁(之前甚至只开放了几个浏览网页和收发邮件的端口,协议也只开放了最基本的, icmp都封了,甚至连文件下载都被block了,非常痛苦……不过现在好了些,至少文件下载又重新开放了),所以逼于无奈下定决心要冲出去。
正好自己在公网有一台服务器,这台服务器便成了我的救命稻草。在上面开了http proxy和socks proxy,虽然能缓解一下形势,不过还是不太爽,想pptp连回学校都不行。所以我的目标很明确,用那台Server提供VPN,然后这边通过这个VPN钻出去,从而不受本地防火墙限制地使用网络服务,包括拨pptp回学校。
由于当初对网络协议认识不深,以为可以通过Socks来拨pptp,然而socks只能代理基于TCP/UDP的应用层协议,pptp需要的GRE协议是不能代理的(如果我的理解没有错),所以当然失败了。同样,后来尝试用
datapipe进行端口映射,由于datapipe只支持tcp,所以也失败了。因此,只能选择VPN来实现我的目的了。
(值得一提的是
freecap这个俄罗斯人写的socks client,功能比sockscap强多了,还支持proxy chain,至少不会像sockscap和Permeo Security Driver那样,死活连不上需要密码验证的Socks5 Proxy)
通过google,我了解到OpenVPN是一个不错的解决方案,于是就决定用它了。服务器使用的是Linux (2.4.19),可以在官方主页
http://openvpn.net/下载,我用的版本是2.0.6。客户端是WindowsXP,可以在
http://openvpn.se/下载OpenVPN GUI for Windows,我用的是1.0.3。安装和配置没有什么问题,参考
HowTo就OK了。服务器端主要需要注意的是要先保证系统有lzo和openssl这两个库。安装完后,客户端和服务端的配置文件分别以example里的客户端和服务器配置文件为蓝本,稍作修改就没问题了。证书和密钥的设置可以参考这篇:
配置OpenVPN进行加密通讯v0.1.pdf,在server端生成key后,把生成的ca.crt client1.crt和client1.key三个文件下载到C:\keys下面。(补充一点,在生成key和证书前,可以编辑vars文件的末尾,修改一些field的缺省值,这样就不用每次生成key和证书时都去改(其实不改也行,随便填的),一路回车就行了。我把默认值改成了:
export KEY_COUNTRY="CN"
export KEY_PROVINCE="GD"
export KEY_CITY="Guangzhou"
export KEY_ORG="SUAA"
export KEY_EMAIL="me@myhost.mydomain"
我的客户端配置如下:
----------client.ovpn-----------
client
dev tun
proto udp
remote 192.168.1.199 1194 #当然,我实际使用的ip和port不是这个 ;)
resolv-retry infinite
nobind
persist-key
persist-tun
redirect-gateway #让VPN成为默认网关
ca "C:\\keys\\ca.crt"
cert "C:\\keys\\client1.crt"
key "C:\\keys\\client1.key"
comp-lzo
verb 3
我的服务器端配置如下:
----------server.conf-----------
port 1194
proto udp
dev tun
daemon
ca keys/ca.crt
cert keys/server.crt
key keys/server.key
dh keys/dh1024.pem
server 10.8.1.0 255.255.255.0
ifconfig-pool-persist ipp.txt
client-to-client
keepalive 10 120
comp-lzo
max-clients 10
user nobody
group nogroup #这个系统没有nobody组,但有nogroup组,所以就用nogroup了
chroot /usr/local/etc/vpn
persist-key
persist-tun
status openvpn-status.log
log openvpn.log
verb 3
我实际使用的当然不是1194这个端口,这个端口是过不了这边的防火墙的,我用的是另外一个已确认防火墙没有挡掉的UDP端口。客户端这边是内网nat出去的,不过没有问题,因为服务器那边不需要访问通过我访问我这里的lan的其它,所以不用进行额外的设置。这样设置后,用OpenVPN GUI已经可以建立VPN连接了,互相也能ping得通。但这时客户端只能访问服务器,还不能通过服务器访问其它机器。
其实这个问题困扰了我很长时间,网上那些解释把我绕得晕头转向的,而之前因为我并没有开防火墙,跟iptables有关的说明我都一概不理,所以一直没有成功。后来静下来想一想,虽然服务器端能访问VPN子网,也能访问外部网络,但VPN到外部网络,必然是要经过nat的过程,而不仅仅是route的设置问题。OpenVPN本身不会自己去nat,还是需要在系统里另外实现。(不过奇怪的是,我一开始在自己vmware里的linux试验时,只要打开ip_forward就可以了……)
首先是要打开ip_forward:
sysctl -w net.ipv4.ip_forward=1
或者
echo "1">/proc/sys/net/ipv4/ip_forward
都可以(在我这里的FC4上,echo 1>...居然不行,一定要echo "1"...真分特!)
然后是用iptables实现nat。我参考了这篇文章:
http://www.linuxonline.net.cn/bbs/viewthread.php?tid=1080 。只要这个命令就可以了:
iptables -t nat -A POSTROUTING -s 10.8.1.0/24 -o eth0 -j MASQUERADE
(我的vpn子网为10.8.1.0 mask 255.255.255.0)
首先启动iptables:
service iptables start
然后再运行上面那个命令设置nat(我没有iptables save来保存设置,所以要先启动服务再设置)
检查一下是否设置成功:
iptables -t nat -L -n
设置完成后,再试试vpn,发现已经可以nat了。(不过如果在conf里设置了verb 9,在log里还是能看到GET INST BY VIRT: 66.102.9.99 [failed]这类东西,跟没nat时一样……)
另外,如果不把vpn做为默认网关,可以在服务器的conf里用push "route ip mask"或者在客户端的配置文件里加入route ip mask来设置客户端访问哪些地址需要走vpn。