前阵子在LVS中文站找资料,发现很多人反应LVS的TUN模式搭建不成功,很多人反应网上的资料很混杂,但是照着做都没做成功,稍微有点郁闷。这里分享一个成功的案例,希望能帮到有需要的朋友。

     本文将介绍IPIP协议,LVS/TUN 搭建,以及在TUN模式下通过iptables实现端口转发等内容。

     之前看了很多网上的资料都说企业中用的最多的是DR模式,因为DR相比于TUN不用额外的开销之类的,但是DR是不是真的就那么完美呢?其实不是的,当服务器的规模一大,问题就出来了,我们知道DR模式下的Director和RealServer必须是同一网段的,那么当服务器足够多的时候,就会出现问题。假设机房给了你一整个C网段的IP地址,而你的真实服务器有成千上万台,这种情况下,DR的局限性就出来了,而TUN模式是可以跨网段,跨地域通信的, 不存在这方面的顾虑。


一、IP Tunnel 原理

   IP Tunnel,又叫IPIP,是一种将一个IP封装到另外一个IP中进行传输的技术。通常需要两个部件:封装部件和解包部件,两端各需要一个IP地址,且两个IP地址能够直接通信。它的工作原理是:在封装部件将一个IP封装到封装部件地址(隧道端的IP)上,并以解包部件地址(IP隧道另一端的地址)为目标地址进行转发。解包部件接受到封装好的数据包后,先进行解包,对数据报进行还原,再以数据报原目标地址为目标地址转发数据报,从而实现通信。用一句话总结就是:将两个无法直接通信的IP,封装在两个能够直接通信的IP,借助IP Tunnel 进行传输、通信。此时,隧道两端的IP地址便是一个载体,提供传输的功能。完整的封包结构如下所示:

LVS/Tun 成功案例_第1张图片

   说了这么多,是不是对概念还不太清晰?没关系,接着看下面的实验,做完实验再回头看原理,或许会有另外的收获。


二、IP Tunnel实验

IP 分配

node1     10.1.1.101/24           192.168.1.1/24

node2      10.1.1.103/24            192.168.2.1/24


在不做任何配置的情况下,10.1.1.101/24能够直接与10.1.1.103/24 通信,而192.168.1.1/24 不能直接与192.168.2.1/24 进行通信。

wKiom1M4Hrbh6uCVAADuhm88d9A108.jpg



wKioL1M4Ho7RGhLPAABumzDrim0694.jpg


node1 配置

root@node1:~# modprobe ipip

root@node1:~# modprobe ip_gre

root@node1:~# ip tunnel add tun0 mode gre remote 10.1.1.103 local 10.1.1.101 ttl 64

root@node1:~# ip link set tun0 up

root@node1:~# ip addr add 192.168.1.1 peer 192.168.2.1 dev tun0

root@node1:~# ip route add 192.168.2.0/24 dev tun0


node2 配置

root@node2:~# modprobe ipip

root@node2:~# modprobe ip_gre

root@node2:~# ip tunnel add tun0 mode gre remote 10.1.1.101 local 10.1.1.103 ttl 64

root@node2:~# ip link set tun0 up

root@node2:~# ip addr add 192.168.2.1 peer 192.168.1.1 dev tun0

root@node2:~# ip route add 192.168.1.0/24 dev tun0


再次在node1 上ping node2可以发现192.168.1.1/24和 192.168.2.1/24 两个网段能够通信。

LVS/Tun 成功案例_第2张图片


三、LVS/TUN+iptables 实现端口转发

   有时候,出于安全的考虑,我们需要通过端口转发来隐藏我们真实服务的端口。我们知道DR/TUN模式是不支持端口转发的,因此DR/TUN模式若想但是网上很多资料都会有这么一句话:“记得关闭防火墙,否则将导致实验不成功。”难道真的没办法吗?答案是否定的,下面是实验的演示:

LVS/Tun 成功案例_第3张图片

实验平台:Ubuntu 12.04

Director 上的配置

# 配置网卡

root@node1:~# ifconfig eth0:1 192.168.10.254 netmask 255.255.255.255 broadcast 192.168.10.254 up

root@node1:~# route add -host 192.168.10.254 dev eth0:1


# 配置LVS/TUN

