荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: ykwch.bbs@bbs.cqupt.edu.cn (心蓝--雨下), 信区: Linux
标  题: 防火墙技术分析讲义--二
发信站: 幽幽黄桷兰 (Sat Apr  5 15:02:39 2003)
转信站: SZU!news.tiaozhan.com!news.happynet.org!CQUPT

二 Linux下防火墙的实现之一(2.2内核):
2.1 截获位置:
        网络层
                  ----------------------------------------------------------
------
                  |            ACCEPT/                              lo inter
face |
                  v           REDIRECT                  _______
     |
          --> C --> S --> ______ --> D --> ~~~~~~~~ -->|forward|----> ______
_ -->
              h     a    |input |    e    {Routing }   |Chain  |     |output
 |ACCEPT
              e     n    |Chain |    m    {Decision}   |_______| --->|Chain
 |
              c     i    |______|    a     ~~~~~~~~        |     | ->|______
_|
              k     t       |        s       |             |     | |     |
              s     y       |        q       |             v     | |     |
              u     |       v        e       v            DENY/  | |     v
              m     |     DENY/      r   Local Process   REJECT  | |   DENY/

              |     v    REJECT      a       |                   | |  REJECT

              |   DENY               d       --------------------- |
              v                      e -----------------------------
             DENY
2.2 提炼出的代码:
输入检测:
        /*
        *         Main IP Receive routine.
        */
        int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_ty
pe *pt)
        {
        #ifdef        CONFIG_FIREWALL
                int fwres;
                u16 rport;
        #endif /* CONFIG_FIREWALL */
        ......
        #ifdef CONFIG_FIREWALL
                /*
                *        See if the firewall wants to dispose of the packet.

                *
                * We can't do ICMP reply or local delivery before routing,
                * so we delay those decisions until after route. --RR
                */
                fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);
                if (fwres < FW_ACCEPT && fwres != FW_REJECT)
                        goto drop;
                iph = skb->nh.iph;
        #endif /* CONFIG_FIREWALL */
        ......
        #ifdef CONFIG_FIREWALL
                if (fwres == FW_REJECT) {
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH,
 0);
                        goto drop;
                }
        #endif /* CONFIG_FIREWALL */
                return skb->dst->input(skb); //根据路由查找的结果决定是转发(
ip_forward)还是发往上层(ip_local_deliver)
        drop:
                kfree_skb(skb);        //如果规则匹配的结果是FW_REJECT,FW_B
LOCK,丢弃此包
                return(0);
        }
转发检测:
        int ip_forward(struct sk_buff *skb)
        {
        ...
        #ifdef CONFIG_FIREWALL
                        fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &s
kb);
                        switch (fw_res) {
                        case FW_ACCEPT:
                        case FW_MASQUERADE:
                                break;
                        case FW_REJECT:
                                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_
UNREACH, 0);
                                /* fall thru */
                        default:
                                kfree_skb(skb);
                                return -1;
                        }
        #endif
        ...
        }
输出检测:(不同的上层协议走不同的流程,因此检测点较多)
        UDP/RAW/ICMP报文:ip_build_xmit
        TCP报文:ip_queue_xmit
        转发的包:ip_forward
        其他:ip_build_and_send_pkt
实际的匹配:
        /*
        *        Returns one of the generic firewall policies, like FW_ACCEP
T.
        *
        *        The testing is either false for normal firewall mode or tru
e for
        *        user checking mode (counters are not updated, TOS & mark no
t done).
        */
        static int
        ip_fw_check(struct iphdr *ip,                 //IP头位置
                    const char *rif,                //出口网卡的名字
                    __u16 *redirport,                //端口转发时用到
                    struct ip_chain *chain,        //规则链的名字
                    struct sk_buff *skb,        //要检测的数据包
                    unsigned int slot,
                    int testing)                //见函数本身的注释
调用举例:
        call_in_firewall实际调用ipfw_input_check,而ipfw_input_check中有:
        int ipfw_input_check(struct firewall_ops *this, int pf, struct devic
e *dev,
                             void *phdr, void *arg, struct sk_buff **pskb)
        {
                return ip_fw_check(phdr, dev->name,
                                   arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBE
R(), 0);
        }
