玩转Linux网络namespace-单机自环測试与策略路由
可是,仅凭4个光口怎么測试?起码你要有个“对端”啊。不论什么人应该都不想扛着三台机器在客户们之间跑来跑去測试其转发性能,当然你也不能指望客户那里就一定有你须要的“对端”设备,比方我们公司就没有这样的和万兆光口对接的设备,只是赶巧的是。那天还真有一台设备带有万兆光口。可是仅仅是碰巧了。
最佳的測试方式当然是不依赖不论什么外部设备了。显而易见的方法就是做自环。
RJ45口的双绞线能够做物理层自环。1/3。2/6短接就可以。这样一台机器的一块网卡自己就能够既发又收了,可是你能对照头发略粗的光纤做什么呢?真实的做法当然是用软件攻克了,在Linux上能够使用netns来解决。即net namespace。
netns是一个非常好玩的东西,它能够让你在一台机器上模拟多个网络设备。这样做的意义是非同一般的:
1.使用netns能够充分利用闲置的处理器资源,特别是你的多块网卡性能压不满CPU的时候;
2.使用netns能够将不同类型的网络应用隔离,针对每一类实施不同的策略。
3.使用netns有点玩虚拟化的意思。只是比虚拟机更灵活。
一个net namespace有自己独立的路由表。iptables策略。设备管理机构,和其他的netns全然隔离。比方你将eth0增加了netns1,那么netns2中的应用程序就看不到eth0。网卡设备管理仅仅是netns中的一个元素,还有非常多,比方你在netns1中配置的iptables策略对netns2中的数据包没有不论什么影响。总之,假设你懂Linux内核源代码,那么仅仅要附着有net结构体字段的那些结构。比方skb,net_device,都和netns有关。
那么我应该怎么做自环呢?我的设备有4个网卡。我希望1和4之间通信,通过2和3转发。它的逻辑拓扑例如以下:
PC1/eth0----PC2/eth1(forward)PC2/eth2----PC3/eth3
非常easy,将eth0和eth3设置在两个不同的netns。然后用线缆连接eth0和eth1。相同连接eth2和eth3,最后将eth0和eth1的IP地址设置在一个网段,将eth2和eth3的IP地址设置在还有一个不同的网段就可以。光说不练假把式,详细应该怎么做呢?相同非常easy:
1.增加两个netns
ip netns add t1
ip netns add t2
2.将eth0增加t1,而且设置IP地址
ip link set eth0 netns t1
此时再ifconfig就看不到eth0了,你甚至运行ls /sys/class/net也看不到eth0了,仅仅有运行ip netns exec t1 ls /sys/class/net才干看到。
ip netns exec t1 ifconfig eth0 192.168.1.200/24
3.将eth3增加t2。而且设置IP地址
ip link set eth3 netns t2
此时ifconfig就看不到eth3了。你甚至运行ls /sys/class/net也看不到eth3了,仅仅有运行ip netns exec t2 ls /sys/class/net才干看到。
ip netns exec t1 ifconfig eth3 172.16.1.200/24
4.设置eth1和eth2的地址
ifconfig eth1 192.168.1.1/24
ifconfig eth2 172.16.1.1/24
5.设置两个netns的默认路由
ip netns exec t1 route add default gw 192.168.1.1
ip netns exec t2 route add default gw 172.16.1.1
6.測试
在netns t1中ping netns t2中的eth3地址
ip netns exec t1 ping 172.16.1.200
上述配置之后,从eth0发出的包会通过网线到达eth1(而不是走local路由表的loopback),然后经过eth1的forward从eth2发出。经由网线到达目的地eth3杯接收。整个过程中就一台机器。展示出的效果好像三台机器的样子。有了这个机制,是不是再也不用为搭建測试环境而发愁了呢?
除了自环測试之外,netns还能够用于设置策略路由。这样的策略路由不须要ip rule。
试想一种场景,你同一时候运行了P1和P2两个程序。本机所在的局域网有两个出口到达外网。你希望P1通过gw1和外界通信。P2通过gw2和外界通信,约束条件是你的机器仅仅有一张网卡eth0,怎么办呢?通过iptables为P1和P2的数据包打上不同的mark,然后通过ip rule设置策略路由无疑能够解决,另外直接在P1和P2应用程序中用setsockopt也是能够设置ipmark的,这就不须要iptables了。然而这一切都过时了,2014年我须要一种不同的方式。
我不知道怎么表达我思考的过程,可是给出一个操作序列是简单的事情,由于照着这么做确实能够满足需求,然后看到这篇文章的人照着操作步骤倒推回去,就能够得到一个思考过程。首先你要明确的是Linux内核支持一种虚拟网卡类型。即veth,一般而言veth是成对的,从一个veth发出的数据包能够直接到达它的peer veth,感兴趣的能够看Linux内核的drivers/net/veth.c。和drivers/net/tun.c没什么不同,更简单些罢了。第一步要做的就是建立一对veth:
ip link add veth1 type veth peer name veth2
此时系统中除了eth0之外又多了两块网卡,全部的网卡为lo。eth0,veth1。veth2。
中间隐含着一个事实。即veth1和veth2之间有一条虚拟的链路将两块网卡连接起来,就好像一条双绞线连接的两块物理网卡一样。我如今希望P1的数据包通过veth1发出。然后自然而然地就能发到veth2,可是随后怎么通过eth0发到物理线路呢?太简单。太简单。使用bridge吧:
brctl addbr br0
brctl addif br0 eth0 veth2
同一时候,veth1和br0所在的局域网设置在一个IP网段中,这下子就全通了。该二层网络的逻辑拓扑为:
veth1----veth2(bridge)eth0----gw(1,2)
怎么设置netns我本来不想说了,可是由于小小临时不跟我玩了,我还是写完吧。
首先将veth1设置到netns1(详细怎么创建netns,不再赘述)并设置路由:
ip link set veth1 netns netns1
ip netns exec netns1 route add default gw $gw1
route add default gw $gw2
这就完了?是的,完事了。
其实,保留br0的默认netns就可以,没有必要创建netns2了。接下来须要做的就是启动P1和P2了:
ip netns exec netns1 P1
P2
好了,一切结束。
我始终都认为。在Linux上一般都是不用改动源代码就能解决这个问题,可是我还是喜欢改动代码,原因何在?非常easy,源代码非常容易获得,而且源代码非常容易改动,我走火入魔般地写了大量的Netfilter扩展以及做了大量的nf_conntrack改动。甚至还增加了一些该死的socket filter...尽管这些行为都是自娱自乐型的。并没有被应用在工作中,可是这些行为说明我不是网络管理员,而是一名程序猿。哈哈,自封的资深软件project师(我还是认为这些成果能被应用)。然而,做一名技术精湛的网络管理人员的难度却远远超过做程序猿的难度。这不,重新遇到了OpenVPN的多实例问题。我认为,单纯的程序猿搞不定它。单纯的网管也不行。
TAP模式的多实例已经被我用Linux Bridge完美蹂躏了。可是TUN模式的多实例问题仍然没有完美的方案。尽管改动tun驱动。使用broadcast mode bonding+tun filter能够解决。可是我还是认为那是一种走火入魔的方式。因此就算在公司我也没能将整个调试測试进行下去,结果落了个不了了之,其实,是我太不喜欢那种方式。
tun的IP filter是我改出来的方案。并非标准的。能不能使用标准的方式进行寻址呢?使用netns,答案就是肯定的。
假设在GW上启动了2个OpenVPN实例ovpn1和ovpn2,虚拟网卡分别为tun1和tun2。在client-connect脚本中得知ovpn2负责N1,ovpn2负责N2。
如今问题的关键是。GW后方出发的数据包如何知道是将数据包发送到tun1还是tun2。这个推断能不能自己主动进行?假设使用netns,那就是能够的,我能够将2个tun分别设置在不同的netns,然后每个netns相应一个同处一个netns的veth虚拟网卡,这些veth的peer们处在另外一个netns中。这样就能够实现IP层TUN模式虚拟网卡到以太网的TAP模式虚拟网卡的适配。最后将这些peer们Bridge成一个br0,那么TUN模式的OpenVPN就能和TAP模式的OpenVPN採用同一种方式处理了。
无论如何,当你玩弄netns的时候,你要知道你并非在玩弄冷酷无情的虚拟化操作系统,也不是真的模拟了两台物理上相互隔离的机器,由于尽管两个程序的网络是隔离的,可是文件系统却是共享的。你要时刻准备着,使用网络隔离和使用内存,文件系统共享相结合。
将一台机器既能够作为多台机器使用,又能够作为一台机器共享资源!
无论如何。当你玩弄netns的时候,你要知道你并非在玩弄冷酷无情的虚拟化操作系统,也不是真的模拟了两台物理上相互隔离的机器。由于尽管两个程序的网络是隔离的,可是文件系统却是共享的。你要时刻准备着,使用网络隔离和使用内存,文件系统共享相结合。将一台机器既能够作为多台机器使用。又能够作为一台机器共享资源!
理解了上述的样例和最后的总结,那么我来发问,单网卡或者没有网卡怎么玩自环?这个需求可能就是为了測试一下协议栈而已。
略去思考的过程,非常easy,多加一个层次。比方你有一台机器一块网卡也没有,那么你仅仅须要以下的命令就能够在你的机器上实现IP转发或者bridge转发了:
ip link add v1 type veth peer name vp1
ip link add v2 type veth peer name vp2
brctl addbr br0
brctl addif vp1 vp2
ifconfig vp1 up
ifconfig vp2 up
sysctl -w net.ipv4.ip_forward=1
ip netns add t1
ip netns add t2
ip link set v1 netns t1
ip link set v2 netns t2
ip netns exec t1 ifconfig v1 1.1.1.1/24
ip netns exec t2 ifconfig v2 1.1.1.2/24
ip netns exec t1 ping 1.1.1.2
...
玩转Linux网络namespace-单机自环測试与策略路由的更多相关文章
- Caffe-python interface 学习|网络训练、部署、測试
继续python接口的学习.剩下还有solver.deploy文件的生成和模型的測试. 网络训练 solver文件生成 事实上我认为用python生成solver并不如直接写个配置文件,它不像net配 ...
- linux mysql 卸载,安装,測试全过程
Mysql卸载 yum remove mysql mysql-server mysql-libs compat-mysql51 rm -rf /var/lib/mysql rm /etc/my.cnf ...
- linux 网络虚拟化: network namespace 简介
linux 网络虚拟化: network namespace 简介 network namespace 是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自的网络栈信息.不管是虚拟机还是 ...
- 【转】理解Docker容器网络之Linux Network Namespace
原文:理解Docker容器网络之Linux Network Namespace 由于2016年年中调换工作的原因,对容器网络的研究中断过一段时间.随着当前项目对Kubernetes应用的深入,我感觉之 ...
- (四)跟我一起玩Linux网络服务:DHCP服务配置之中继代理
继第三部分的DHCP服务器的设置成功,我们来做一个中继代理服务器的配置吧. 我们的虚拟机结构如图: 具体参考: (一)跟我一起玩Linux网络服务:DNS服务——BIND(/etc/named.con ...
- Java I/O演进与Linux网络I/O模型
参考文章: 简书-浅谈Linux五种IO:http://www.jianshu.com/p/486b0965c296 一.linux基础概念 1.1 内存空间 linux系统中的使用的是虚拟存储器,即 ...
- [Linux网络、命名空间、veth设备对、docker的host模式、container模式、none模式、brideg模式、网桥的增删查,容器与网桥的连接断开]
[Linux网络.命名空间.veth设备对.docker的host模式.container模式.none模式.brideg模式.网桥的增删查,容器与网桥的连接断开] 网络名称空间 为了支持网络协议栈的 ...
- Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网
学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...
- Netruon 理解(12):使用 Linux bridge 将 Linux network namespace 连接外网
学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...
随机推荐
- Jquery的一些取值
//获取当前节点的html代码(包括当前节点),prop用于获取与设置Html元素的原生属性 $("#tmpMsgObj").prop("outerHTML") ...
- ORA-02396: exceeded maximum idle time, please connect again的原因
一般为了防止过多活动的session占用资源,可以对允许连接到数据库的session个数,已连接到数据库的session空闲时间等进行限制(当然也可以对尝试连接次数等其它很多内容进行限制).方式就是可 ...
- pexpect-pxssh-登陆Linux-执行命令
#!/usr/bin/python import pexpect import pxssh try: remote=pxssh.pxssh() hostname=raw_input('hostname ...
- ie6与固定定位fixed,+ 条件注释格式注意
ie6并不支持position:fixed, ie7+都支持fixed定位, ie6固定定位实现方法1: <!DOCTYPE html> <html> <head> ...
- HDU 1847 Good Luck in CET-4 Everybody!
题解:巴什博弈,2^k+1=3N或2^k2=3N,所以3N为P-position,3N+r为N-position. #include <cstdio> int main(){ int n; ...
- qwebkit - Open new window after click using QT - Stack Overflow
qwebkit - Open new window after click using QT - Stack Overflow Open new window after click using QT
- [dfs+水] hdu 4462 Scaring the Birds
题意: N*N的矩阵中有M个点能够放稻草人.且给覆盖距离R 每一个稻草人能覆曼哈顿距离R以内的点 问最少须要多少个稻草人 思路: 由于范围非常小,直接能够暴力 注意稻草人所在的位置是不须要被覆盖的 代 ...
- hdu3416 Marriage Match IV【最短路+最大流】
转载请注明出处,谢谢:http://www.cnblogs.com/KirisameMarisa/p/4297581.html ---by 墨染之樱花 题目链接:http://acm.hdu.ed ...
- MVC 常用方法
1. 后台 action方法里添加错误消息到字典中(key,value) ModelState.AddModelError("Error", "参数传输有误,请重新尝试! ...
- 解决 win10 预览版开始菜单打不开的问题
除了该文章[http://jingyan.baidu.com/article/64d05a025d2668de55f73b9e.html]里面说的解决方法之外,我只加上一点 . 打开本机防火墙,或者调 ...