linux 网桥的配置与实现

陌路散爱 提交于 2019-12-20 04:05:37

==================================================================================
from: http://www.ibm.com/developerworks/cn/linux/kernel/l-netbr/index.html
ALinux网桥的实现分析与使用





文档选项



未显示需要 JavaScript
的文档选项




打印本页



将此页作为电子邮件发送
级别: 初级
祝顺民
(
[email=getmoon@163.com?subject=ALinux%E7%BD%91%E6%A1%A5%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%88%86%E6%9E%90%E4%B8%8E%E4%BD%BF%E7%94%A8&cc=]getmoon@163.com[/email]
)
XML error:  Please enter a value for the author element's jobtitle attribute, or the company-name element, or both.
2004 年  3 月  09 日

文分析了linux
2.4.x内核的网桥的实现方法,并且描述了如何使用2.4中的网桥。网桥,类似于中继器,连接局域网中两个或者多个网段。它与中继器的不同之处就在于它
能够解析它收发的数据,读取目标地址信息(MAC),并决定是否向所连接网络的其他网段转发数据包。为了能够决策向那个网段发送数据包,网桥学习接收到数
据包的源MAC地址,在本地建立一个以MAC和端口为记录项的信息数据库。
      
一、Linux内核网桥的实现分析
      
Linux 内核分别在2.2 和 2.4内核中实现了网桥。但是2.2 内核和 2.4内核的实现有很大的区别,2.4中的实现几乎是全部重写了所有的实现代码。本文以2.4.0内核版本为例进行分析。
      
