原文:http://blog.csdn.net/dog250/article/details/7354590安全
提及IEEE 802.1q,都知道是VLAN,提及VLAN,基本上也没有盲区,网络基础。然而说到配置,基本全部人都能顺口溜同样说出Cisco或者H3C设备的配置命令,对于Linux的VLAN配置却存在大量的疑问。这些疑问之因此存在我以为有两点缘由:
1.对VLAN的本质仍是没有理解。
无论你的Cisco/H3C命令敲得再熟练,若是看不懂Linux的vconfig,那么也将没法掩饰你对概念理解的浅显;
2.对Linux实现虚拟网络设备风格不熟悉
网络
可能你已经十分理解802.1q了,也许还看过了IEEE的文档,然而却对Linux的Bridge,tap,bond等虚拟设备不是很理解,那么也将没法顺利配置VLAN。函数
对于VLAN概念的理解,有几点要强调:
1.VLAN分离了广播域;
2.单独的一个VLAN模拟了一个常规的交换以太网,所以VLAN将一个物理交换机分割成了一个或多个逻辑交换机;
3.不一样VLAN之间通讯须要三层参与;
4.当多台交换机级联时,VLAN经过VID来识别,该ID插入到标准的以太帧中,被称做tag;
5.大多数的tag都不是端到端的,通常在上行路上第一个VLAN交换机打tag,下行链路的最后一个VLAN交换机去除tag;
6.只有在一个数据帧不打tag就不能区分属于哪一个VLAN时才会打上tag,能去掉时尽早要去掉tag;
7.最终,IEEE 802.1q解决了VLAN的tag问题。除了IEEE 802.1q,其他的都是和实现相关的,虽然Cisco和H3C的实现很相似,Linux能够和它们有大不一样。
关 键看最后3点,也就是3,4,5。这是VLAN最难理解的部分,不过一旦理解了,VLAN也就不剩下什么了。为了使得叙述上以及配置上更加的方 便,Cisco以及其余的厂商定义了不少的细节,而这些细节在IEEE 802.1q标准中并无被定义,这些细节包括但不局限于如下几点:
工具
我 们实则没有必要去深究Cisco/H3C的命令以及到底那三类端口类型有何区别,之因此有三类端口类型彻底是为了将VLAN的概念(最终的IEEE 802.1q标准)很方便的用起来。说白了,trunk端口的存在是由于不得已,由于有属于多个VLAN的数据帧要经过单一的物理链路,不打tag是没法 区分各自属于哪一个VLAN的,因而就有了IEEE 802.1q这个标准,定义了一个tag插入到以太帧中,为了使这个理论性的东西被使用起来,厂商便定义了一系列的概念性的东西,好比和tag相关的链路 就是trunk链路之类。
因而乎,咱们能够彻底抛开任何的配置命令,抛开任何厂商定义的东西,彻底按照IEEE 802.1q标准以及咱们的需求来理解VLAN,这样下来以后,你绝对能够在Linux上完美实现任何VLAN配置了。首先咱们定义一下咱们的需求以及满 足该需求的网络拓扑,关键看如何接线。
spa
从 上述1.2能够看出,为了节省线缆和避免环路,两个VLAN交换机的两个端口之间的同一条链路须要承载不一样的VLAN数据帧,为了使彼此可以识别每一个数据 帧到底属于哪一个VLAN,十分显然的办法就是为数据帧打上tag,所以上述1.2中的端口J和端口K之间的链路上的数据帧须要打tag,端口J和端口K都 同属于两个VLAN,分别为VLAN m和VLAN n。换句话说,只要一个端口须要传输和接收属于多个VLAN的数据帧,那么从该端口发出的数据帧就要打上tag,从该端口接收的数据帧能够经过tag来识 别它属于哪一个VLAN,用Cisco/H3C等厂商的术语来说,它就是trunk端口,两个trunck端口之间的链路属于trunk链路。
咱们知道,通常而言,咱们的PC机直接链接在常规二层交换机或者支持VLAN的交换机端口上,而咱们的PC机发出的通常都是常规的以太网数据帧,这些数据 帧是没有tag的,它们可能根本不知道802.1q为什么物,然而VLAN存在的目的就是把一些PC机划在一个VLAN中,而把另外一些PC机划在另外一个 VLAN中从而实现隔离,那么很显然的一种办法就是将支持VLAN的交换机的某些端口划在一个VLAN,而另外一些端口划在另外一个VLAN中,一个VLAN 的全部端口其实就造成了一个逻辑上的二层常规交换机,同属于一个VLAN的PC机链接在划在同一个VLAN的端口上,为了扩展VLAN,鉴于单台交换机端 口数量的限制,须要级联交换机,那么级联链路上则同时承载着不一样VLAN流量,所以级联链路则成为trunk链路,全部不是级联链路的链路都是直接链路, 用厂商术语来说就是access链路(注意,这里暂且不谈hybrid),天然而然的,access链路两端的端口都是和tag无关的,只须要作到“没有 tag直通,有tag去掉便可”,所以它能够链接PC机或者常规交换机以及VLAN交换机的非trunk端口。
VLAN的内容基本也就是以上那些了,分为三部分:
.net
隔离广播域,节省物理设备,隔离安全策略域
设计
为扩展VLAN的级联方案提供了一个标准的协议
blog
将某些端口划为一个VLAN,基于MAC地址什么的...
其实,至于怎么划分VLAN,标准中并无给出什么硬性的规定,只要可以保证属于同一VLAN的端口彻底不然IEEE 802系列的标准便可,换句话说就是属于同一VLAN的全部交换机的全部同一VLAN的端口彻底就是一个以太网便可,透传以太帧。
到此为止,咱们基本上已经忘了配置trunk,access,基于端口划VLAN的命令了,脑子里面留下的只是VLAN的核心概念,使用这些核心的概念, 咱们就能够在Linux上配置完整的VLAN方案了,若是你去硬套Cisco的配置,那么结果只是悲哀。好比若是你问:如何在Linux上配置端口为 access,如何在Linux上将某些网卡划到一个VLAN...
理解Linux Bridge的都知道,Linux自己就能够实现多个Bridge设备,由于Linux的Bridge是软的,因此一个Linux Box能够配置多个逻辑意义的Bridge,而多个Bridge设备之间必须经过第三层进行通讯,加之第三层正是以太网的边界,所以一个Linux Box也就能够模拟多个以太网了,不一样的Bridge设备就能够表明不一样的VLAN。
接口
Linux 上的VLAN和Cisco/H3C上的VLAN不一样,后者的VLAN是现有了LAN,再有V,也就是说是先有一个大的LAN,再划分为不一样的VLAN,而 Linux则正好相反,因为Linux的Bridge设备是被建立出来的逻辑设备,所以Linux须要先建立VLAN,再建立一个Bridge关联到该 VLAN,建立VLAN很简单:
ifconfig eth0 0.0.0.0 up
vconfig eth0 10
ifconfig eth0.10 up
当 使用vconfig建立了eth0.10以后,它就是一个“真实意义”的虚拟网卡设备了,相似br0,tap0,bond0之类的,在这个虚拟网卡之下绑 定的是一个真实网卡eth0,也就是数据从eth0这块真实网卡发出,eth0.10中的“.10”表示它能够承载VLAN 10的数据帧,而且在经过eth0发出以前要打上tag。那么打tag这件事天然而然就是经过eth0.10这个虚拟设备的hard_xmit来完成的, 在这个hard_xmit中,打上相应的tag后,再调用eth0的hard_xmit将数据真正发出,以下图所示:
所以一个真实的物理网卡好比ethx,它能够承载多个VLAN的数据帧,所以它就是trunk端口了,以下所示:
Linux 的VLAN工具vconfig采用ethx.y的方式以ethx为trunk端口加入VLAN id为y的VLAN中。类比Cisco/H3C,咱们已经建立了trunk,总结一下:使用vconfig建立一个ethx.y的虚拟设备,就建立了一个 trunk,其中ethx就是trunk口,而y表明该trunk口链接的trunk链路能够承载的VLAN数据帧的id,咱们建立 ethx.a,ethx.b,ethx.c,ethx.d,就说明ethx能够承载VLAN a,VLAN b,VLAN c,VLAN d的数据帧。
接下来,咱们看一下如何建立access端口。首先注意,因为Linux的Bridge是虚拟的,逻辑意义的,所以能够先建立了VLAN以后,再根据这个VLAN动态的建立Bridge,而不是“为每个端口配置VLAN id”,咱们须要作的很简单:
建立VLAN:
ifconfig eth0 0.0.0.0 up
vconfig eth0 10
ifconfig eth0.10 up
为该VLAN建立Bridge:
brctl addbr brvlan10
brctl addif brvlan10 eth0.10
为该VLAN添加网卡:
ifconfig eth1 0.0.0.0 up
brctl addif brvlan10 eth1
ifconfig eth2 0.0.0.0 up
brctl addif brvlan10 eth2
...
这 就完了。今后,eth1和eth2就是VLAN 10的access端口了,而eth0则是一个trunk端口,级联VLAN的时候要用到,若是不须要级联VLAN,而仅仅须要扩展VLAN 10,那么你大可将eth1链接在一个二层常规交换机或者hub上...一样的,你能够再建立一个VLAN,一样经过eth0来级联上游VLAN交换机:
ifconfig eth0 0.0.0.0 up
vconfig eth0 20
ifconfig eth0.20 up
brctl addbr brvlan20
brctl addif brvlan20 eth0.20
ifconfig eth5 0.0.0.0 up
brctl addif brvlan20 eth5
以下图所示:
这 下基本就搞定了Linux上VLAN的配置,接下来还有一个内容,那就是VLAN之间的通讯。这个知识点最简单了,那就是使用路由,为此不少人把支持 VLAN的三层交换机和路由器等同起来。既然使用路由就须要一个IP地址做为网关,那么如何能寻址到这个IP地址天然就是一个不可回避的问题,咱们要把这 个IP配置在哪里呢?能够确定的是,必须配置在当前VLAN的某处,因而咱们有多个地方能够配置这个IP:
ip
其中的1和2实际上没有什么差异,本质上就是找一个能配置IP地址的地方,大多数状况下使用2,可是若是出现同一个VLAN在同一个Linux Box配置了两个trunk端口,那么就要使用Bridge的地址了,好比下面的配置:
brctl addbr brvlan10
brctl addif brvlan10 eth0.10
brctl addif brvlan10 eth1.10
ifconfig brvlan10 up
此 时有两个ethx.y型的虚拟接口,为了避免使路由冲突,只能配置一个IP,那么此IP地址就只能配置在brvlan10上了。无论配置在Bridge上还 是配置在ethx.y上,都是要走IP路由的,只要MAC地址指向了本地的任意的一个接口,在netif_receive_skb调用 handle_bridge的时候都会将数据帧导向本地的IP路由来处理。Linux做为一个软件,其并无原生实现硬件cache转发,所以对于 Linux而言,所谓的三层交换其实就是路由。
咱们看一下一个被打上tag的数据帧何时脱去这个tag,在定义上,它是从access端口发出时脱去的,然而在语义上,只要能保证access端口 发出的数据帧不带有tag便可,所以对于什么时候脱去tag并无什么严格的要求。在Linux的VLAN实现上,packet_type的func做为一个 第三层的处理函数来单独处理802.1q数据帧,802.1q此时和IP协议处于一个同等的位置,VLAN的func函数vlan_skb_recv正如 IP的处理函数ip_rcv同样。在Linux实现的VLAN中,只有当一个端口收到了一个数据帧,而且该数据帧是发往本地的时候,才会到达第三层的 packet_type的func处理,不然只会被第二层处理,也就是Bridge逻辑处理,Linux的原生Bridge实现并不能处理802.1q数 据帧,甚至都不能识别它。整个trunk口收发数据帧,IEEE 802.1q帧处理,以及VLAN间通讯的示意图以下:
到 此为止,Linux的VLAN要点基本已经说完了,有了这些理解,我想设计一个单臂Linux Box就不是什么难事了,单臂设备最大的优点就是节省物理设备,同时还能实现隔离。这个配置不复杂,若是不想用VLAN实现的话也能够用ip addr add dev ...增长虚拟IP的方式来实现,然而用VLAN实现的好处在于能够和既有的三层交换机进行联动,也能够直接插在支持标准的IEEE 802.1q的设备的trunk口上。
机制搭台,策略唱戏。既然VLAN的实现机制已经了然于胸了,那么它的缺点估计你也看到了,如何去克服呢?PVLAN说实在的是一个VLAN的替代方案。 解决了VLAN间的IP网段隔离问题,咱们在Linux上如何实现它呢?这倒也不难,无非就是在LAN上添加一些访问控制策略罢了,彻底能够用纯软件的方 式来实现,甚至均可以用ebtables/arptables/iptables来实现一个PVLAN。若是说VLAN是一个硬实现的VLAN的话,那么 PVLAN纯粹是一个软实现的VLAN,甚至都不须要划分什么VLAN,你们都处于一个IP网段,只须要配置好访问控制策略便可,使得同一IP子网的 Host只能和默认网关通讯,而之间不能通讯,因此说,即便你不知道“隔离VLAN”,“团体VLAN”之类的术语,实际上你已经实现了一个PVLAN 了。
1.你须要首先规划出你的网络拓扑而不是先去研究VLAN在Linux上如何配置以及如何实现;2.你须要深刻理解VLAN设计的初衷,该配置哪些东西;3.你须要知道对于VLAN哪些概念是核心,哪些概念并非必须的。4.无论基于什么平台配置VLAN,只有两点是必须的:a.哪些端口属于哪一个VLAN;b.哪一个端口是级联端口,属于多个VLAN。5.其它的都不用去死记硬背,都是浮云...