网普技术论坛 网普科技  
» 游客:   网普主页 | 注册 | 登录 | 帮助
 

作者:
标题: 防火墙技术分析讲义Part One [ZT] 上一主题 | 下一主题
网普科技
网普管理员

网普科技人民公仆


积分 3080
发贴 2863
注册 2004-6-26
来自 网普科技
状态 离线
#1  防火墙技术分析讲义Part One [ZT]

一 基本概念

1.1 防火墙分类:
        包过滤
        代理(应用层网关)

1.2 代理:

        两个连接(browser与proxy之间,proxy与web server之间)。
        工作在应用层。

        直接发往服务器的包:
        GET / HTTP/1.1
        Accept:        */*
        Accept-Language: zh-cn
        Accept-Encoding: gzip, deflate
        User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
        Host: www.lisoleg.net
        Connection: Keep-Alive

        往代理发出的包:
        GET http://www.lisoleg.net/ HTTP/1.1
        Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/msword, */*
        Accept-Language: zh-cn
        Accept-Encoding: gzip, deflate
        If-Modified-Since: Thu, 14 Dec 2000 07:24:52 GMT
        If-None-Match: "8026-185-3a3875c4"
        User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
        Host: www.lisoleg.net
        Proxy-Connection: Keep-Alive

        增强:
        cache

1.3 包过滤
        单IP包检测
        缺陷:无状态

1.4 增强1-状态检测(Stateful Inspection),又称动态包过滤(dynamic packet filtering)
        1.4.1 规则表和动态状态表

        1.4.2 ftp的例子:
        A 4847->B 21 PORT 192,168,7,60,18,241
        B 21->A 4847 PORT command successful.

        B 20->A 4849 syn
        > A classic example is transferring files using FTP. The firewall remembers the details of the
        > incoming request to get a file from an FTP server. The firewall then tracks the back-channel
        > request (the FTP Port command) by the server for transferring information back to the client.
        > As long as the information agrees (same IP addresses, no changes in port numbers, and no
        > non-FTP requests), the firewall allows the traffic. After the transfer is complete, the
        > firewall closes the ports involved.

        1.4.3 两种实现方法:
        1.4.3.1 checkpoint FW1,netfilter
        1.4.3.2 动态添加规则(ipchains patch)
        > I believe it does exactly what I want: Installing a temporary
               > "backward"-rule to let packets in as a response to an
               > outgoing request.


1.5 增强2-地址转换:
        1.5.1 静态NAT
        1.5.2 动态NAT
        1.5.3 地址伪装


1.6 增强3-VPN:
        位置的优越性

二 Linux下防火墙的实现之一(2.2内核):

2.1 截获位置:
        网络层

                  ----------------------------------------------------------------
                  |            ACCEPT/                              lo interface |
                  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_type *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_BLOCK,丢弃此包
                return(0);

        }

转发检测:
        int ip_forward(struct sk_buff *skb)
        {
        ...
        #ifdef CONFIG_FIREWALL
                        fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
                        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_ACCEPT.
        *
        *        The testing is either false for normal firewall mode or true for
        *        user checking mode (counters are not updated, TOS & mark not 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 device *dev,
                             void *phdr, void *arg, struct sk_buff **pskb)
        {
                return ip_fw_check(phdr, dev->name,
                                   arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
        }

实际流程:

        ip_fw_check
        {
                从传入的skb参数中提取源地址src,目的地址dst,源端口src_port,目的端口dst_port,
                TCP发起连接标志tcpsyn,分片包位移offset,IP包TOS消息oldtos;

                ......

                f = chain->chain;        //取出规则链的的一条规则,规则链由chain参数传入
                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,offset)) {
                                        if (!testing
                                            && !ip_fw_domatch(f, ip, rif, chain->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 each block */
                struct ip_chain *next;            /* Pointer to next block */
                struct ip_fwkernel *chain;  /* Pointer to first rule in block */
                __u32 refcount;             /* Number of refernces to block */
                int policy;                    /* Default rule for chain.  Only *
                                             * 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 current
                                                * rule doesn't match */
                struct ip_chain *branch;        /* which branch to jump to if
                                                * current rule matches */
                int simplebranch;                /* Use this if branch == NULL */
                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 packet */
                __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 output to
                                                           NETLINK */
                char           fw_vianame[IFNAMSIZ];        /* name of interface "via" */
                __u8           fw_tosand, fw_tosxor;        /* Revised packet priority */
        };

 


2.4 地址转换
        ip_fw_demasquerade
        ip_fw_masquerade


三 Linux下防火墙的实现之二(2.4内核):
3.1
        A Packet Traversing the Netfilter System:

        --->PRE------>[ROUTE]--->FWD---------->POST------>
               Conntrack    |       Filter   ^    NAT (Src)
               Mangle       |                |    Conntrack
               NAT (Dst)    |             [ROUTE]
               (QDisc)      v                |
                            IN Filter       OUT Conntrack
                            |  Conntrack     ^  Mangle
                            |                |  NAT (Dst)
                            v                |  Filter


3.2 例子

## Insert connection-tracking modules (not needed if built into kernel).
# insmod ip_conntrack
# insmod ip_conntrack_ftp

## Create chain which blocks new connections, except if coming from inside.
# iptables -N block
# iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT
# iptables -A block -j DROP

## Jump to that chain from INPUT and FORWARD chains.
# iptables -A INPUT -j block
# iptables -A FORWARD -j block

3.3 规则的描述
        一条规则分为三部分:
        struct ipt_entry        //主要用来匹配IP头
        struct ip_match        //额外的匹配(tcp头,mac地址等)
        struct ip_target        //除缺省的动作外(如ACCEPT,DROP),可以增加新的(如REJECT)。

3.4 代码提炼

ip_input.c:
        /*
        *         Main IP Receive routine.
        */
        int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
        {
        ...
        return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
                               ip_rcv_finish);
        ...
        }

netfilter.h:
        #ifdef CONFIG_NETFILTER
        #define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                        \
        (list_empty(&nf_hooks[(pf)][(hook)])                                        \
        ? (okfn)(skb)                                                                \
        : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn)))
        #else /* !CONFIG_NETFILTER */
        #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
        #endif /*CONFIG_NETFILTER*/