实际流程:
        ip_fw_check
        {
                从传入的skb参数中提取源地址src,目的地址dst,源端口src_port,目
的端口dst_port,
                TCP发起连接标志tcpsyn,分片包位移offset,IP包TOS消息oldtos;

                ......
                f = chain->chain;        //取出规则链的的一条规则,规则链由ch
ain参数传入
                count = 0;
                do {
                        for (; f; f = f->next) {        //遍历规则链中的规则
,直到匹配(ip_rule_match返回1)
                                count++;
                                if (ip_rule_match(f,rif,ip,
                                                  tcpsyn,src_port,dst_port,o
ffset)) {
                                        if (!testing
                                            && !ip_fw_domatch(f, ip, rif, ch
ain->label,//作些标记,一般返回1
                                                              skb, slot,
                                                              src_port, dst_
port,
                                                              count, tcpsyn)
) {
                                                ret = FW_BLOCK;
                                                goto out;
                                        }
                                        break;
                                }
                        }
                        if(f) { //找到匹配规则
                                ......
                        }else { //这次遍历根本没找到
                                是从别的地方跳转过来的,则转回去,然后继续遍
历;
                                否则应用这条链的缺省规则;
                        }
                } while (ret == FW_SKIP+2);
        out:
                ......
                return ret;
        }
碎片:
        根据第一个片的消息进行过滤,其他分片则允许通过。如果规则是丢弃的话,
虽然后面的分片都可到达主机,
        但由于第一片被滤掉了,无法重组成功,因此从效果上也相当于整个IP包被丢
弃。
        存在的漏洞等.
2.3 规则:
        from 192.168.7.0/24 to 192.168.6.32/32 tcp 80 BLOCK
规则的数据结构表示:
        规则链
        struct ip_chain
        {
                ip_chainlabel label;            /* Defines the label for eac
h block */
                struct ip_chain *next;            /* Pointer to next block *
/
                struct ip_fwkernel *chain;  /* Pointer to first rule in bloc
k */
                __u32 refcount;             /* Number of refernces to block
*/
                int policy;                    /* Default rule for chain.  O
nly *
                                             * used in built in chains */
                struct ip_reent reent[0];   /* Actually several of these */
        };
        规则
        struct ip_fwkernel
        {
                struct ip_fw ipfw;
                struct ip_fwkernel *next;        /* where to go next if curr
ent
                                                * rule doesn't match */
                struct ip_chain *branch;        /* which branch to jump to i
f
                                                * current rule matches */
                int simplebranch;                /* Use this if branch == NU
LL */
                struct ip_counters counters[0]; /* Actually several of these
 */
        };
        待匹配的数据包消息
        struct ip_fw
        {
                struct in_addr fw_src, fw_dst;                /* Source and
destination IP addr */
                struct in_addr fw_smsk, fw_dmsk;        /* Mask for src and
dest IP addr */
                __u32 fw_mark;                          /* ID to stamp on pa
cket */
                __u16 fw_proto;                         /* Protocol, 0 = ANY
 */
                __u16 fw_flg;                                /* Flags word *
/
                __u16 fw_invflg;                        /* Inverse flags */
                __u16 fw_spts[2];                       /* Source port range
. */
                __u16 fw_dpts[2];                       /* Destination port
range. */
                __u16 fw_redirpt;                       /* Port to redirect
to. */
                __u16 fw_outputsize;                    /* Max amount to out
put to
                                                           NETLINK */
                char           fw_vianame[IFNAMSIZ];        /* name of inter
face "via" */
                __u8           fw_tosand, fw_tosxor;        /* Revised packe
t priority */
        };
2.4 地址转换
        ip_fw_demasquerade
        ip_fw_masquerade
--
蒹葭苍苍白露为霜所谓伊人在水一方溯洄从之道阻且长
溯游从之宛在水中央
蒹葭萋萋白露未晞所谓伊人在水之湄溯洄从之道阻且跻
溯游从之宛在水中坻
蒹葭采采白露未已所谓伊人在水之涘溯洄从之道阻且右
溯游从之宛在水中沚
※ 来源:·幽幽黄桷兰 bbs.cqupt.edu.cn·[FROM: BlueCrystal]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店