用openswan 2.4.7构建安全VPN笔记 (2007)
摘自:http://blog.chinaunix.net/uid-233544-id-2427445.html
前言:
反把复复尝试了很多次,在网上相关文档的指导下,终于实现了在RH Linux 9.0 (kernel 2.4.20-8 )上以源码方式安装openswan-2.4.27,但老系统安装新版本的软件却是颇为劳心费神之事,不为别的,只为学习,呵呵。此实验在RH Linux 9.0 (kernel 2.4.20-8 )上实现,请注意您的内核版本(这一点很重要)。
第一部分:VPN简介
Linux平台上的VPN大致可以为分为三类:
IPSec VPN(Openswan,frees/wan,strongswan,KAME)
IPSec(IP Security)是一种较老的也是采用的最为广泛的VPN技术,是由IETF开发的一组身份验正和数据加密的协议,提供了私有性、完整性、真实性和防重播等安全服务,可以用于IP网络中的数据保密、完整性检查、身份验正、密匙管理等许多方面。
IPSec在Linux上的实现主要分为两类,第一类是曾被称作Frees/wan的项目,如今已经分裂为openswan和strongswan。它们都提供自身的内核堆栈(kernel stack),也可以基于新近的内核中所提供的代码。第二类是BSD之上的KAME,它只能使用内核堆栈。大多ipsec规范本身并不在本地网络中为远程主机提供一个虚拟IP,不过仍有不少为此而实现的扩展可以解决诸如此类的问题。因此,可以将Microsoft的支持L2TP的产品运行于ipsec之上。
ipsec是面各连接的协议,为很多家商业类的路由器所采用。Openswan基于自身的XAUTH扩展,也可以作为Cisco,Nortel以及其它多家VPN集成产品的客户端。
ipsec可以让我们在不改变外部防火墙规则的情况下,在内核级别相当容易的对什么能通过隧道或什么不能作出安全的处理;其在实现NET-TO-NET以及host-to-net的配置方面也表现出了很大的灵活性。但灵活也就意味着实现起来的困难,所以ipsec的成功配置运行相当有难度,此外,尽管已经其在对NAT-Travel的支持方面做了不少改进,但还是不能较好的工作于一些NAT网关之后。
SSL-Based VPN (openVPN)
近来,加密套接字层(SSL)虚拟专用网(VPN)逐渐流行起来。这种VPN的最大好处在于,你仅仅需要一个单独的TCP或者UDP端口便可以轻易的穿越大多数的防火墙进行数据传送。SSL VPN在Linux系统上的最好实现是OpenVPN,其相当成熟和富于特色。
PPTP-Based VPN (PoPToP)
PPTP(Point to Point Tunneling Protocol)是由微软发起的可以工作在包括Windows 95在内的微软多个操作系统上的协议。虽然已经采用了相当长一段时间,但其仍存在许多安全方面的问题。它主要是基于GRE(Generic Routing Encapsulation)通过隧道来传送一个PPP连接。Linux系统上PPTP实现的主要代表是PoPToP。如果你的确需要PPTP的话,烈建议你用基于IPSEC的L2TP来代替PPTP,因为它更加安全,并且提供了和PPTP一样的功能。
第二部分,openswan的安装
FreeS/WAN是基于IPSec的VPN项,现在已经停止开发,其分裂为两个项目,Openswan与 Strongswan。其可以用自身的IPsec内核堆栈(Kernel stack),称为KLIPS,也可以用2.6内核中的堆栈代码;因为IPSec工作在网络层,所以需要系统内核态的支持,但2.4的内核没有实现内核堆栈,故必须打klips补丁。同时,若想要实现NAT Traversal的支持,还需要打上NAT-T补丁。
openswan是新项目,且frees/wan已经于2004年停止开发,于是我们想当然地要用openswan了。
既然要做网关转发数据,两个或更多的NIC自然是必不可少的了.
一、安装内核原代码
1。你可以从网上下载2.4的最新版本至/usr/src,并解压缩;我这里使用发行光盘中自带的内核源码实现,挂载RH 9.0的第二张盘并执行以下命令安装
#rpm -ivh kernel-source-2.4.20-8.i386.rpm
2.检查/usr/src目录下的linux和linux-2.4是否已链接到新近安装的内核源码,如果没有,则执行以下命令创建链接:
#ln -s linux-2.4.20-8 linux
#ln -s linux-2.4.20-8 linux-2.4
二、下载openswan、klips补丁和nat-t补丁至/usr/src目录中
1.下载地址为:http://www.openswan.org/code,请下载以下全部三个软件包
openswan-2.4.7.tar.gz
openswan-2.4.7.kernel-2.4-klips.patch.gz
openswan-2.4.7.kernel-2.4-natt.patch.gz
2.解压openswan,并将补丁拷贝至其解压出的目录中
#cd /usr/src
#tar zxvf openswan-2.4.7.tar.gz
#cp openswan-2.4.7.kernel-2.4-* /usr/src/openswan-2.4.7
三、进入源码目录,进行内核编译的准备工作
1.清理源代码树
#cd /usr/src/linux-2.4
#make mrproper
2.生成内核源码
#cp ./configs/kernel-2.4.20-i686.config .config
#make menuconfig
选择你所需要的内核选项,保存退出即可。请注意,尽量不要把关于开发以及实验性的选项编译进来。
注:如果你的Linux是安装在VMWare之上的话,请确保选择了以下几项:
Ram Disk驱动:
Block devices--->
< * > RAM disk support
(4096) Default RAM disk size (NEW)
< * > Initial RAM disk (initrd) support
文件系统:
File systems--->
[ * ] Ext3 journalling file system support
[ * ] JBD (ext3) debugging support
SCSI驱动,如果你使用的是模拟SCSI硬盘(若是升级安装内核,BusLogic SCSI support项亦必需设置为‘M’),此项尤其应该注意:
< * > SCSI support--->
SCSI low-level drivers --->
< M >BusLogic SCSI support
虚拟网卡AMD PCnet32 驱动:
Device Drivers --->
Networking support --->
Ethernet (10 or 100Mbit) --->
<*> AMD PCnet32 PCI support
3.建立新内核模块所需要的目录
#mkdir -pv /lib/modules/2.4.20-8custom
四、应用内核补丁,并编译安装内核
1.应用内核补丁,并编译内核
#cd /usr/src/openswan-2.4.7
#make nattpatch | (cd /usr/src/linux-2.4 && patch -p1 && make bzImage)
#cd /usr/src/linux && make dep bzImage
2.编译并安装内核模块
#cd /usr/src/linux-2.4
#make modules
#make modules_install
3.安装内核
#make install
4.检查/boot目录,是否显示有以下三项
#ls /boot |grep custom
initrd-2.4.20-8custom.img
System.map-2.4.20-8custom
vmlinuz-2.4.20-8custom
因为一些不知明的原因,这个initrd文件时常会引出kernel panic,所以我们把它移至别处并重新生成一个
#mv /boot/initrd/initrd-2.4.20-8custom.img
#mkinitrd /boot/initrd-2.4.20-8custom.img 2.4.20-8custom
5.检查/boot/grub/grub.conf文件中是否有如下几行:
#more /boot/grub/grub.conf
title Red Hat Linux (2.4.20-8custom)
root (hd0,0)
kernel /vmlinuz-2.4.20-8custom ro root=LABEL=/
initrd /initrd-2.4.20-8custom.img
好了,如果一切就绪,就可以重启你的系统了,注意要启用新内核。祈祷……
五、如果新内核启用没有任何问题,那么就可以开始以下的openswan的安装过程啦
1.确保启用了新的内核
#uname -r
2.4.20-8custom
2.安装生成userland tools 和 ipsec.o
#cd /usr/src/openswan-2.4.7
#make KERNELSRC=/usr/src/linux-2.4 programs module
#make KERNELSRC=/usr/src/linux-2.4 install minstall
注意:以上第二个步骤(#make KERNELSRC=/usr/src/linux-2.4 programs module)过程中若出现类同以下的错误,则需要编辑/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c文件删除“owner"对应的行,大概在原文的122和132行,把它删除即可。
cc -include /usr/src/openswan-2.4.7/packaging/linus/config-all.h -O3 -Wall -DIPCOMP_PREFIX -D__KERNEL__ -I/usr/src/linux-2.4.20-8/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fomit-frame-pointer -pipe -mpreferred-stack-boundary=2 -march=i686 -I/usr/src/openswan-2.4.7/linux/include -I/usr/src/linux-2.4/include -I -DIPCOMP_PREFIX -DARCH=i386 -DMODVERSIONS -include /usr/src/linux-2.4/include/linux/modversions.h -DMODULE -DMODVERSIONS -include /usr/src/linux-2.4.20-8/include/linux/modversions.h -DKBUILD_BASENAME=pfkey_v2 -c -o pfkey_v2.o /usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c
/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c:122: unknown field `owner' specified in initializer
/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c:122: warning: initialization makes integer from pointer without a cast
/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c:122: initializer element is not computable at load time
/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c:122: (near initialization for `pfkey_family_ops.authentication')
/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c:132: unknown field `owner' specified in initializer
/usr/src/openswan-2.4.7/linux/net/ipsec/pfkey_v2.c:132: warning: initialization from incompatible pointer type
make[2]: *** [pfkey_v2.o] Error 1
make[2]: Leaving directory `/usr/src/openswan-2.4.7/modobj'
make[1]: *** [module24] Error 2
make[1]: Leaving directory `/usr/src/openswan-2.4.7'
make: *** [module] Error 2
3.检查/lib/modules/2.4.20-8custom/kernel/net/ipsec的输出中是否有ipsec.o
#ls /lib/modules/2.4.20-8custom/kernel/net/ipsec
ipsec.o
4.安装openswan,[ 这一刻等的太久了吧 ]
#cd /usr/src/openswan-2.4.7
#make programs
#make install
六、启动并检查启动状态
1.编辑/etc/sysctl.conf,找到如下两项:
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
改作:
net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
然后用以下命令重新启用此文件
#sysctl -p
2.启动openswan
#service ipsec start
ipsec_setup: Starting Openswan IPsec 2.4.7...
3.检查状态
#ipsec verify
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path [OK]
Linux Openswan 2.4.7 (klips)
Checking for IPsec support in kernel [OK]
Checking for RSA private key (/etc/ipsec.secrets) [OK]
Checking that pluto is running [OK]
Two or more interfaces found, checking IP forwarding [OK]
Checking NAT and MASQUERADEing
Checking for 'ip' command [OK]
Checking for 'iptables' command [OK]
Opportunistic Encryption Support [DISABLED]
第三部分,配置Openswan
openswan的连接方式有两类:
1)NET-TO-NET方式
使用这种方式,可以将两个不同的位置的networks连接成为一个虚拟专用网;连接建立后,两端的主机可以透明的互相访问。不过,两个网关间以及网关到对方内部网络内主机不能实现透明的互相访问。这也是第二种方式Road Warrior存在的部分原因。
使用这种方式必须满足以下条件:
A 两个network都有自己的Linux网关,且每个网关都安装了openswan;
B 两端网络的IP地址不能出现叠加;
在本地网的网关上最好安装了tcpdump,以便测试连接
2)Road Warrior方式
这种方式用以实现远程主机到本地网络的安全拨入,主要用于经常有员工出差时可以远程安全的访问企业内部的资源。
使用这种方式应该满足以下条件:
一个具有静态IP地址的Linux网关,安装了openswan
一个安装了openswan的laptop,可以是动态IP地址
在本地网的网关上最好安装了tcpdump,以便测试连接
openswan支持多种认证方式,如RSA、RSK、XAUTH、X.509等;最常用到的是RSA和x.509,下面我们就分别介绍这两种认证下openswan的各种连接方式的配置。
一、RSA认证方式
(一)net-to-net连接
1. 用到的网络模型如下:
left network<----->left gateway<-----|----->right gateway<----->right network(192.168.10.0/24) (eth1:192.168.10.254 (eth0:192.168.1.202 (192.168.100.0/24) eth0:192.168.1.201 eth1:192.168.100.254
defaultGW:192.168.1.1) defaultGW:192.168.1.1)
除了以上IP地址信息外,还应该为每个网关准备一个用于在IPSEC协商中用以区分彼此的标识,可以用网关自身的FQDN,或者其它的名字,如@left、@right.mydomain.org。这个名字完全可以由自己编配。
2.
获得左侧(左右可以由管理员自己定义,一般以本地为左,远程为右)网关的ipsec公匙并追加至/etc/ipsec.conf中
,在left gateway上执行如下命令:
#ipsec showhostkey --left >> /etc/ipsec.conf
其输出为类同如下结果(由于输出很长,故用省略号替代):
# RSA 2192 bits Left Sat Mar 10 11:44:12 2007
leftrsasigkey=0sAQOuY/CYUfe66P+RXeZ0TXEbH......
执行如下命令将文件/etc/ipsec.conf拷贝为右侧网关的/etc/ipsec.conf(目的是获得右侧网关的public key)
#scp /etc/ipsec.conf root@192.168.1.202:/etc/ipsec.conf
获得右网关的ipsec公匙并追加至/etc/ipsec.conf中,在right gateway上执行如下命令:
#ipsec showhostkey --right >> /etc/ipsec.conf
将右网关的/etc/ipsec.conf文件拷贝回左网关一份:
#scp /etc/ipsec.conf root@192.168.1.201:/etc/ipsec.conf
注:在执行ipsec showhostkey命令时如果提示没有private key存在,需要用以下命令产生一个:
#ipsec newhostkey --out /etc/ipsec.secrets
3.在左网关上编辑/etc/ipsec.conf,定义要建立的连接
在/etc/ipsec.conf中如下一句之后添加新定义的连接
# Add connections here(此句前的“#”为注释符)
conn net-to-net
left=192.168.1.201 #左网关外网IP
leftsubnet=192.168.10.0/24 #左侧内网网段
leftid=@left #左网标识
leftnexthop=%defaultroute #指定左网关的下一跳为默认路由
right=192.168.1.202 #右网关外网IP
rightsubnet=172.16.16.0/20 #左侧网络网段
rightid=@right #右网关标识
rightnexthop=%defaultroute #指定右网关的下一跳为默认路由
auto=add #授权此连接,但在网关间建立连接时不自动启动,为了调试或手动启动
为了统一,也可将各网关的公匙对应在以上连接中。
将/etc/ipsec.conf拷贝至右网关:
#scp /etc/ipsec.conf root@192.168.1.202:/etc/ipsec.conf
3. 不要让IP伪装或NAT的数据包通过此连接隧道
如果在任何一边网关上使用了MASQ或者NAT,则必须在网关上修改iptables规则以免于让基于此目的的数据包通过IPSEC隧道,即如果网关上使用了如下规则:
#iptables -t nat -A POSTROUTING -o eth0 -s 192.168.10.0/24 -j MASQUERADE
则应该修改为:
#iptables -t nat -A POSTROUTING -o eth0 -s 192.168.10.0/24 -d ! 192.168.100.0/24 -j MASQUERADE
4. 启动连接
在本地网关启动连接:
#ipsec auto --up net-to-net
输出结果如下:
[root@Left root]# ipsec auto --up net-to-net
104 "net-to-net" #1: STATE_MAIN_I1: initiate
003 "net-to-net" #1: received Vendor ID payload [Openswan (this version) 2.4.7 PLUTO_SENDS_VENDORID PLUTO_USES_KEYRR]
003 "net-to-net" #1: received Vendor ID payload [Dead Peer Detection]
106 "net-to-net" #1: STATE_MAIN_I2: sent MI2, expecting MR2
108 "net-to-net" #1: STATE_MAIN_I3: sent MI3, expecting MR3
004 "net-to-net" #1: STATE_MAIN_I4: ISAKMP SA established {auth=OAKLEY_RSA_SIG cipher=oakley_3des_cbc_192 prf=oakley_md5 group=modp1536}
117 "net-to-net" #2: STATE_QUICK_I1: initiate
004 "net-to-net" #2: STATE_QUICK_I2: sent QI2, IPsec SA established {ESP=>0x606fcf02 <0xd0904bdd xfrm=AES_0-HMAC_SHA1 NATD=none DPD=none}
也可以通过查看日志/var/log/messages以及/var/log/secure来查看连接启动的具体情况。如果没能正常启动,请注意查看后文中关于troubleshooting介绍。
5. 测试连接
在一侧的内网网段里的主机(注意:不能是网关)上ping对方子网内的机器(注意:不能是网关)
ping 192.168.100.7 (如果是windows主机,最好加上-t选项,以确保ping的持续进行)
此时,在本地的网关上使用如下命令来查看输出:
#tcpdump -i eth0
而后应该可以看到有类同如下的数据序列来来回回的穿过:
23:16:18.529865 192.168.1.201 > 192.168.1.202: ESP(spi=0x32db83e2,seq=0x154)
23:16:18.530521 192.168.1.202 > 192.168.1.201: ESP(spi=0x7e2b7039,seq=0x154)
23:16:19.531058 192.168.1.201 > 192.168.1.202: ESP(spi=0x32db83e2,seq=0x155)
23:16:19.531861 192.168.1.202 > 192.168.1.201: ESP(spi=0x7e2b7039,seq=0x155)
注:这种方式只能建立net-to-net间的连接,并不能确保gateway-gateway之间的连接或者gateway-subnet(对方)之间的连接。如果你要使用此种连接,比如一方的网关还是一个文件服务器时,那么你还需要额外建立其它的连接。
6. 重新修订/etc/ipsec.conf文件(如果你想系统启动时会自动启用连接的话)
在各网关主机上找到:
auto=add
修改为:
auto=start
好了,如此你便可以尽情享用VPN给你带来的便利了。
(二)Road warrior
1.用到的网络模型如下:
left network<--------->left gateway<-------|------->laptop(linux系统)
(192.168.10.0/24) (eth1:192.168.10.254 eth0:192.168.1.202 eth0:192.168.1.201 defaultGW:192.168.1.1)
defaultGW:192.168.1.1)
laptop主机操作系统为Linux;如果是WindowsXP系统,可以配置x.509证书来实现远程访问,也可以基于L2TP/ipsec用PSK的方式来实现。后文将有介绍。
2.前提要求:
网关要有一个静态的外网IP,并要确定好网关后的子网IP地址范围;
本地网关和laptop都已经正确安装了openswan
网关和laptop都要有一个标识,以便在ipsec协商中区分彼此。可以是FQDN,也可以是任意编配的名字,只要能把二者区别开来即可。
3.获得双方公钥:
先获得laptop的公钥(以其为左)
#ipsec showhostkey --left
这个公钥和底下网关上的公钥都要追加至laptop以及网关的/etc/ipsec.conf文件中(但由于这次的配置中双方/etc/ipsec.conf有很大不同,故要自己想办法实现)。
然后,在网关上获得其公钥(以其为右):
#ipsec showhostkey --right
4.修改/etc/ipsec.conf,定义连接
在laptop上,你需要用编辑器打开/etc/ipsec.conf,并在其后添加如下内容。你可以根据自己的情况进行修改。
conn road
left=%defaultroute #如果是动态IP的话,把left指向默认网关。若是静态IP,填上,并新增一项leftnexthop=%defaultroute即可。
leftid=@laptop #标识
leftrsasigkey=…… #此处为laptop的公钥
right=192.168.1.201 #要拨入的网关的IP
rightsubnet=192.168.10.0/24 #远端子网
rightid=@vpnserver #远程网关标识
rightrsasigkey=…… #远程网关的公钥
auto=add #连接方式,不自动启用
在远程网关上,用编辑器编辑/etc/ipsec.conf,添加如下内容(可以概据自己的情况修改)。注意,在Road Worrior方式中,left和right的指定跟net-to-net方式有很大不同。在这种方式中,left表示本地机器,right表式远程主机。
conn road
left=192.168.1.201 #网关主机ip
leftid=@vpnserver #网关主机标识
leftsubnet=192.168.10.0/24 #子网
leftrsasigkey=... #
rightnexthop=%defaultroute #
right=%any # 远程主机(laptop)的IP未知
rightid=@laptop #
rightrsasigkey=... #远程主机(laptop)公钥
auto=add #
5. 启动连接
启动Road Worrior连接要在laptop端进行
#ipsec auto --up road
若输出结果类同以下,则表示启动成功
104 "net-net" #223: STATE_MAIN_I1: initiate
106 "road" #301: STATE_MAIN_I2: sent MI2, expecting MR2
108 "road" #301: STATE_MAIN_I3: sent MI3, expecting MR3
004 "road" #301: STATE_MAIN_I4: ISAKMP SA established
112 "road" #302: STATE_QUICK_I1: initiate
004 "road" #302: STATE_QUICK_I2: sent QI2, IPsec SA established
6. 测试连接
在laptop端,ping远程网关后的任一结点进行测试,注意不要ping网关本身。
#ping 192.168.10.7
然后在网关主机上查看ESP数据包的通过情况,如果类同如下,恭喜,你成功了。
13:46:18.529865 192.168.1.201 > 192.168.1.202: ESP(spi=0x32db83e2,seq=0x154)
13:46:18.530521 192.168.1.202 > 192.168.1.201: ESP(spi=0x7e2b7039,seq=0x154)
可能大家已经注意到了,这种方式仍然只能对网关后的主机与laptop之间的数据流进行加密,而并不能保护网关本向到laptop之间的数据。
7. 修改配置,使“road”连接可以自动启动
在双方主机的/etc/ipsec.conf中,找到
auto=add
修改为:
auto=start
8. 在如上的RSA的Road Warriors中,如果有多个laptop需要拨入,则需要配置多路的Road Warrior来实现。通过区分每个laptop的公匙,以及每个连接中left/right其它参数可以使网关主机轻而易举的区别每个拨入的laptop。但如果是通过PSK的认证方式来实现这种应用,将不得不让每个laptop使用同一个密钥,这将带来极大的安全隐患。
待续……
后记:如果您在安装过程中不是如此实现,欢迎在引交流;并请各位高手前辈给予批评指正,谢谢!