大的框架:"HOOK表":
        struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];        //netfilter.c
        通过nf_register_hook和nf_unregister_hook完成添加删除工作,nf_iterate负责执行hook上的函数。

        增加用户自定义的HOOK,参见【8】,【10】:

重要流程(建议结合netfilter hacking howto 4.1.3来看):
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ipt_do_table(struct sk_buff **pskb,
             unsigned int hook,
             const struct net_device *in,
             const struct net_device *out,
             struct ipt_table *table,
             void *userdata)
{
        struct ipt_entry *e;
        struct ipt_entry_target *t;
        unsigned int verdict = NF_DROP;

        table_base = (void *)table->private->entries
                + TABLE_OFFSET(table->private,
                               cpu_number_map(smp_processor_id()));
        e = get_entry(table_base, table->private->hook_entry[hook]);

        ...
        ip_packet_match(ip, indev, outdev, &e->ip, offset);

        ...
        IPT_MATCH_ITERATE(e, do_match, *pskb, in, out, offset, protohdr, datalen, &hotdrop)

        ...
        t = ipt_get_target(e);

        ...
        verdict = t->u.kernel.target->target(pskb, hook, in, out, t->data, userdata);//非标准的target走这一步

        ...
        return verdict;
}

要加强对这段话的理解(netfilter hacking howto 4.1节) :
>iptables does not register with any netfilter hooks: it relies on
>other modules to do that and feed it the packets as appropriate; a
>module must register the netfilter hooks and ip_tables separately, and
>provide the mechanism to call ip_tables when the hook is reached.



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。



网普科技,优质美国主机服务!
美国Linux主机,美国虚拟主机
支持PHP+MYSQL+cPanel+EMAIL
为用户负责,拒绝反动、赌博及色情内容! QQ:126818

发送QQ消息
2005-12-8 02:32 PM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
celn
网普高级成员





积分 209
发贴 197
注册 2004-6-30
状态 离线
#2  


工人是高手

2006-1-3 10:32 AM
查看资料  发送邮件  发短消息   编辑帖子  引用回复 顶部
茱莉娅
THE BODY SHOP美容顾问

茱莉娅美体小铺


积分 209
发贴 197
注册 2009-5-21
来自 茱莉娅美体小铺
状态 离线
#2  赞助商信息The body shop

茱莉娅美体小铺
茱莉娅美体小铺淘宝店
茱莉娅美体小铺
2006-1-3 10:32 AM
查看资料  发送邮件  发短消息   编辑帖子  引用回复 顶部


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转:  




Powered by Discuz! 2.5 © 2001-2005 Comsenz Technology Ltd.
Processed in 0.012233 second(s), 7 queries, Gzip enabled
------------------------------------------------------------------------------
本论坛属网普科技交流与技术支持论坛!
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!
美国主机, 美国虚拟主机, cPanel+PHP+Mysql+Ftp+Email+Zend+GD2+国际域名支持
技术支持 QQ: 126818 EMail & MSN: support[AT]netpu.net
[ 联系我们 ] - [ 网普科技 ]