root@node1:~# ipvsadm -A -t 192.168.10.254:80 -s rr

root@node1:~# ipvsadm -a -t 192.168.10.254:80 -r 192.168.10.103:80 -i

root@node1:~# ipvsadm -a -t 192.168.10.254:80 -r 192.168.10.104:80 -i


root@node1:~# echo "0" >/proc/sys/net/ipv4/ip_forward

root@node1:~# echo "1" >/proc/sys/net/ipv4/conf/all/send_redirects

root@node1:~# echo "1" >/proc/sys/net/ipv4/conf/default/send_redirects

root@node1:~# echo "1" >/proc/sys/net/ipv4/conf/eth0/send_redirects


此时,每个控制器已可以处理引入的对浮动服务 IP 的 Web 和 SSL 请求,方法是重写这些请求并连续地将工作传递给 realserver。但是为了从 realserver 收回通信量,并且为了在将请求返回给发出请求的客户机之前执行相反的过程,您需要对控制器更改几个连网设置。其原因是需要在平面网络拓扑结构中实现 LVS 控制器和 realserver(即,同一子网上的所有组件)。我们需要执行以下步骤以强制 Apache 通过控制器返回响应通信量,而不是自己直接应答:

echo "0" >/proc/sys/net/ipv4/conf/all/send_redirects

echo "0" >/proc/sys/net/ipv4/conf/default/send_redirects

echo "0" >/proc/sys/net/ipv4/conf/eth0/send_redirects


执行此操作的目的是为了防止活动的 LVS 控制器通知 realserver 和浮动服务 IP 直接相互通信,从而获取 TCP/IP 捷径(因为它们位于同一个子网中)。一般情况下,重定向是有用的,因为它们通过清除网络连接中不必要的中间件提高了性能。但是此时,它可能阻碍了响应通信量的重写,而这又是对客户机透明所必需的。实际上,如果在 LVS 控制器上没有禁用重定向,那么从 realserver 直接发往客户机的通信量将被客户机视为未被请求的网络响应而被丢弃。


RealServer(web01、web02)上面的配置

# 配置tunl0

root@web01:~# ifconfig tunl0 192.168.10.254 broadcast 192.168.10.254 netmask 255.255.255.255

root@web01:~# route add -host 192.168.10.254 dev tunl0


# 关闭转发、arp响应

root@web01:~# echo "0" > /proc/sys/net/ipv4/ip_forward

root@web01:~# echo 1 > /proc/sys/net/ipv4/conf/tunl0/arp_ignore

root@web01:~# echo 2 > /proc/sys/net/ipv4/conf/tunl0/arp_announce

root@web01:~# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore

root@web01:~# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

root@web01:~#echo 0 > /proc/sys/net/ipv4/conf/tunl0/rp_filter

root@web01:~# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter


注:web02 上面的配置同上


配置防火墙规则(至关重要)

root@node3:~# iptables -t nat -A PREROUTING -d 192.168.10.254 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.10.254:8080


root@node3:~# iptables -t nat -A PREROUTING -d 192.168.10.254 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.10.254:8080


参考资料:

http://www.austintek.com/LVS/LVS-HOWTO/HOWTO/LVS-HOWTO.rewrite_ports.html#re-mapping_ports_with_iptables

里面有这么一段话:

You can still rewrite the ports at the  realserver with iptables allowing the realserver to listen on another port.


if you need to rewrite ports for LVS-DR  or LVS-Tun, just use


realserver:/# /sbin/iptables -t nat -A PREROUTING -d VIP -p  tcp -m tcp --dport 80 -j DNAT --to-destination VIP:9999


Here the client connects to VIP:80 on the  director, the realserver is listening on VIP:9999. It works for me for tomcat  standalone servers.


测试

LVS/Tun 成功案例_第4张图片


LVS/Tun 成功案例_第5张图片


另外有一点需要注意点的是:iptables最好配置在RealServer 上,若配置在Director 上,会引起一些问题,原因是ipvsadm 和 iptables 都是用户态的,而他们的内核态都是netfilter,即本质上是一样的,工作在同一层,两个一起工作,会影响性能,还有造成其他的一些问题。

详细情况可以参考:

http://zh.linuxvirtualserver.org/node/2422