为了提升产品在复杂网络环境下的体验,性能,所以搭建了一套模拟网络的环境来提高效率,主要通过Ubuntu分享小范围Ap,使用Facebook的开源项目ATC(argumented traffic control)进行流量控制。介于目前公司没有一套相关的工具,就衍生了我去搭建一套企业级别的复杂网络模拟平台的想法。
目前为了先让功能跑起来,UI是基于ATC Demo直接修改,后续大家可以针对这个平台进行订制化修改。
ATC的搭建,配置,分享Wifi热点配置方式。(这种目前网上资料很多,可以先搭建这种,成功之后再尝试搭建企业级的平台)
优点:网上资料充足,搭建要求低
缺点:接入量少,覆盖范围只有10米,不稳定。
企业化的配置方式。
优点:接入量大,覆盖范围大,稳定。
缺点:网上没有相关资料,搭建要求高,成本高。
AP设备覆盖
为了降低成本,直接和IT部门同学沟通,使用公司网络的AP设备
如何实现弱网络模拟服务,并清楚依赖细节
自己通过tc+iptables实现。 基于facebook atc进行二次开发实现。网络拓扑图设计
在设计之前需要想清楚几个问题:
新建网络,还是对现有网络进行架构变更? 流量如何迁移到弱网络服务上? 预期使用的用户量,使用场景,给出大概需要的IP数量,IP段弱网络服务部署在公司现有测试网络mogu-alpha上,为了降低网络架构变更成本,采用桥接透传的模式。
在alpha网关服务器和H3C交换机中间串联一台弱网络服务器,弱网络服务器内外网口桥接,做流量透传,当流量经过弱网络服务器设备时候,会进行检测并对当前IP的流量进行控制,再转发出去。
要实现流量模拟,有几个准备工作:
真实流量必须经过控制服务器 要对IP进行控制,就需要对IP进行打标区分(iptables setmark) 系统需要支持流控服务(Linux tc命令) 根据物理连接的方式,选用不同的iptables策略 双网卡(建议两个物理口,如果只有单口,需要虚拟一个出来)https://github.com/facebook/augmented-traffic-control
一. 弱网络服务器与alpha网关服务器网线直连不通,弱网络服务器与S3C交换机直连不通
这个问题,是有好几个问题组合而成,消耗了不少时间。
服务器网线直连不通,是否是网线问题排查。
将alpha网关服务器直连交换机,发现是互通的。 用工作本替换alpha网关服务器,直连弱网络服务器,发现是互通的。通过这些验证,网线没有问题,定位在alpha网关服务器配置上。
弱网络服务器(10.54.0.20)和alpha服务器(10.54.0.1)之间网线直连网络不通
通过查看arp表,发现10.54.0.20没有学到10.54.0.1的arp表项。出现incomplete arp表项的原因一般有两种:
arp表项被删除了 arp学习失败了由于10.54.0.20与10.54.0.1之间网络是不通的,所以推测出现出现10.54.0.1的incomplete arp表项的原因是因为arp失败了,所以问题定位的重点是为什么这两台机器之间网络不通。
所以查看了,当前的组网方式如下
分析结果:发现因为Vlan不匹配导致不通。
弱网络服务器:网桥br0桥接eth1、eth0两个物理口,配置管理ip:10.54.0.20/16
alpha网关服务器:单物理口p4p1,配了几个Vlan,其中一个p4p1.54配置了10.54.0.1/16。所以可以得出10.54.0.1/16这段的ip都是走Vlan:54 这个虚拟口,该Vlan:54的真实设备是p4p1。又由于10.54.0.1是在p4p1.54上的。而10.54.0.20是在native device上的,那么10.54.0.20发的arp request for 10.54.0.1都会被Vlan device p4p1.54给丢掉(因为直连的弱网络服务器没有与之匹配的Vlan:54 device),所以不会有arp relply。这也是为什么直连不通的原因。
为了解决这个问题,我们在弱网络服务器的eth0口上创建一个vlan54 device,然后再把eth0.54加到br0上,组网方式如下图所示
通过这样修改之后,10.54.0.20就可以和10.54.0.1相通了。
手机连不上mogu-alpha wifi
在解决了10.54.0.20和10.54.0.1之间直连网络不通的问题后,又发现使用手机连不上alpha wifi,判定原因出在dhcp的请求失败导致,alpha wifi的dhcp功能是由alpha机器上的dhcp服务提供的,所以怀疑弱网络服务器获得数据包之后,丢弃了。
我们继续分析了现在的组网图
在eth1和eth0上抓了下包,发现在eth1上可以抓到发往10.54.0.1的arp request,并且该arp request还携带vlan:54。
在eth0上抓不到发往10.54.0.1的arp request,这是因为携带vlan:54的arp request在到达eth0.54 device时会被其丢掉。
所以我们发现Vlan的出入口都需要匹配,对组网又进行了一次修改,通过在eth1上创建一个vlan:54 deivce,然后将eth1.54加到br0上,如果下图所示
分析因为请求dhcp的设备本身处于10.54.0.x/16段,所以这些设备请求的内网服务都是带vlan:54的标识,所以通过这样修改之后,手机就可以连上alpha wifi了。
wifi无法访问外网(比如www.baidu.com无法访问)
通过在10.54.0.20的eth0上抓包,可以抓到source IP为172.17.0.12的包,是不带vlan的,那这个包肯定会被eth0.54给丢掉。
于是确认alpha服务器上的路由配置,发现默认网关是172.17.0.1,device是p4p1;同时确认了dns配置/etc/resolv.conf,nameserver是172.17.0.7和172.17.0.8,所以连接baidu时会首先跟nameserver通信,获取baidu.com的IP,这时发出去的包的source ip是172.17.0.12,走的是p4p1。
这时需要在10.54.0.20上把native通道打通,我们可以给每个vlan都创建一个bridge,用来给alpha服务器的各个Vlan提供相应的转发通道,组网图如下
通过这样的修改,就可以访问公网IP地址了,但是有个缺点就是,每添加一个Vlan都需要创建一个bridge作为透传。
二. Centos Python升级之后导致yum不可用。
解决了网络问题之后,就需要对弱网络服务的依赖环境进行配置,搭建,由于系统默认Python2.6.6,弱网络服务器依赖Python2.7,升级之后导致了yum不可用(错误:import no module yum),大大影响了一些工具的下载安装。
网络上推荐的几种解决方案:
修改python解释器地址
vim /usr/bin/yum 修改第一行#!/usr/bin/python 修改成 #!/usr/bin/python2.6.6
这种解决方案适用于:系统centos6.5自带的python2.6.6没有被卸载,只是软引用被修改。
但是当时我把python2.6.6给卸载了,重装python2.4,2.6都没有用,
所以这个解决方案并不适用所有人。
卸载所有python,完全重新安装python和yum
(这里一定要小心,千万别把rpm包给卸载了,否则就得重装系统)
上述的解决方案不可行,只能卸载重装,但是需要注意的是,重装的版本最好要根据当前系统依赖的版本,可以到http://mirror.centos.org/ 找到本机系统版本对应的安装包,可以写个shell脚本,批量下载或者手动一个个载也行。
操作步骤:
卸载Python
rpm -qa|grep python|xargs rpm -ev –allmatches –nodeps ##强制删除
whereis python |xargs rm -frv ##删除所有残余文件
卸载yum
rpm -qa|grep yum|xargs rpm -ev –allmatches –nodeps
whereis yum |xargs rm -frv
下载重装的python ,yum的rpm安装包(以我的机器centos6.5为例,需要下载centos6.5默认的那些版本号,可以google查下)
到http://mirror.centos.org/centos-6/6/os/x86_64/Packages/ 里面找到需要下载的安装包,在安装过程中,有漏什么,自己在去上面下载相应的包即可。如果没有就google找到相应的版本,手动下载。
安装rpm
rpm -Uvh –replacepkgs .rpm ## 专门起一个文件夹,存放相关的安装包,可以用这个命令,或者自己写一个shell脚本,把 .rpm 改成相应的rpm包即可。
最好装一个安装python2.7,隔离系统python2.6.6版本
如果要python默认为2.7版本,那么需要做如下操作:
rm -rf /usr/bin/python
ln -s /usr/local/bin/python2.7 /usr/bin/python
之后将vim /usr/bin/yum 第一行#!/usr/bin/python 修改成 #!/usr/bin/python2.6.6
如果不修改python默认,后续想使用2.7版本可以通过python2.7来使用。
三、 弱网络模拟服务(tc)不生效。
通过上面的操作,网络通了,服务也搭建起来了,流控界面对本手机设置限速,没有效果,比如设置18Kbps,访问百度依然很流畅。通过监控tc流量分配,发现iptables没有生效,流量根本没有走相应的class里面。而tc的流控都是基于HTB策略,通过class来区分每个ip的。
如果生效的话,流量应该走的qdisc netem 802d: parent 1:2 limit 1000 delay 650.0ms loss 2%里面。
分析流控原理,主要是通过在traffic control服务器的bridge上的FORWARD chain上设置iptables规则,然后在eth0.54和eth1.54上使用tc的HTB策略进行发包限速。(facebook atc 内核里面默认配置的),顺藤摸瓜,发现了以下几个问题。
netfilter相关模块没有加载,iptables服务未启动。
service iptables start 没有反应。(如果有反应的,那就忽略这个问题)
iptables 是一个用户态工具,其设置的规则最终需要在kernel netfilter的各个hook point上执行。在当前的traffic control服务器上没有加载netfilter相关模块,因为上面的iptables service启动失败了,导致没有正常加载相关的netfilter模块。
我们可以先手动加载这些模块(不过还是建议重新安装下iptables service)
ip_tables
iptable_filter
iptable_nat
iptable_mangle
nf_defrag_ipv4
nf_conntrack_ipv4
nf_conntrack
nf_nat
当然也可以自行google解决。
没有enable netfilter in bridge
traffic control服务器上把netfilter in bridge给disable了,因为其/etc/sysctl.conf配置文件中设置了
net.bridge.bridge-nf-call-iptables=0
需要修改为
net.bridge.bridge-nf-call-iptables=1
然后执行sysctl -p,这种方式可以保证下次启动服务器还会设置成1;
也可以直接echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables,这种方式对下次重启无效。
bridge-nf-call-iptables=1是用来使能bridge将ip包传给各种chains进行包处理的,包括我们当前用到的mangle表的forward chain处理,说白了,bridge-nf-call-iptables=1可以使bridge的netfilter利用IP层的netfilter代码。
内核中默认是enable的,除非你在用户态通过设置net.bridge.bridge-nf-call-iptables=0主动disable。
iptables规则设置不对
默认的iptables配置的是路由方式,而我们采用的是桥接方式,所以通过查阅iptables官网发现,桥接方式需要使用另外的配置命令。
目前的iptables设置规则是
iptables -A FORWARD -t mangle -s 10.54.4.155 -i eth1.54 -j MARK —set-mark 0x2/0xffffffff
iptables -A FORWARD -t mangle -d 10.54.4.155 -i eth0.54 -j MARK —set-mark 0x2/0xffffffff
这种规则并不会在bridge的forward chain上生效,针对bridge上的iptables专门新增了一个physdev的模块,使用户能够透过iptables -m physdev -h 在bridge模式下生效,规则需要按如下方式设置。
iptables -A FORWARD -t mangle -s 10.54.4.155 -m physdev --physdev-in eth1.54 --physdev-out eth0.54 -j MARK --set-xmark 0x2/0xffffffff
iptables -A FORWARD -t mangle -d 10.54.4.155 -m physdev --physdev-in eth0.54 --physdev-out eth1.54 -j MARK --set-xmark 0x2/0xffffffff
physdev参数是专门给设置nf_bridge提供的。
所以问题的根本,还是在iptables上,当解决了iptables的问题,那么流量就恢复了正常,如下图
四、Facebook ATC 内核不支持bridge的方式。
虽然我们知道了是iptables的使用姿势问题,但是我们使用facebook的ATC框架,这些代码都封在内核中,并且atc并不支持bridge的方式,针对这些问题,所以需要对atc的内核源码进行研究,并进行相应的修改。最终发现了最终设置iptables的地方
原来的iptables的配置
那么我们需要对原来的iptables策略进行修改,如下
修改完成之后,将服务器代码更新,服务重启即可,效果图如下
后续可能会帮他们新增一个支持bridge方式的功能。
五、弱网络服务如何后台运行。
借助nohup命令进行,不过如果服务挂了,需要手动重启。
nohup atcd --atcd-lan eth1.54 --atcd-wan eth0.54 &
nohup python2.7 manage.py runserver 10.54.0.20:8000 &
通过上述步骤,就完成了一个企业级别的弱网络模拟平台搭建,当然这只是搭建过程,关于弱网络的展示页面,功能都需要大家自行开发。
最后,希望能帮到有需要的同学,欢迎讨论 。