在分析具体的实现之前,先描述几个概念,有助于对网桥的功能及实现有更深的理解。
      
    • 冲突域
                

      个冲突域由所有能够看到同一个冲突或者被该冲突涉及到的设备组成。以太网使用C S M A / C D(Carrier Sense
      Multiple Access with Collision
      Detection,带有冲突监测的载波侦听多址访问)技术来保证同一时刻,只有一个节点能够在冲突域内传送数据。网桥或者交换机,构成了一个冲突域的边
      界。缺省情况下,网桥中的每个端口实际上就是一个冲突域的结束点。
              
    • 广播域
                

      个广播域由所有能够看到一个广播数据包的设备组成。一个路由器,构成一个广播域的边界。网桥能够延伸到的最大范围就是一个广播域。缺省的情况下,一个网桥
      或交换机的所有端口在同一个广播域中。VLAN技术可以把交换机或者网桥的不同端口分割成不同的广播域。一般情况下, 一个广播域代表一个逻辑网段。
              
    • 网桥中的CAM表
                
      网桥和交换机一样,为了能够实现对数据包的转发,网桥保存着许多(MAC,端口)项。所有的这些项组成一个表,叫做CAM表。每个项有超时机制,如果一定时间内未接收到以这个MAC为源MAC地址的数据包,这个项就会被删除。
              
            
              
      图1:一个交换网络的逻辑图
              


            
            
      在Linux内核网桥的实现中,一个逻辑网段用net_bridge结构体表示。一个逻辑网段需要保留的信息有:
            
    • 本逻辑网段中所有的端口(port_list)
                
      每个端口用net_bridge_port结构体来表示,从net_bridge_port结构体中可以看出,它主要有:
              
    • 逻辑网段中的下一个端口(next)
    • 本端口所属的逻辑网段(br)
    • 本端口所指向的物理网卡(dev)
    • 本端口在网桥中的编号(port_no)
    • 用于生成树管理的信息

    •           
      一个逻辑网段中可以具有很多个端口,所有的端口都挂在以port_list为链表头的链表上。
      本网段中CAM表(hash[BR_HASH_SIZE])
                
      CAM表中的每个项用net_bridge_fdb_entry结构体代表,每项中有:
              
    • 用于CAM表连接的链表指针(next_hash,pprev_hash)
    • 此项当前的引用计数(use_count)
    • MAC地址(addr)
    • 此项所对应的端口(dst)
    • 处理MAC超时(ageing_timer)
    • 是否是本机的MAC地址(is_local)
    • 是否是静态MAC地址(is_static)

    •           
      一个逻辑网段中的所有表项形成一个CAM表,他们之间的组织关系是一个HASH链表。HASH链的个数为BR_HASH_SIZE(256)。
      本逻辑网段用于和外部通信的虚拟网络设备(dev)
                
      Linux网桥可以在网桥上为每个逻辑网段配置一个IP,用于和外部通信。实际上这个IP不是配置在一个特定的物理网卡上面, 而是建立一个虚拟的网卡,虚拟网卡可以附在每个同一逻辑网段的物理网卡上,让这个网卡可以象所有的物理网卡一样工作。从而使网桥可以和外部通信。
              
    • 本逻辑网段虚拟网卡的统计数据(statistics)
                
      按照Linux网卡驱动的接口,一个网卡的统计信息是由每个网卡的私有数据处理的。一般的写法是用dev->priv来指向每个网卡的统计数据。网卡的get_stats方法就是用来读取统计数据。
              
    • 用户一个网段的生成树(STP)信息
            
      以上对几个结构体的描述和分析可以通过下图来表示:
            
              
      图2:Linux网桥数据结构描述图
              


            
            
      描述了网桥的数据结构后,就可以开始数据包处理流程的分析。
            
      网桥处理包遵循着以下几条原则:
            
    • 在一个接口上接收到的包不会再在那个接口上发送这个数据包。
    • 每个接收到的数据包都要学习其源MAC地址。
    • 如果数据包是多播包或广播包,则要在同一个网段中除了接收端口外的其他所有端口发送这个数据包,如果上层协议栈对多播包感兴趣,则需要把数据包提交给上层协议栈。
    • 如果数据包的目的MAC地址不能在CAM表中找到,则要在同一个网段中除了接收端口外的其他所有端口发送这个数据包。
    • 如果能够在CAM表中查询到目的MAC地址,则在特定的端口上发送这个数据包,如果发送端口和接收端口是同一端口,则不发送。
            
      在网络软中断处理函数net_rx_action中,嵌入了handle_bridge用于把数据包skb送入网桥模块处理。
             
            #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
                              if (skb->dev->br_port != NULL &&
                                  br_handle_frame_hook != NULL) {
                                      handle_bridge(skb, pt_prev);
                                      dev_put(rx_dev);
                                      continue;
                              }
      #endif

            
      br_handle_frame_hook是网桥处理
      接收到数据包的中入口,网桥初始化(br_init)的时候,把br_handle_frame_hook赋值为br_handle_frame。
      skb->dev->br_port用于判断接收到这个数据包的接口是否是网桥中的一个端口,如果
      是,skb->dev->br_port不为NULL,那么数据包应该由网桥处理。反之,数据包由上层协议栈处理。网桥中虚拟网卡对应的数据
      包就是在这个判断点时不再进入网桥。(实际上虚拟网卡并不会自己主动接收数据包,而是在网桥处理中把数据包向本地上层协议栈提交,并且修改了
      skb->dev,使得数据包不会多次进入桥处理代码)。
            
      前面提到,网桥处理接收包的入口是br_handle_frame(net/bridge/br_input.c)函数。
            
      br_handle_frame
      函数首先从skb中获得这个包属于的逻辑网段。然后调用__br_handle_frame进行转发处理。
      br_handle_frame函数里有一个值得了解的地方,里面有一个加读锁。因为在转发中需要读CAM表,所以必须加读锁,避免在这个过程中另外的内
      核控制路径(如多处理机上另外一个CPU上的系统调用)修改CAM表。
            
      对输入包的转发决策都是在__br_handle_frame函数中。这个函数的处理可以分为以下几个部分:
            
    • 如果网桥的虚拟网卡处于混杂模式,那么每个接收到的数据包都需要克隆一份送到AF_PACKET协议处理体(网络软中断函数net_rx_action中ptype_all链的处理)。
                
                

                if (br->dev.flags & IFF_PROMISC) {
                      struct sk_buff *skb2;
                      skb2 = skb_clone(skb, GFP_ATOMIC);
                      if (skb2) {
                              passedup = 1;
                              br_pass_frame_up(br, skb2);
                      }
              }

                
                
              
    • 如果源MAC地址是多播或者是广播地址,那么这个包格式是错误的,简单的丢弃。
                
                

                                if (skb->mac.ethernet->h_source[0] & 1)
                      goto freeandout;
                      

                
                
              
    • 如果是一个多播包,则需要向本机的上层协议栈传送这个数据包(如果在之前没有向上提交的话,即passedup为0。如果为1,则前面已经发送了,现在就不需要提交了,在后面中的处理都是一样的)。
                
                

                        if (!passedup &&
                  (dest[0] & 1) &&
                  (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL)) {
                      struct sk_buff *skb2;
                      skb2 = skb_clone(skb, GFP_ATOMIC);
                      if (skb2) {
                              passedup = 1;
                              br_pass_frame_up(br, skb2);
                      }
              }
              

                
                
              
    • 如果启动了生成树协议,一个生成树包需要由生成树协议处理模块单独处理。如果不支持,则这个包的目的MAC肯定在CAM中查询不到,所以是向所有的端口发送(除接收口)。这样才不会影响整个网络的生成树协议运行。
                
                

                                if (br->stp_enabled &&
                  !memcmp(dest, bridge_ula, 5) &&
                  !(dest[5] & 0xF0))
                      goto handle_special_frame;
                      

                
                
              
    • 如果接收端口不是处于LEARNING或者FORWARDING,那么就学习这个包的源MAC地址,或者更新CAM表中相应项的定时器。
                
                

                if (p->state == BR_STATE_LEARNING ||
                  p->state == BR_STATE_FORWARDING)
                      br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);

                
                
              
    • 如果是一个多播包或广播包,则调用br_flood函数向每个口发送(除接收口)这个数据包。如果之前没有提交上层协议,则需要克隆一个包提交上层协议。
                
                

                        if (dest[0] & 1) {
                      br_flood(br, skb, 1);
                      if (!passedup)
                              br_pass_frame_up(br, skb);
                      else
                              kfree_skb(skb);
                      return;
              }
              

                
                
              
    • 用接收到数据包的目的MAC地址查询CAM表。
                
                

                dst = br_fdb_get(br, dest);

                
                
              
    • 查询CAM表后,如果能够找到表项,并且目的MAC是到本机的虚拟网卡的,那么就需要把这个包提交给上层协议。网桥就是通过这个地方的处理和外部通信,实现远程管理的目的。
                
                

                        if (dst != NULL && dst->is_local) {
                      if (!passedup)
                              br_pass_frame_up(br, skb);
                      else
                              kfree_skb(skb);
                      br_fdb_put(dst);
                      return;
              }
              

                
                
              
    • 如果查询CAM表有结果,并且目的MAC不是到本地的,那么就通过调用br_forward发送到特定的端口。
                
                

                        if (dst != NULL) {
                      br_forward(dst->dst, skb);
                      br_fdb_put(dst);
                      return;
              }
              

                
                
              
    • 如果在CAM表中查询不到数据包的目的MAC地址,那么就需要向别的每个端口发送这个数据包。调用br_flood来进行这个处理。
                
                

                        br_flood(br, skb, 0);
              return;
              

                
                
              
            
      在br_forward和br_flood函数中都必须判断源接口和目的接口是否是同一个,如果是同一端口,就不发送这个数据包。数据包的最后发送都是通过统一的发送接口dev_queue_xmit函数来完成的。
            
      以下就是数据包的处理流程:
            
              
      图3:数据包处理流程图
              


            
            

      面多次提到网桥的虚拟网卡,实际上在网桥中,这个网卡存在着一个net_device结构(在net_bridge里),但是不存在着实际的物理设备,而
      是附在网桥中每个物理网卡上面。这个虚拟网卡的支持函数在(br_device.c)。因为是虚拟的网卡,所以没有物理中断产生,每个需要发送到这个设备
      的数据包都是靠判断数据包的目的MAC地址来决定是否需要提交到本地上层协议栈(在__br_handle_frame判断)。
            

      果数据包需要向上层协议提交,都调用br_pass_frame_up函数来处理。在这个函数中,首先把skb->dev设置成
      br->dev。然后再模拟在中断中处理数据包一样,进行相应的处理,
      然后调用netif_rx放入接收队列。这里有一个要十分注意的地方,这个数据包的skb->dev已经变成br->dev。所以在网络接收
      软中断处理函数net_rx_action中不会再次进入handle_bridge了。
             
            static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
      {
              br->statistics.rx_packets++;
              br->statistics.rx_bytes += skb->len;
              skb->dev = &br->dev;
              skb->pkt_type = PACKET_HOST;
              skb_pull(skb, skb->mac.raw - skb->data);
              skb->protocol = eth_type_trans(skb, &br->dev);
              netif_rx(skb);
      }

            





      回页首
      二、配置内核 2.4 Linux 网桥
            
      要配置网桥,首先需要网桥的配置工具bridge-utils。这个配置程序的源代码可以在
              
      http://bridge.sourceforge.net/bridge-utils/
      下载。编译成功之后,就可以生成网桥配置的主要工具brctl。
            
            
      下面,我们将用brctl对以下网络拓扑配置网桥,使Linux能够对数据包进行交换。
            
              
              


            
            

      图中,有五台主机。其中中间那台主机装有linux
      ,安装了网桥模块,而且有四块物理网卡,分别连接同一网段的其他主机。我们希望其成为一个网桥,为其他四台主机(IP分别为192.168.1.2
      ,192.168.1.3,192.168.1.4,192.168.1.5)
      之间转发数据包。同时,为了方便管理,希望网桥能够有一个IP(192.168.1.1),那样管理员就可以在192.168.1.0/24网段内的主机
      上telnet到网桥,对其进行配置,实现远程管理。
            
      前一节中提到,网桥在同一个逻辑网段转发数据包。针对上面的拓扑,这个逻辑网段就是192.168.1.0/24网段。我们为这个逻辑网段一个名称,br_192。首先需要配置这样一个逻辑网段。
             
            # brctl addbr br_192                        (建立一个逻辑网段,名称为br_192)

            
      实际上,我们可以把逻辑网段192.168.1.0/24看作使一个VLAN ,而br_192则是这个VLAN的名称。
            

      立一个逻辑网段之后,我们还需要为这个网段分配特定的端口。在Linux中,一个端口实际上就是一个物理网卡。而每个物理网卡的名称则分别为
      eth0,eth1,eth2,eth3。我们需要把每个网卡一一和br_192这个网段联系起来,作为br_192中的一个端口。
             
            # brctl addif br_192 eth0                        (让eth0成为br_192的一个端口)
      # brctl addif br_192 eth1                        (让eth1成为br_192的一个端口)
      # brctl addif br_192 eth0                        (让eth2成为br_192的一个端口)
      # brctl addif br_192 eth3                        (让eth3成为br_192的一个端口)

            
      网桥的每个物理网卡作为一个端口,运行于混杂模式,而且是在链路层工作,所以就不需要IP了。
             
            # ifconfig eth0 0.0.0.0
      # ifconfig eth1 0.0.0.0
      # ifconfig eth2 0.0.0.0
      # ifconfig eth3 0.0.0.0

            
      然后给br_192的虚拟网卡配置IP:192.168.1.1。那样就能远程管理网桥。
             
            # ifconfig br_192 192.168.1.1

            
      给br_192配置了IP之后,网桥就能够工作了。192.168.1.0/24网段内的主机都可以telnet到网桥上对其进行配置。
            
      以上配置的是一个逻辑网段,实际上Linux网桥也能配置成多个逻辑网段(相当于交换机中划分多个VLAN)。具体的方法可以参考bridge-util中的HOWTO。
            





      回页首
      三、总结
            
      本文分析了Linux网桥的实现,并且举例说明如何配置网桥。 通过学习网桥的实现,就能够了解网络中二层交换的原理。
            
      网桥和交换机的功能非常相似,所以在分析网桥的时候,绝大多数情况下可以用交换机的处理方法来分析网桥的动作。
          
      关于作者



      祝顺民,网名:getmoon。目前从事防火墙开发,致力于网络的研究和开发,分析linux内核。经常出没于
              
      www.linuxforum.net
      的内核板块。希望于爱好者们共同探讨。email:
              
      [email=getmoon@163.com?cc=]getmoon@163.com[/email]
            
      ================================================
      linux协议栈之网桥实现(从网桥配置说起(二))
      ------------------------------------------
      本文系本站原创,欢迎转载!
      转载请注明出处:http://ericxiao.cublog.cn/
      ------------------------------------------
      关于网桥:
      网桥是一个二层设备,在深入之前可以把它当成一个二层的交换机。它在二层协议上转发数据。
      网桥为了转发数据,维持了一个端口与MAC的对应表,通常通为CAM表。根据这张表可以把数据送往相应的端口进行发送.
      网桥的转发过程为:
      1:接收到一个包。判断自己的CAM表中是否含包它此包的源地址.如果没有,则把源地址与端口更新至于CAM表.
      2:判断包是否是送给本机,如果是,则送往本机上层协议栈处理。如果不是,则查寻CAM表。找到相应的出口。
      3:如果找到出口,则将此包送至出口。如果不存在,将会在各端口发送。
      4:如果CAM表中对应表项在规定时间之内没有得到更新,则删除此项。
      网桥的配置:
      Brctl是一个比较好的配置网桥的工具。它的源代码和配置方法极其简单。我们将从网桥的配置流程说起,看linux内核是怎样一步步管理的。
      首先,创建一个网桥: brctl addbr br0             (建立一个br0的网桥)
      然后,将接口添加进网桥:brctl addif  br0 eth0   (将eth0和eth1添加进网桥br0)
                                                     brctl addif   bro eth1
      OK,网桥现在就配置好了。这台linux的主机可以当作交换机使用了,从eth0的包都可以转发到eth1。
      现在,我们看下代码中如何进行处理
      首先 brctl addbr 。查看brctl的代码发现它调用了:ioctl(br_socket_fd, SIOCBRADDBR, brname);
      然后 brctl addif    在brctl的代码中调用了:ioctl(br_socket_fd, SIOCBRADDIF, &ifr);
      呵呵。Brctl的代码很简单吧,只是调用了用户空间的配置工具ioctl.
      Linux网桥分析:
      好了,现在就可以进入内核分析网桥模式了:
      static int __init br_init(void)                                                (net/brige/br.c)
      {
               //分配slab缓冲区
               br_fdb_init();
      //网桥的netfiter处理,将在以后的章节中分析
      #ifdef CONFIG_BRIDGE_NETFILTER
               if (br_netfilter_init())
                         return 1;
      #endif
               //用户空间ioctl调用的函数
               brioctl_set(br_ioctl_deviceless_stub);
               //接收到数据包的处理,也就是我们在上面netif_receive_skb函数中看到的br_handle_frame_hook
               br_handle_frame_hook = br_handle_frame;

      #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
               br_fdb_get_hook = br_fdb_get;
               br_fdb_put_hook = br_fdb_put;
      #endif
               //在netdev_chain通知链表上注册。关于通知链表,在前面已经介绍过,这里不再讨论了
               register_netdevice_notifier(&br_device_notifier);

               return 0;
      }
      ==================================================================================
      from: http://www.linux-cn.com/html/linux/system/20070505/27862.html
      使用Linux创建网桥式防火墙
      来源:Linux-cn.com 作者:Webmaster 时间:2007-05-05 点击: [收藏] [投稿]
      作者:Henry Stilmack
      原文出处:http://www2.linuxjournal.com/articles/misc/0041.html
      翻译:ideal
        联合天文学中心在夏威夷岛的Manua Kea的14,000英尺高的山顶上拥有两个天文望远镜,还在Hilo市有自己的办公室及其他设施,该组织是是通过夏威夷大学连接到Internet上的,夏威夷大学在自己的B类IP地址范围内给天文中心分配了三个子网。以前天文中心的网络安全性是由出口路由器的 ACL(访问控制列表)连同Soloris或Linux系统的主机访问控制(tcpwrappers)来实现的。最近天文中心的一个主要英国资助基金会在一次审核后强烈推荐安装防火墙来增强网络的安全性。在对几种商业和免费的防火墙产品进行调研以后,发现它们都需要对内部网络的三个不同子网地址都重新进行分配,分配为192.168的内部地址。内部网络的在三个子网上共有超过200个节点,某些嵌入式微处理器系统甚至需要重新烧制EEPROM以实现IP变换,这是一个非常麻烦和庞杂的任务。因此就开始寻找透明防火墙解决方案,实现即能保持原有的地址分配,又能实现对内部网络的防护。
        Linux 2.2以上版本都支持以太网桥接方式。一个网桥的一个接口接收到数据报以后,通过检查目的MAC地址以后被转发到另外一个接口上,而不去检查源或目的IP地址。一个名为AC2I的法国公司发布了一个内核补丁实现在网桥化的接口上使用ipchains进行数据报过滤。这种解决方案能实现透明的防火墙,同时保证对内部网络提供上层的保护和访问控制。下面我们就讨论如何架设一个网桥式防火墙。
      1.硬件配置
        为了实现高效的防火墙和网络检测,系统CPU必须足够的强大和快速。该系统架设在一台拥有256M内存和500MHz的赛扬CPU系统之上。测试显示桥能满足一个10M以太网的速度要求,而不会出现丢包现象。系统需要三块网卡,其中两块网卡支持网桥的实现,另外一块用来实现对防火墙的管理。
        磁盘容量并不是很重要,但是所有的log信息应该被保存下来。若希望维护某些本地logging(用于某些配置和检测工具),则需要确保拥有足够的免费空间-防火墙和入侵检测记录往往非常庞大。
      2.安装Linux
        下面的讨论都基于Linux2.2.16(redhat7.0)版本内核,若使用2.4内核,iptables将会替代ipchains实现内核防火墙。
        首先进行标准的Linux安装,但是基本上不要选择任何应用软件包,甚至包括xinet/inetd,因为在该系统上不需要运行任何服务。不要安装编译 /开发工具,因为若系统被攻破则入侵者就不那么容易编译任何程序。但是需要安装Perl(某些报告工具是需要的)和OpenSSH(用于远程管理)。确保安装ipchains软件包-这对于就防火墙设置是必须的。一个web浏览器也许会很有用处。若你仅仅接收来自内部网络的时间更新那么安装NTP则不会有多大坏处。你可以选择安装某些X11应用,tcpwrapper及某些网络监控包 (whois,finger,tcpdump,traceroute,nc等等)。创建一个非root账号,使用该账号登录系统。
        安装时,仅仅配置一个主以太接口-该接口将是被保护网络的一个节点-为其配置一个固定的网络地址,此时应该将其连接到一个空的HUB上,在进行安全设置以后再将其连接到网络中。当系统安装完毕并重新启动时,在lilo引导系统时键入linux single以单用户模式引导进入系统,编辑/etc /hosts.allow来只允许管理机通过SSH来连接进入系统,然后重新启动按照正常模式引导进入系统。然后再将主以太接口连接到内部网络中。
      3.创建支持网桥方式的内核
        按照基本的内核编译步骤进行,只不过需要关闭大多数的选项开关,而仅仅打开一些必须的内核编译开关。
        进入到/usr/src目录下,拷贝内核源代码到一个新创建的linux-fw目录下:
            # cd /usr/src;mkdir linux-fw;cp -r linux-2.2.16 ./linux-fw 
            # rm linux;ln -s ./linux-fw linux
          
        对linux源代码打linux_brfw2补丁,该补丁为ipchains添加了一个名为bridgein的缺省规则链。该链将被用来存放网桥式防火墙规则,但是该规则链中的规则只能使用ACCEPT或DENY目标,使用REJECT及MASQ是没有意义的。可以从 http://ac2i.tzo.com/bridge_filter/处得到该补丁。
            # patch -p0 
      |linux host|
      | eth2=->
      +----------+
      >ifconfig eth0 down
      >ifconfig eth1 down
      >brctl addbr br0
      >brctl addif br0 eth0
      >brctl addif br0 eth1
      >ifconfig eth0 0.0.0.0
      >ifconfig eth1 0.0.0.0
      >ifconfig br0 192.168.10.1
      then, the virtual interface 'br0' can be used for dhcpd to serve ip address on multi-interface.
      ==================================================================================
      from: http://ansondrew.bokee.com/6414248.html
      浅析linux网桥设置MAC地址时的行为
      关键词: linux    网桥    MAC                                          
      先说现象
      brctl addbr br0
      ifconfig br0
      br0 MAC is 00:00:00:00:00:00
      brctl addif br0 eth1  (eth1 is xx:xx:xx:xx:xx:33)
      ifconfig br0
      br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, auto change
      brctl addif br0 eth2  (eth2 is xx:xx:xx:xx:xx:30)
      ifconfig br0
      br0 MAC is xx:xx:xx:xx:xx:30  same as eth2, For eth2 less than eth1, auto change
      ifconfig eth2 hw ether xx:xx:xx:xx:xx:50
      ifconfig br0
      br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, auto change
      ifconfig br0 hw ether xx:xx:xx:xx:xx:99
      ifconfig br0
      br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, NOT change
      ifconfig br0 hw ether xx:xx:xx:xx:xx:33  ;same as eth1
      ifconfig eth2 hw ether xx:xx:xx:xx:xx:20  ;less than eth1
      ifconfig br0
      br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, `ifconfig br0 hw` NOT effective
      ifconfig eth1 hw ether xx:xx:xx:xx:xx:50  ;upper op,we set br0 = eth1's MAC,now we change eth1 MAC
      ifconfig br0
      br0 MAC is xx:xx:xx:xx:xx:20  same as eth2, auto change
      结论:
        br0如果没有指定hw MAC, br0的MAC地址会根据bridge中port的变化,自动选择port中最小的一个MAC地址作为br0的MAC地址。
        br0只能指定port中有的interface的MAC作为br0的MAC地址。

      源代码分析:
        source code dir is: linux-2.4.x/net/bridge

        - br_device.c
            br_dev_setup() 注册了一些函数,其中  dev->set_mac_address = br_set_mac_address;  //这个就是ifconfig br0 hw ether调用的函数了
           
            static int  br_set_mac_address(struct net_device *dev, void *addr)
                {
                  struct net_bridge *br = dev->priv;
                  struct sockaddr *sa = (struct sockaddr *) addr;
                 
                。。。。。 
                //here ! copy MAC addr to br->preferred_id.addr
                  memcpy(br->preferred_id.addr, sa->sa_data, ETH_ALEN);
               
                  br_stp_recalculate_bridge_id(br);
               
                。。。。。
                }

        - br_stp_if.c
            static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};
           
            /* called under bridge lock */
            void br_stp_recalculate_bridge_id(struct net_bridge *br)
            {
              unsigned char *addr;
              struct net_bridge_port *p;
           
              //初始br0的MAC为00:00:00:00:00:00
              addr = br_mac_zero;
           
              p = br->port_list;
              while (p != NULL) {
                /* match against preferred address first */
                if (memcmp(p->dev->dev_addr, br->preferred_id.addr, ETH_ALEN) == 0) {
                  addr = p->dev->dev_addr;
                  //匹配port的MAC地址与首选MAC是否相符
                  break;
                }
               
                if (addr == br_mac_zero ||
                    memcmp(p->dev->dev_addr, addr, ETH_ALEN) dev->dev_addr;
           
                p = p->next;
              }
           
              //如果没有Port的话,就为0;
              //如果没有设置首选MAC,就等于最小的那一个。
              //如果设置了首选MAC,则首选MAC必须同其中一个port的MAC匹配,才等于首选MAC
              if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
                br_stp_change_bridge_id(br, addr);
            }

        - 什么时候会执行br_stp_recalculate_bridge_id呢
            - in br_device.c 中 br_set_mac_address()
            - in br_if.c 中 br_del_if() & br_add_if()
            - in br_notify.c 中 br_devic_event()的 NETDEV_CHANGEADDR 事件,该事件是任意port有修改addr就会触发的
            
           
      看过代码就很容易理解bridge在处理自身MAC地址时的行为了
      ==================================================================================
      from: http://hi.baidu.com/pengge168/blog/item/6e6f91fc98718afbfd037f27.html
      在linux下配置网桥透明模式防火墙
      一、透明模式防火墙与透明代理的概念
            一般而言,防火墙的两个网络接口应分属两个不同的网络,根据系统管理员定义的访问规则在两个接口之间转发数据包,或者拒绝、丢弃数据包。实际上,防火墙不单单是访问控制的功能,而且还充当了路由器的角色。当然,这并非有什么不妥当的地方,但是当你企图把你配置好的防火墙放入运行网络,来保护现有系统安全的时候,你不得不重新考虑和更改你的网络架构。另外一个可能的麻烦是,当防火墙发生意外时,如果没有防火墙的硬件备份的话,那么你将面临巨大的心理压力,因为防火墙的故障,整个网络瘫痪了。假如你把防火墙配置成透明模式(可称为伪网桥),就无需更改网络架构,即使是防火墙不能工作了,要做的仅仅是拔出网线,把网线直接插在路由器的内部接口就可以让网络正常工作,然后你就有时间慢慢恢复发生故障的防火墙。
            在防火墙厂商推荐产品的过程中,很多厂商往往会介绍自己的产品实现了透明模式和透明代理。那么究竟什么是透明模式和透明代理呢?他们之间又有何关系呢?下面我们将做具体分析。
             透明模式,顾名思义,首要的特点就是对用户是透明的(Transparent),即用户意识不到防火墙的存在。要想实现透明模式,防火墙必须在没有IP地址的情况下工作,不需要对其设置IP地址,用户也不知道防火墙的IP地址。
            防火墙作为实际存在的物理设备,其本身也起到路由的作用,所以在为用户安装防火墙时,就需要考虑如何改动其原有的网络拓扑结构或修改连接防火墙的路由表,以适应用户的实际需要,这样就增加了工作的复杂程度和难度。但如果防火墙采用了透明模式,即采用无IP方式运行,用户将不必重新设定和修改路由,防火墙就可以直接安装和放置到网络中使用,如交换机一样不需要设置IP地址。
            透明模式的防火墙就好象是一台网桥(非透明的防火墙好象一台路由器),网络设备(包括主机、路由器、工作站等)和所有计算机的设置(包括IP地址和网关)无须改变,同时解析所有通过它的数据包,既增加了网络的安全性,又降低了用户管理的复杂程度。而与透明模式在称呼上相似的透明代理,和传统代理一样,可以比包过滤更深层次地检查数据信息,比如FTP包的port命令等。同时它也是一个非常快的代理,从物理上分离了连接,这可以提供更复杂的协议需要,例如带动态端口分配的H.323,或者一个带有不同命令端口和数据端口的连接。这样的通信是包过滤所无法完成的。
            防火墙使用透明代理技术,这些代理服务对用户也是透明的,用户意识不到防火墙的存在,便可完成内外网络的通讯。当内部用户需要使用透明代理访问外部资源时,用户不需要进行设置,代理服务器会建立透明的通道,让用户直接与外界通信,这样极大地方便了用户的使用。一般使用代理服务器时,每个用户需要在客户端程序中指明要使用代理,自行设置Proxy参数(如在浏览器中有专门的设置来指明HTTP或FTP等的代理)。而透明代理服务,用户不需要任何设置就可以使用代理服务器,简化了网络的设置过程。透明代理的原理如下:假设A为内部网络客户机,B为外部网络服务器,C为防火墙。
            当A对B有连接请求时,TCP连接请求被防火墙截取并加以监控。截取后当发现连接需要使用代理服务器时,A和C之间首先建立连接,然后防火墙建立相应的代理服务通道与目标B建立连接,由此通过代理服务器建立A 和目标地址B的数据传输途径。从用户的角度看,A和B的连接是直接的,而实际上A 是通过代理服务器C和B建立连接的。反之,当B对A有连接请求时原理相同。由于这些连接过程是自动的,不需要客户端手工配置代理服务器,甚至用户根本不知道代理服务器的存在,因而对用户来说是透明的。
            代理服务器可以做到内外地址的转换,屏蔽内部网的细节,使非法分子无法探知内部结构。代理服务器提供特殊的筛选命令,可以禁止用户使用容易造成攻击的不安全的命令,从根本上抵御攻击。
            防火墙使用透明代理技术,还可以使防火墙的服务端口无法探测到,也就无法对防火墙进行攻击,大大提高了防火墙的安全性与抗攻击性。透明代理避免了设置或使用中可能出现的错误,降低了防火墙使用时固有的安全风险和出错概率,方便用户使用。
            因此,透明代理与透明模式都可以简化防火墙的设置,提高系统安全性。但两者之间也有本质的区别:工作于透明模式的防火墙使用了透明代理的技术,但透明代理并不是透明模式的全部,防火墙在非透明模式中也可以使用透明代理。
      二、环境搭建
      2.1.1硬件配置
            为了实现高效的防火墙和网络检测,系统CPU必须足够的强大和快速。系统需要三块网卡,其中两块网卡支持网桥的实现,另外一块用来实现对防火墙的管理。(至少2块网卡,可以把管理IP配置在桥接设备上)。磁盘容量并不是很重要,但是所有的log信息应该被保存下来。若希望维护某些本地 logging(用于某些配置和检测工具),则需要确保拥有足够的免费空间-防火墙和入侵检测记录往往非常庞大。
      2.1.2安装Linux
            当系统安装完毕并重新启动时,编辑/etc/hosts.allow来只允许管理机通过SSH来连接进入系统,然后重新启动按照正常模式引导进入系统。然后再将主以太接口连接到内部网络中。
      2.1.3创建支持网桥方式的内核
            按照基本的内核编译步骤进行,只不过需要关闭大多数的选项开关,而仅仅打开一些必须的内核编译开关。下载最新的内核,2.4可能需要下载在网桥模式下的时候让内核能正常支持netfilter的补丁bridge-nf,这个很重要,不打这个patch , iptables 将无法对通过你网桥包做过滤,2.6就已经自带了,地址:
      http://ebtables.sourceforge.net/download.html,bridge- nf只支持最新版本的原始内核,所以如果你不是对内核很熟悉,请不要试图在老版本内核上安装这个patch,因为你可能根本找不到适合你内核版本的补丁,也不要试图在发行版自带的内核上打这个patch,因为几乎所有Linux发行版都打了很多发行商认为对用户有益的patch,所以你可能根本没办法把 bridgenf成功打到这些内核的源码中。
      # cd /usr/src/linux-2.4.21
      # patch –p1  用户模式
      1:进入特权模式 enable
      router > enable
      router #
      2:进入全局配置模式 configure terminal
      router > enable
      router #configure terminal
      router (conf)#
      3:交换机命名 hostname routera 以routerA为例
      router > enable
      router #configure terminal
      router(conf)#hostname routerA
      routera (conf)#
      4:配置使能口令 enable password cisco 以cisco为例
      router > enable
      router #configure terminal
      router(conf)#hostname routerA
      routerA (conf)# enable password cisco
      5:配置使能密码 enable secret ciscolab 以cicsolab为例
      router > enable
      router #configure terminal
      router(conf)#hostname routerA
      routerA (conf)# enable secret ciscolab
      6:进入路由器某一端口 interface fastehernet 0/17 以17端口为例
      router > enable
      router #configure terminal
      router(conf)#hostname routerA
      routerA (conf)# interface fastehernet 0/17
      routerA (conf-if)#
      进入路由器的某一子端口 interface fastethernet 0/17.1 以17端口的1子端口为例
      router > enable
      router #configure terminal
      router(conf)#hostname routerA
      routerA (conf)# interface fastehernet 0/17.1
      7:设置端口ip地址信息
      router > enable
      router #configure terminal
      router(conf)#hostname routerA
      routerA(conf)# interface fastehernet 0/17 以17端口为例
      routerA (conf-if)#ip address 192.168.1.1 255.255.255.0 配置交换机端口ip和子网掩码
      routerA (conf-if)#no shut 是配置处于运行中
      routerA (conf-if)#exit
      8:查看命令 show
      router > enable
      router # show version 察看系统中的所有版本信息
      show interface vlan 1 查看交换机有关ip 协议的配置信息
      show running-configure 查看交换机当前起作用的配置信息
      show interface fastethernet 0/1 察看交换机1接口具体配置和统计信息
      show mac-address-table 查看mac地址表
      show mac-address-table aging-time 查看mac地址表自动老化时间
      show controllers serial + 编号 查看串口类型
      show ip router 查看路由器的路由表
      9:cdp相关命令
      router > enable
      router # show cdp 查看设备的cdp全局配置信息
      show cdp interface fastethernet 0/17 查看17端口的cdp配置信息
      show cdp traffic 查看有关cdp包的统计信息
      show cdp nerghbors 列出与设备相连的cisco设备
      10:csico2600的密码恢复
      重新启动路由器,在启动过程中按下win+break键,使路由器进入rom monitor
      在提示符下输入命令修改配置寄存器的值,然后重新启动路由器
      remmon1>confreg 0x2142
      remmon2>reset
      重新启动路由器后进入setup模式,选择“no”,退回到exec模式,此时路由器原有的配置仍然保存在startup-config中,为使路由器恢复密码后配置不变把startup-config中配置保存到running-config中,然后重新设置enable密码,并把配置寄存器改回0x2102:
      router>enable
      router#copy startup-config running-config
      router#configure terminal
      router(conf)#enable password cisco
      router(conf)#config-register 0x2102
      保存当前配置到startup-config , 重新启动路由器。
      router #copy running-config startup-config
      router #reload
      -------------------------
      路由器命令大全(二)
      11:路由器telnet远程登录设置:
      router>en
      router #configure terminal
      router (conf)#hostname routerA
      routerA (conf)#enable password cisco 以cisco为特权模式密码
      routerA (conf)#interface fastethernet 0/1 以17端口为telnet远程登录端口
      routerA (conf-if)#ip address 192.168.1.1 255.255.255.0
      routerA (conf-if)#no shut
      routerA (conf-if)#exit
      routerA (conf)line vty 0 4 设置0-4 个用户可以telnet远程登陆
      routerA (conf-line)#login
      routerA (conf-line)#password edge 以edge为远程登录的用户密码
      主机设置:
      ip 192.168.1.2 主机的ip必须和交换机端口的地址在同一网络段
      netmask 255.255.255.0
      gate-way 192.168.1.1 网关地址是交换机端口地址
      运行:
      telnet 192.168.1.1
      进入telnet远程登录界面
      password : edge
      routera>en
      password: cisco
      routera#
      12:配置路由器的标识 banner $……………$
      在全局配置的模式下利用“banner”命令可以配置路由器的提示信息,所有连接到路由器的终端都会收到。
      router>en
      router #configure terminal
      router (conf)#hostname routerA
      routerA(conf)#banner motd $This is aptech company’ router ! Please don’t change the configuration without permission!
      $13:配置接口标识 description ………
      接口标识用于区分路由器的各个接口。
      router>en
      router #configure terminal
      router (conf)#hostname routerA
      routerA(conf)#interface fastethernet 0/1 以0/1 接口为例
      routerA(conf-if)# description this is a fast Ethernet port used to connecting the company’s intranet!
      14:配置超时
      超时适用于设置在多长时间没有对console进行配置,自动返回exec会话时间。默认为10分钟。
      router>en
      router #configure terminal
      router (conf)#hostname routerA
      routerA(conf)#line console 0
      routerA(conf-if)#exec-timeout 0 0 第一个“0”代表分钟,第二个“0”代表秒
      15:配置串口参数
      两台路由器通过串口连接需要一个做为DTE,一个做为DCE。DCE设备要向DTE设备提供时钟频率和带宽。
      DCE配置:
      router>en
      router #configure terminal
      router (conf)#hostname routerA
      routerA(conf)#interface serial 0/0
      routerA(conf_if)#clock rate 64000 提供时钟频率为64000
      routerA(conf_if)#bandwidth 64 提供带宽为64
      DTE配置:路由器串口配置ip地址
      router>en
      router #configure terminal
      router (conf)#hostname routerB
      routerB(conf)#interface serial 0/0
      routerB(conf_if)#ip address 192.168.1.1 255.255.255.0
      ]
      --------------------------------
      路由器命令大全(3)
      16:静态路由的配置
      配置路由器A的主机名和接口参数
      router>enable
      router#configure terminal
      router(conf)#hostname routerA
      routerA(conf)#interface fastethernet 0/1 路由器A的1端口为两路由器的连接端口
      routerA(conf-if)#ip address 192.168.2.1 255.255.255.0
      routerA(conf-if)#no shutdown
      routerA(conf-if)#exit
      routerA(conf)# interface fastethernet 0/0 路由器A的0端口为与主机的连接端口
      routerA(conf-if)#ip address 192.168.1.2 255.255.255.0
      routerA(conf-if)#no shutdown
      主机A的ip地址为 192.168.1.1
      255.255.255.0
      192.168.1.2
      配置路由器B的主机名和接口参数
      router>enable
      router#configure terminal
      router(conf)#hostname routerB
      routerB(conf)#interface fastethernet 0/0 路由器B的0端口为两路由器的连接端口
      routerB(conf-if)#ip address 192.168.2.2 255.255.255.0
      routerB(conf-if)#no shutdown
      routerB (conf-if)#exit
      routerB(conf)# interface fastethernet 0/1 路由器B的1端口为与主机的连接端口
      routerB(conf-if)#ip address 192.168.3.1 255.255.255.0
      主机B的ip地址为 192.168.3.2
      255.255.255.0
      192.168.3.1
      配置路由器A的静态路由表
      routerA(conf)#ip router 192.168.3.0 255.255.255.0 192.168.2.2
      配置路由器B的静态路由表
      routerA(conf)#ip router 192.168.1.0 255.255.255.0 192.168.2.1
      在routerA和routerB上配置默认路由
      routerA(conf)#ip route 0.0.0.0 0.0.0.0 192.168.2.2
      routerA(conf)#ip classless
      routerB(conf)#ip route 0.0.0.0 0.0.0.0 192.168.2.1
      routerB(conf)#ip classless
      在routerA和routerB上配置动态路由(RIP)
      routerA(conf)#router rip
      routerA(conf)#network 192.168.1.0
      routerA(conf)#network 192.168.2.0
      routerB(conf)# router rip
      routerB(conf)#network 192.168.2.0
      routerB(conf)#network 192.168.3.0

      ==================================================================================
      Linux网桥接器的运作
      添加记录:  类别: 网络配置 发布日期: 2007.01.15
      本文从系统管理员的角度讨论安全问题.系统管理员是管理系统的人:启动
      系统,停止系统运行,安装新软件,增加新用户,删除老用户,以及完成保持系统发
      展和运行的日常事务工作.
      1.安全管理
      安全管理主要分为四个方面:
      (1)防止未授权存取:这是计算机安全最重要的问题:未被使用系统的人进入系
      统.用户意识,良好的口令管理(由系统管理员和用户双方配合),登录活动
      记录和报告,用户和网络活动的周期检查,这些都是防止未授权存取的关键.
      (2)防止泄密:这也是计算机安全的一个重要问题.防止已授权或未授权的用户
      相互存取相互的重要信息.文件系统查帐,su登录和报告,用户意识,加密都
      是防止泄密的关键.
      (3)防止用户拒绝系统的管理:这一方面的安全应由操作系统来完成.一个系统
      不应被一个有意试图使用过多资源的用户损害.不幸的是,UNIX不能很好地
      限制用户对资源的使用,一个用户能够使用文件系统的整个磁盘空间,而
      UNIX基本不能阻止用户这样做.系统管理员最好用PS命令,记帐程序df和du
      周期地检查系统.查出过多占用CUP的进程和大量占用磁盘的文件.
      (4)防止丢失系统的完整性:这一安全方面与一个好系统管理员的实际工作(例
      如:周期地备份文件系统,系统崩溃后运行fsck检查,修复文件系统,当有新
      用户时,检测该用户是否可能使系统崩溃的软件)和保持一个可靠的操作系
      统有关(即用户不能经常性地使系统崩溃).
      本文其余部分主要涉及前两个问题,第三个问题在一节讨论.
      2.超级用户
      一些系统管理命令只能由超级用户运行.超级用户拥有其他用户所没有的特
      权,超级用户不管文件存取许可方式如何,都可以读,写任何文件,运行任何程序.
      系统管理员通常使用命令: /bin/su 或以 root 进入系统从而成为超级用户.在
      后面文章中以#表示应敲入必须由超级用户运行的命令,用$表示应敲入由所有其
      他用户运行的命令.
      3.文件系统安全
      (1)UNIX文件系统概述
      UNIX文件系统是UNIX系统的心脏部分,提供了层次结构的目录和文件.文
      件系统将磁盘空间划分为每1024个字节一组,称为块(block)(也有用512字节
      为一块的,如:SCO XENIX).编号从0到整个磁盘的最大块数.
      全部块可划分为四个部分,块0称为引导块,文件系统不用该块;块1称为专
      用块,专用块含有许多信息,其中有磁盘大小和全部块的其它两部分的大小.从
      块2开始是i节点表,i节点表中含有i节点,表的块数是可变的,后面将做讨论.
      i节点表之后是空闲存储块(数据存储块),可用于存放文件内容.
      文件的逻辑结构和物理结构是十分不同的,逻辑结构是用户敲入cat命令
      后所看到的文件,用户可得到表示文件内容的字符流.物理结构是文件实际上
      如何存放在磁盘上的存储格式.用户认为自己的文件是边疆的字符流,但实际
      上文件可能并不是以边疆的方式存放在磁盘上的,长于一块的文件通常将分散
      地存放在盘上.然而当用户存取文件时,UNIX文件系统将以正确的顺序取各块,
      给用户提供文件的逻辑结构.
      当然,在UNIX系统的某处一定会有一个表,告诉文件系统如何将物理结构
      转换为逻辑结构.这就涉及到i节点了.i节点是一个64字节长的表,含有有关一
      个文件的信息,其中有文件大小,文件所有者,文件存取许可方式,以及文件为
      普通文件,目录文件还是特别文件等.在i节点中最重要的一项是磁盘地址表.
      该表中有13个块号.前10个块号是文件前10块的存放地址.这10个块号能给出
      一个至多10块长的文件的逻辑结构,文件将以块号在磁盘地址表中出现的顺序
      依次取相应的块.
      当文件长于10块时又怎样呢?磁盘地址表中的第十一项给出一个块号,这
      个块号指出的块中含有256个块号,至此,这种方法满足了至多长于266块的文
      件(272,384字节).如果文件大于266块,磁盘地址表的第十二项给出一个块号,
      这个块号指出的块中含有256个块号,这256个块号的每一个块号又指出一块,
      块中含256个块号,这些块号才用于取文件的内容.磁盘地址中和第十三项索引
      寻址方式与第十二项类似,只是多一级间接索引.
      这样,在UNIX系统中,文件的最大长度是16,842,762块,即17,246,988,288
      字节,有幸是是UNIX系统对文件的最大长度(一般为1到2M字节)加了更实际的
      限制,使用户不会无意中建立一个用完整个磁盘窨所有块的文件.
      文件系统将文件名转换为i节点的方法实际上相当简单.一个目录实际上
      是一个含有目录表的文件:对于目录中的每个文件,在目录表中有一个入口项,
      入口项中含有文件名和与文件相应的i节点号.当用户敲入cat xxx时,文件系
      统就在当前目录表中查找名为xxx的入口项,得到与文件xxx相应的i节点号,然
      后开始取含有文件xxx的内容的块.
      (2)设备文件
      UNIX系统与边在本系统上的各种设备之间的通讯,通过特别文件来实现,
      就程序而言,磁盘是文件,MODEM是文件,甚至内存也是文件.所有连接到系统上
      的设备都在/dev目录中有一个文件与其对应.当在这些文件上执行I/O操作时,
      由UNIX系统将I/O操作转换成实际设备的动作.例如,文件/dev/mem是系统的内
      存,如果cat这个文件,实际上是在终端显示系统的内存.为了安全起见,这个文
      件对普通用户是不可读的.因为在任一给定时间,内存区可能含有用户登录口
      令或运行程序的口令,某部分文件的编辑缓冲区,缓冲区可能含有用ed -x命令
      解密后的文本,以及用户不愿让其他人存取的种种信息.
      在/dev中的文件通常称为设备文件,用ls /dev命令可以看看系统中的一
      些设备:
      acuo 呼叫自动拨号器
      console 系统控制台
      dsknn 块方式操作磁盘分区
      kmem 核心内存
      mem 内存
      lp 打印机
      mto 块方式操作磁带
      rdsknn 流方式操作的磁盘分区
      rmto 流方式操作的磁带
      swap 交换区
      syscon 系统终端
      ttynn 终端口
      x25 网络端口
      等等
      (3)/etc/mknod命令
      用于建立设备文件.只有root能使用这个命令建立设备文件.其参数是文
      件名,字母c或b分别代表字符特别文件或块特别文件,主设备号,次设备号.块
      特别文件是像磁带,磁盘这样一些以块为单位存取数据的设备.字符特别文件
      是如像终端,打印机,MODEM,或者其它任何与系统通讯时,一次传输一个字符的
      设备,包括模仿对磁盘进行字符方式存取的磁盘驱动器.主设备号指定了系统
      子程序(设备驱动程序),当在设备上执行I/O时,系统将调用这个驱动程序.调
      用设备驱动程序时,次设备号将传递给该驱动程序(次设备规定具体的磁盘驱
      动器,带驱动器,信号线编号,或磁盘分区).每种类型的设备一般都有自己的设
      备驱动程序.
      文件系统将主设备号和次设备号存放在i节点中的磁盘地址表内,所以没
      有磁盘空间分配给设备文件(除i节点本身占用的磁盘区外).当程序试图在设
      备文件上执行I/O操作时,系统识别出该文件是一个特别文件,并调用由主设备
      号指定的设备驱动程序,次设备号作为调用设备驱动程序的参数.
      (4)安全考虑
      将设备处理成文件,使得UNIX程序独立于设备,即程序不必一定要了解正
      使用的设备的任何特性,存取设备也不需要记录长度,块大小,传输速度,网络
      协议等这样一些信息,所有烦人的细节由设备驱动程序去关心考虑,要存取设
      备,程序只须打开设备文件,然后作为普通的UNIX文件来使用.
      从安全的观点来看这样处理很好,因为任何设备上进行的I/O操作只经过
      了少量的渠道(即设备文件).用户不能直接地存取设备.所以如果正确地设置
      了磁盘分区的存取许可,用户就只能通过UNIX文件系统存取磁盘.文件系统有
      内部安全机制(文件许可).不幸的是,如果磁盘分区设备得不正确,任何用户都
      能够写一个程序读磁盘分区中的每个文件,作法很简单:读一i节点,然后以磁
      盘地址表中块号出现的顺序,依次读这些块号指出的存有文件内容的块.故除
      了root以外,决不要使盘分区对任何人可写.因为所有者,文件存取许可方式这
      样一些信息存放于i节点中,任何人只要具有已安装分区的写许可,就能设置任
      何文件的SUID许可,而不管文件的所有者是谁,也不必用chmod()命令,还可避
      过系统建立的安全检查.
      以上所述对内存文件mem,kmem和对换文件swap也是一样的.这些文件含有
      用户信息,一个的程序可以将用户信息提取出来.
      要避免磁盘分区(以及其它设备)可读可写,应当在建立设备文件前先用
      umask命令设置文件建立屏蔽值.
      一般情况下,UNIX系统上的终端口对任何人都是可写的,从而使用户可以
      用write命令发送信息.虽然write命令易引起安全方面的问题,但大多数用户
      觉得用write得到其他用户的信息很方便,所以系统将终端设备的存取许可设
      置成对所有用户可写.
      /dev目录应当是755存取许可方式,且属root所有.
      不允许除root外的任何用户读或写盘分区的原则有一例外,即一些程序
      (通常是数据库系统)要求对磁盘分区直接存取,解决这个问题的经验的盘分区
      应当由这种程序专用(不安装文件系统),而且应当告知使用这种程序的用户,
      文件安全保护将由程序自己而不是UNIX文件系统完成.
      (5)find命令
      find命令用于搜索目录树,并对目录树上的所有文件执行某种操作,参数
      是目录名表(指出从哪些起点开始搜索),还可给出一个或多个选项,规定对每
      个文件执行什么操作.
      find . -print 将列出当前工作目录下的目录树的每一个文件.
      find / -user bob -print 将列出在系统中可找到的属于bob用户的所有
      文件.
      find /usr/bob -perm 666 -print 将列出/usr/bob目录树下所有存取许
      可为666的文件.若将666改为-666则将列出所有具有包含了666在内
      的存取许可方式的文件(如777).
      find /usr/bob -type b -print 将列出/usr/bob目录树下所有块特别文
      件(c为字符特别文件).
      find / -user root -perm -4000 -exec ls -l {} ; 是一个较复杂一
      点的命令,-exec COMMAND ;允许对所找到的每个文件运行指定的
      命令COMMAND.若COMMAND中含有{},则{}将由find所找到的文件名替
      换.COMMAND必须以;结束.
      以上举例介绍find的用法,各选项可组合使用以达到更强的功能.
      (6)secure程序
      系统管理员应当做一个程序以定期检查系统中的各个系统文件,包括检查
      设备文件和SUID,SGID程序,尤其要注意检查SUID,SGID程序,检查/etc/passwd
      和/etc/group文件,寻找久未登录的户头和校验各重要文件是否被修改.
      (源程序清单将在今后发表)
      (7)ncheck命令
      用于检查文件系统,只用一个磁盘分区名作为参数,将列出i节点号及相应
      的文件名.i节点相同的文件为建链文件.
      注意:所列出的清单文件名与mount命令的第一个域相同的文件名前部分
      将不会列出来.因为是做文件系统内部的检查,ncheck并不知道文件系统安装
      点以上部分的目录.
      也可用此命令来搜索文件系统中所有的SUID和SGID程序和设备文件,使用
      -s选项来完成此项功能.
      (8)安装和拆卸文件系统
      UNIX文件系统是可安装的,这意味着每个文件系统可以连接到整个目录树
      的任意节点上(根目录总是被安装上的).安装文件系统的目录称为安装点.
      /etc/mount命令用于安装文件系统,用这条命令可将文件系统安装在现有
      目录结构的任意处.
      安装文件系统时,安装点的文件和目录都是不可存取的,因此未安装文件
      系统时,不要将文件存入安装点目录.文件系统安装后,安装点的存取许可方式
      和所有者将改变为所安装的文件根目录的许可方式和所有者.
      安装文件系统时要小心:安装点的属性会改变!还要注意新建的文件,除非
      新文件系统是由标准文件建立的,系统标准文件会设置适当的存取许可方式,
      否则新文件系统的存取许可将是777!
      可用-r选项将文件系统安装成只读文件系统.需要写保护的带驱动器和磁
      盘应当以这种方式来安装.
      不带任何参数的/etc/mount可获得系统中所安装的文件系统的有关信息.
      包括:文件系统被安装的安装点目录,对应/dev中的哪个设备,只读或可读写,
      安装时间和日期等.
      从安全的观点来讲,可安装系统的危险来自用户可能请求系统管理员为其
      安装用户自己的文件系统.如果安装了用户的文件系统,则应在允许用户存取
      文件系统前,先扫描用户的文件系统,搜索SUID/SGID程序和设备文件.在除了
      root外任何人不能执行的目录中安装文件系统,用find命令或secure列出可疑
      文件,删除不属用户所有的文件的SUID/SGID许可.
      用户的文件系统用完后,可用umount命令卸下文件系统.并将安装点目录
      的所有者改回root,存取许可改为755.
      (9)系统目录和文件
      UNIX系统中有许多文件不允许用户写,如:/bin,/usr/bin,/usr/lbin,
      /etc/passwd,/usr/lib/crontab,/unix,/etc/rc,/etc/inittab这样一些文件
      和目录(大多数的系统目录),可写的目录允许移动文件,会引起安全问题.
      系统管理员应经常检查系统文件和目录的许可权限和所有者.可做一个程
      序根据系统提供的规则文件(在/etc/permlist文件中)所描述的文件所有者和
      许可权规则检查各文件.
      (源程序清单将在今后发表)
      注意:如果系统的安全管理不好,或系统是新安装的,其安全程序不够高,
      可以用make方式在安全强的系统上运行上述程序,将许可规则文件拷贝到新系
      统来,再以设置方式在新系统上运行上述程序,就可提高本系统的安全程序.但
      要记住,两个系统必须运行相同的UNIX系统版本.
      4.作为root运行的程序
      在UNIX系统中,有些程序由系统作为root进程运行.这些程序并不总是具有
      SUID许可,因为其不少程序仅由root运行,系统管理员需要清楚这些程序做什么,
      以及这些程序还将运行其它什么程序.
      (1)启动系统
      当某些UNIX系统(如SCO UNIX/XENIX)启动时,是以被称为单用户的方式运
      行,在这种方式中普通用户不能登录,唯有的进程是init,swapper,以及一些由
      系统管理员从控制台运行的进程.UNIX系统的单用户方式启动,使系统管理员
      能在允许普通用户登录以前,先检查系统操作,确保系统一切正常,当系统处于
      单用户方式时,控制台作为超级用户,命令揭示是 
      ==================================================================================
      Linux网桥接器的运作
      1. 设定
      l 取得 ``桥接器配置''
      ftp://shadow.cabi.net/pub/Linux/BRCFG.tgz
      l 取得和阅读 ``Multiple ethernet'' HOWTO
      ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini/Multiple-Ethernet
      l 配置lilo启动参数
      使多个乙太网路设备在你的机器运作照著加入这行到你的 /etc/lilo.conf, 和重新执行 lilo:append = "ether=0,0,eth1"
      如果你在你的桥接器上有三张界面卡,使用这些行取代上面
      append = "ether=0,0,eth1 ether=0,0,eth2"
      靠加入更多的乙太陈述可以找到更多的界面. 预设上一个传统的 Linux 核心只侦测一张独一的乙太网路卡, 和当一个被找到侦测就会停止. 上面所附加的陈述告诉核心在第一个被找到之後继续侦测去找到更多乙太网路设备。
      另一个方法,可以使用启动变数来取代:
      linux ether=0,0,eth1
      或者, 有三个界面,使用:
      linux ether=0,0,eth1 ether=0,0,eth2
      l 重新编译那核心启动BRIDGING功能
      l 一个桥接器应没有一个的 IP 地址. 它可以有一个,但是一个平常的桥接器不需要一个 IP 地址. 从你的桥接器上移除 IP 地址,到 /etc/sysconfig/network-scripts/ (对於一个 RedHat系统) 和拷贝 ifcfg-lo0到 ifcfg-eth0 & ifcfg-eth1. 在这两个乙太档案中,改变那行包含 ``DEVICE=lo'' to ``DEVICE=eth0'' 和 ``DEVICE=eth1''. 别的 Linux distribution 也许和这个不同,自已动手做你想要的! 如果桥接器上有超过两个界面卡, 确定也使设定符合这些界面.
      l 重新启动,执行那包含桥接器功能的核心, 另外也查明确认一个 IP 地址没有指定到这网路界面卡.
      l 一次系统是备份, 把乙太网路卡设定在纷乱(promiscuous)的模式, 他们将靠它的界面监看每一个通过的封包:
      ifconfig promisc eth0 ; ifconfig promisc eth1
      连接到网路区段的全部的界面卡被桥接器分开进入 promiscuous(纷乱) 的模式.
      l 启动桥接器使用 brcfg程式:
      brcfg –ena
      l 检验每一个界面卡有不同的交通流量:
      tcpdump -i eth0 (在一个视窗)
      tcpdump -i eth1 (在另一个视窗)
      l 执行一个 sniffer (监看器) 或者 tcpdump 在另外的机器上去检验桥接器正确地分开区段。
      2. 一般的问题
      l Question:我得到这个讯息 ioctl(SIOCGIFBR) failed: Package not installed这是什麽意思?
      l Answer:你的核心没有桥接器的能力. 取得到一个 2.0或者更後面的核心, 和重新编译启动桥接器功能的选项 BRIDGING。
      l Question:机器在一边不能 ping 到另外一边!
      l Answer:你有使用 ``brcfg -ena' 使桥接器运作'吗? (brcfg将说 ``bridging is ENABLED'') 你有把界面放在 promiscuous(纷乱)的模式吗? (使用 ``ifconfig''命令. 那 ``PROMISC''参数应该是在两个界面卡上.)。如果正在用 multiple-media 界面卡, 确定启动的是正确的是那一端. 你也许需要使用和网路界面卡附的 配置/设定 程式来做设定 。
      l Question:我不能从桥接器上 telnet/ftp!为什麽?
      l Answer:这是因为没有 IP 地址指定到任何的桥接器的界面卡.一个桥接器是一个网路的透通部分。
      l Question:在设定路由方面我需要做什麽?
      l Answer:无! 整个的路由资料是由核心的桥接器的码所掌握. 靠桥接器看见那乙太网路地址他们是被学习, 在测错模式下使用 brcfg程式:brcfg –deb
      l Question:那桥接器看起来有运作,但是为什麽 ``traceroute'' 没有显示那桥接器是路径的一个部分?
      l Answer:由於桥接器当然的功能, ``traceroute''将不显示桥接器当作路径的一部分.一个桥接器是网路的一个透通组件。
      l Question:IP_FORWARD 是否必要编译到核心中呢?
      l Answer:不.核心中的桥接器的码照料封包传送. IP_FORWARD对於一个 gateway(通路闸)它要有 IP 地址指定到它的界面。
      l Question:根据那 ``brcfg''程式显示,为什麽对於埠 1和埠 2 实体的乙太网路地址是相同的? 他们应该是不同的吗?
      l Answer:不.一个桥接器的每一埠是故意地是由桥接器的码指定那相同的实体的乙太网路地址。
      l Question:当在核心中执行的一个 (make config)建造设定,桥接器的选项没有出现 .它是如何启动的呢?
      l Answer:在核心配置的时候,针对以下的问题回答 'Y' , ``Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL) [Y/n/?]''。
      l Question:太多集线器 (4个或者更多)一个接一个串连在一起 (连续地) 在一个乙太网路上造成时间回应的问题.在一个由集线器所布建的子网中一个桥接器会有什麽结果?
      l Answer:一个桥接器重设 3/4/5集线器规则.一个桥接器没有如同一个集线器所做的处理封包,因此没有一个 contributor(贡献者) 到在一个网路上有时间回应问题.
      l Question:一个桥接器界面能够同时连接 10Mb 和 100Mb 两个乙太网路区段? 这样的配置会造成高速流量的另一边慢下来吗?
      l Answer:是,一个桥接器能够把 10 Mb 的区段和 100Mb 的区段绑在一起只要那网路卡在桥接器的快速网路的那一边是有 100Mb 能力的 , TCP 将要照料其馀的部分.这时它发生的情形是从一个在 100Mb 网路的主机送封包沟通另一个在 10Mb 网路的主机是只有用 10Mb/s 的速度移动,其馀的 那网路交通在快速乙太网路是不会被拖慢
      ==================================================================================
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!