我没有太多的物理服务器,实验环境只能用四台装了linux的虚拟机来模拟,用户层工具是openswan。大致拓扑如下(我有点懒,公网地址我用的194.168.10.0/24,别和192.168.xx.xx弄混了)
LS(left server)的公网地址是194.168.10.4,私网地址是192.168.10.4。RS(right server)的公网地址是194.168.10.5,私网地址是192.168.5.5。LC(left client)是LS私网下面的一台客户机,地址是192.168.4.100。RC(right client)是RS下的一台客户机,地址是192.168.5.100。
openswan的安装过程我就不写了,各个linux的发行版的包管理都有合适的安装包。
第一步模配置地址和路由来模拟真实的网络环境
LS配置如下
ifconfig eth0 192.168.4.4 ifconfig eth1 194.168.10.4 ip route add default via 194.168.10.5
LC配置如下
ifconfig eth0 192.168.4.100 ip route add default via 192.168.4.4
RS配置如下
ifconfig eth0 192.168.5.5 ifconfig eth1 194.168.10.5 ip route add default via 194.168.10.4
RC配置如下
ifconfig eth0 192.168.5.100 ip route add default via 192.168.5.5
还有非常重要的一点,需要在LS和RS上打开内核转发功能
echo 1 >/proc/sys/net/ipv4/ip_forward
第二步设置ipsec
- 生成密钥对,在LS上执行
ipsec newhostkey --output /etc/ipsec.d/john_snow.secrets ipsec showhostkey --left --file /etc/ipsec.d/john_snow.secrets
然后在RS上执行
ipsec newhostkey --output /etc/ipsec.d/john_snow.secrets ipsec showhostkey --right --file /etc/ipsec.d/john_snow.secrets
把输出的内容保存起来,之后会用。
- 在LS和RS上修改/etc/ipsec.conf
version 2.0 # conforms to second version of ipsec.conf specification # basic configuration config setup # Debug-logging controls: "none" for (almost) none, "all" for lots. # klipsdebug=none # plutodebug="control parsing" # For Red Hat Enterprise Linux and Fedora, leave protostack=netkey # nat_traversal=yes protostack=netkey include /etc/ipsec.d/*.conf
- 在LS和RS上分别添加一个/etc/ipsec.d/john_snow.conf,内容如下
conn john_snow type=tunnel authby=rsasig compress=yes left=194.168.10.4 leftsubnet=192.168.4.0/24 leftid=@left leftrsasigkey=<刚才LS上输出的值> right=194.168.10.5 rightsubnet=192.168.5.0/24 rightid=@right rightrsasigkey=<刚才RS上输出的值> auto=add
- 在LS和RS上启动ipsec
service ipsec restart
- 建立连接
ipsec auto --up john_snow
测试一下看看
从RC里面ping 192.168.4.100也就是LC的地址,如果配置没错应该就可以ping通了,不通的话去检查一下iptables规则有没有问题。然后从RS的eth1抓包看一下
06:08:04.431719 IP 194.168.10.5 > 194.168.10.4: ESP(spi=0x0c6af04f,seq=0x137), length 132 06:08:04.432098 IP 194.168.10.4 > 194.168.10.5: ESP(spi=0x4654f5bf,seq=0x12f), length 132 06:08:04.432098 IP 192.168.4.100 > 192.168.5.100: ICMP echo reply, id 37188, seq 48, length 64 06:08:05.433440 IP 194.168.10.5 > 194.168.10.4: ESP(spi=0x0c6af04f,seq=0x138), length 132 06:08:05.433945 IP 194.168.10.4 > 194.168.10.5: ESP(spi=0x4654f5bf,seq=0x130), length 132 06:08:05.433945 IP 192.168.4.100 > 192.168.5.100: ICMP echo reply, id 37188, seq 49, length 64 06:08:06.434173 IP 194.168.10.5 > 194.168.10.4: ESP(spi=0x0c6af04f,seq=0x139), length 132 06:08:06.434621 IP 194.168.10.4 > 194.168.10.5: ESP(spi=0x4654f5bf,seq=0x131), length 132 06:08:06.434621 IP 192.168.4.100 > 192.168.5.100: ICMP echo reply, id 37188, seq 50, length 64 06:08:07.435032 IP 194.168.10.5 > 194.168.10.4: ESP(spi=0x0c6af04f,seq=0x13a), length 132 06:08:07.435600 IP 194.168.10.4 > 194.168.10.5: ESP(spi=0x4654f5bf,seq=0x132), length 132 06:08:07.435600 IP 192.168.4.100 > 192.168.5.100: ICMP echo reply, id 37188, seq 51, length 64
LS和RS之间的数据包已经走了ESP隧道,说明配置已经成功了。
如果你细心观察会发现还有没加密的数据(在上面tcpdump抓的包里比较长的那四条),再细心观察还会发现只有收的包会出现没加密的情况,发的包不会出现,这是为什么呢?这是因为linux里NETKEY协议处理ipsec数据包的方式比较特殊,linux会把外层IP头去掉,内层数据(包括真实的IP层+IP数据)解密以后又放到了相应的网口的协议栈,所以抓包的时候又抓到了解密以后的数据包。发包并不会出现这种情况。如果你从物理机抓包(从我的拓扑里看是vmnet4)就不会抓到没加密的数据包了。
还有一点
我看到有很多人写的文章里要在LS和RS里做NAT转换把LC和RC的私网地址分别转成LS和RS的公网地址,千万不要那么干。配置NAT转换的话数据包就不会再走ipsec了,抓一下包就能看到全是明文的。
我不太理解的地方是我把LS和RS的默认路由删掉以后LC和RC之间就没办法通信了,是不是说明内核里没有关于双方私网的信息,那么我们在配置文件/etc/ipsec.d/john_snow里配置了的leftsubnet/rightsubnet是不是没起作用?等有时间看一下代码。