dsnat简介
dsnat(Dynamic Source Network Address Translation) 是一个基于lvs的模块,在taobao开源的FNAT基础上开发,dsnat位于网络的网关位置,内网访问外网时,会将内网地址改成公网地址池中的ip,轮询选择
目前该模块只支持ipv4下的TCP,UDP协议, ICMP暂时还不支持
dsnat_tools包含ipvsadm和keepalived这2个工具,在官方源码的基础上修改添加了对dsnat的支持
- ipvsadm是对lvs进行配置的用户空间工具,ipvsadm->lvs类似于iptables->netfilter
- keepalived是对lvs集群的一个自动化配置工具(以服务形式常驻内存),可针对rs自动摘除和添加rs到vs中;并带有HA功能,提供热备容灾
change log
- 添加了源地址判断功能
- 不同源地址可使用不同的local address
- 可实现源地址黑白名单功能
- 代码由原来的centos6.2内核改为centos6.3内核
安装
1. 下载 redhat 6.2的内核
1 |
wget ftp://ftp.redhat.com/pub/redhat/linux/enterprise/6Server/en/os/SRPMS/kernel-2.6.32-279.el6.src.rpm |
2. 准备代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
cat > ~/.rpmmacros << 'EOF' %_topdir ~/rpms %_tmppath ~/rpms/tmp %_sourcedir ~/rpms/SOURCES %_specdir ~/rpms/SPECS %_srcrpmdir ~/rpms/SRPMS %_rpmdir ~/rpms/RPMS %_builddir ~/rpms/BUILD EOF cd mkdir -p ~/rpms/{tmp,BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} rpm -ivh kernel-2.6.32-279.el6.src.rpm cd ~/rpms/SPECS rpmbuild -bp kernel.spec |
3. 打补丁
1 2 3 4 |
cd ~/rpms/BUILD/ cd kernel-2.6.32-279.el6/linux-2.6.32-279.el6.x86_64/ wget https://raw.github.com/xiaomi-sa/dsnat/master/dsnat-kernel-2.6.32-279.el6/dsnat-2.6.32-279.el6.xiaomi.noconfig.patch patch -p1 < dsnat-2.6.32-279.el6.xiaomi.noconfig.patch |
4. 编译安装
1 2 3 4 5 |
make -j16 make modules_install make install ##重启使用新内核 init 6 |
LVS TOOL 安装
标准的ipvsadm和keepalive将无法正常使用,
需要编译安装ipvsadm和keepalived,在dsnat_tools下载工具源码
1 2 3 4 5 |
git clone git@github.com:xiaomi-sa/dsnat.git cd dsnat/dsnat_tools/ipvsadm make && make install cd ../keepalived make && make install |
配置用例
将lvs放在网关的位置,假设网络环境是这样的
client eth0 1.1.1.1 255.255.0.0 (cip)
lvs eth0 1.1.100.1 255.255.0.0 (gw ip)
lvs eth1 1.2.100.1-4 255.255.0.0 (lip)
rs eth1 1.2.1.4 255.255.0.0 (rip)
网络环境是(模拟一下)
- client在内网
- realserver在外网
- 内网到外网的路由指向lvs
- route add -net 1.2.0.0 netmask 255.255.0.0 gw 1.1.100.1(用默认路由也可以)
- 外网服务器可以访问lvs的lip
网关的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
##写入开机启动脚本 # echo >> /etc/rc.local << 'EOF' #打开转发设置 echo 1 > /proc/sys/net/ipv4/ip_forward #由于gro/lro功能会影响转发后数据包大小,超过MTU后会被丢弃重发,系统默认是开启的 #关掉gw ip所在的网卡gro/lro ethtool -K eth0 gro off ethtool -K eth0 lro off #绑定网卡中断,让中断在多核cpu上轮训,效果很赞,同样是gw ip所在的网卡 set_irq_affinity.sh eth0 EOF ##关闭irqbalance # service irqbalance stop # chkconfig --level 2345 irqbalance off ## 绑定local address # echo >> /etc/rc.local << 'EOF' ip addr add 1.2.100.1/16 dev eth1 ip addr add 1.2.100.2/16 dev eth1 ip addr add 1.2.100.3/16 dev eth1 ip addr add 1.2.100.4/16 dev eth1 EOF |
zone 说明
- zone表示一个网段,可以用192.168.1.0/24或192.168.1.0/255.255.255.0表示
- local address绑定在zone上
- dsnat对连接源地址判断,顺序匹配zone,以第一个匹配到的zone/local address作为snat的源地址池
- 如果没有匹配到zone或者匹配到的zone没有绑定local address,连接会被丢弃(可用作黑名单)
通过ipvsadm配置lvs规则
如果执行报错,请核对一下使用的内核补丁是否生效,ipvsadm是否为dsnat_tools编译安装版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#打开添加一个0/0的虚拟服务,开启dsnat,让所有的内网请求都能命中该服务 ipvsadm –A –t 0.0.0.0:0 –s rr #添加一个1.1.0.0/16的网段,用来做源地址匹配(client的ip是1.1.1.1/16) ipvsadm -K --zone 1.1.0.0/16 #为1.0.0.0/16的zone添加local address ipvsadm -P --zone 1.1.0.0/16 -z 1.2.100.1 ipvsadm -P --zone 1.1.0.0/16 -z 1.2.100.2 #再添加一个缺省的网段0/0 ipvsadm -K --zone 0.0.0.0/0 #为缺省网段添加local address ipvsadm -P --zone 0.0.0.0/0 -z 1.2.100.3 ... #查看vs ipvsadm -ln #查看公网ip地址池 ipvsadm -G |
通过keepalive配置lvs规则
如果执行报错,请核对一下使用的内核补丁是否生效,keepalive是否为dsnat_tools编译安装版本,
keepalive需要2台机器了,这里给出一台的配置
- 启动:service keepalived start
- 更新:service keepalived reload
- 停止:service keepalived stop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
## /etc/keepalived/keepalived.conf global_defs { router_id LVS_DEVEL } ##这是lvs的配置,写好公网ip地址池的ip local_address_group laddr_g1 { 1.2.100.1 1.2.100.2 } local_address_group laddr_g2 { 1.2.100.3 } zone 1.1.0.0 16 { laddr_group_name laddr_g1 } zone 0.0.0.0 0.0.0.0 { laddr_group_name laddr_g2 } ##这是High Availability部分的配置,会根据lvs的状况,让virtual_ipaddress在合适的机器上浮动 vrrp_sync_group G1 { group { VI_1 VI_2 } } ##配置eth0浮动ip vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type pass auth_pass 1111 } virtual_ipaddress { 1.1.100.1 } } #配置eth1浮动ip vrrp_instance VI_2 { state master interface eth1 virtual_router_id 53 priority 100 advert_int 1 authentication { auth_type pass auth_pass 1111 } virtual_ipaddress { 1.2.100.1/16 1.2.100.2/16 } } ##配置lvs,添加一个0/0的虚拟服务,开启dsnat,让所有的内网请求都能命中该服务 virtual_server 0.0.0.0 0 { delay_loop 6 lb_algo rr lb_kind FNAT protocol TCP laddr_group_name laddr_g1 } |
23 Comments
升级2.0了,GOGOGO~~~
下次更新争取把taobao_lvs v2 v3 的新特性整合进来
波哥的文档写的很赞
好牛B,要试用下!!
求二进制包下载!
kernel-firmware-2.6.32-279.23.1.mi4.el6.x86_64.rpm
kernel-2.6.32-279.23.1.mi4.el6.x86_64.rpm
kernel-devel-2.6.32-279.23.1.mi4.el6.x86_64.rpm
ernel-headers-2.6.32-279.23.1.mi4.el6.x86_64.rpm
ipvsadm
keepalived
TCP可以转发,UDP不行,是神马情况呢?
求联系,我的QQ:83766787
我忘了这版有没有支持UDP,作者近期休假,你留个邮箱吧
v2已经支持udp,用279目录下的patch和tools,tools的编译版本已发布,kernel由于是小米定制的配置,我过几天发个红帽子发行版默认内核+dsnat补丁的编译版本,请关注
请问兼容fullnat、nat、dr吗,能同时使用吗
这个是idc访问公网用的,和传统的lvs用法相反
哦,我试用了一下,就是我想同时使用fullnat+dsnat,两个都配置,发现dsnat可以使用,fullnat转发失败,这个做不到是吧。
应该是可以同时使用的。dsnat是在路由转发时检查(forward);fullnat是在本机收到请求(input)时检查,然后再做转发;互相是不会影响。由于添加了zone,fullnat的localaddress添加方式有所改变
NAT转发用不了,我在你的代码基础上修改了一下,恢复了FULLNAT的local address添加和使用方式。
另外,自己在NAT基础上实现了一个版本,没有使用fullnat补丁。
纯属兴趣爱好,学习交流一下,呵呵
https://github.com/jlijian3/lvs-snat
dsnat上的fnat模式由于应用场景的不同,把fullnat的laddr改成全局的了,跟官方的svc上的方式各有优缺点
nat我们没有测试过,非常感谢你的反馈
dsnat上的FULLNAT是可以使用,但是为zone配置的laddr是外网ip,而fullnat为svc添加的laddr是内网ip。
dsnat和fullnat同时使用,就共用了laddr,所以我修改了一下,各自单独配置。
比如,添加一个缺省网段,测试发现不管内网访问外网,还是FULLNAT转发,都会匹配到,而我们希望FULLNAT的laddr另外配置。
ipvsadm -K –zone 0.0.0.0/0
ipvsadm -P –zone 0.0.0.0/0 -z 1.2.100.3
我就在在函数ip_vs_hbind_laddr里面区分了一下
803 if (svc->addr.ip == 0 && svc->port == 0)
804 local = ip_vs_get_laddr_zone(&cp->caddr);
805 else
806 local = ip_vs_get_laddr(svc);
请问小米机房是多链路的吗,多链路怎么支持,比如有电信,联通,移动三条上行链路,通过路由表控制不同的包走不同的链路,但是不同的链路使用不同的local address
很好很强大,我们也基于阿里的lvs-v2开发适用于多链路的nat网关,支持tcp/udp/icmp,希望有机会跟小米同学交流一下
https://github.com/jlijian3/lvs-snat
virtual_server fwmark 1 {
snat_rule {
from 192.168.40.0/24
gw 1.1.3.1
oif eth2
snat_ip 1.1.3.71-1.1.3.73
algo random
}
}
赞呀,那个公司?
ucweb,感谢小米啊,也是受小米dsnat的启发(普空推荐的,哈哈)。不过我们要支持多isp,要匹配网卡网关,一开始用iptables,后来也基于lvs改了一个。
我们是ucweb公司的,小米同学有没有兴趣一起去杭州找阿里的lvs研发学习交流。
你好!请问dsnat性能咋样?并发请求数和连接数多少左右呀?
我部署的v2版本,请求ip是通的,但通过域名请求就是不行,是否dns这块有问题呀?