关于尚观
最新课程体系
企业服务
零起点咨询
开放课程
报名咨询
免费资源申请
Oracle服务
学员专区&薪资
认证课程
  • 尚观首页
  • 尚观简介
  • 师资力量
  • 尚观文化
  • 尚观动态
  • 加入尚观
  • 联系我们
  • 珍贵瞬间
  • 院校合作
  • Linux系统与集群
  • 数据库集群架构师
  • 嵌入式内核驱动开发
  • 服务器开发架构师
  • Android开发架构师
  • RHCE/LPI认证体系
  • Oracle OCP认证
  • 企业高级技术培训
  • 批量人才供应及研发团队建设
  • 软件外包及研发项目合作
  • 人力外包及人力供应
  • 猎头服务
  • 开启职业生涯
  • 如何入门
  • Unix/Linux职业方向
  • 嵌入式职业方向
  • 集群(Cluster)Oracle(DBA)方向
  • 新手专栏
  • Android开发方向
  • Unix/Linux新手专栏
  • Unix/Linux管理
  • 嵌入式及POSIX开发
  • Linux开源文化及市场
  • 最近网络课堂
  • P2P教学视频
  • 精彩Linux培训视频
  • 零起点数据库集群(长期)
  • 嵌入式驱动(长期)
  • Linux金牌三证(RHCE级)
  • Linux架构师(RHCA级)
  • 嵌入式/驱动加速课程
  • Linux免费网络安全公开课
  • 免费Linux资料申请
  • 免费Linux安全&DDOS防御课程
  • 免费嵌入式Linux开发课程
  • 免费Linux网络安全机制
  • 尚观服务
  • 软件产品
  • 技术方案
  • 尚观支持
  • 学员毕业薪资(不断更新中)
  • 加入尚观猎头服务(仅限老学员)
  • OCP认证
  • Intel认证
  • RHCE认证
  • RHCE+OCP
  • RHCE+LPI
  • OCM认证
  • RHCA认证


    您现在的位置:尚观Linux培训 - 嵌入式Linux培训专家尚观Linux培训 » Unix/Linux管理 » 网络过滤器的基本结构(防火墙编程)

 
 
咨询热线
  • 免费咨询电话:
    400-700-0056
    800-810-0056

    教学就业监督电话:
    400-810-3016



  • 在线咨询
免费资源
  • [北京]Linux安全-4月24日
  • [沈阳]Linux嵌入式-4月24日
  • [上海]DDos攻防-4月24日
  • [上海]Linux嵌入式-4月24日
  • [深圳]DDos攻防-4月24日
  • [深圳]Linux嵌入式-4月24日
  • [北京]DDos攻防-4月24日
  • 就业课程
  • 免费课程
  • 五万年薪就业保证课程

  • ULP-S 尚观王者IT集群课程 v8.2版
  • UEA嵌入式内核驱动开发者 V8.2版
  • UGA-Android开发架构师 V3.2版
  • ULA-linux云存储集群架构师V8.2版
  • UOA-Oracle集群架构师课程V8.2版
  • 八万年薪就业保证课程

  • OCM10g-Oracle顶级数据库大师级
  • UEM-嵌入式开发大师
  • 纯免费!技术达人讲解Android系统通信互动程序开发! 5月24日
  • 纯免费! Shrek主讲Linux网络攻击及安全! 5月17日
  • 纯免费! 大牛讲解如何在开发板上构建Linux系统 5月10日
  • 纯免费! 尚观OCM大师主讲Oracle实时备份课程 4月26日
  • 纯免费! Shrek主讲Linux网络攻击及安全课程 4月11日
  • 纯免费!Foway为您解析OCM考试经验 3月2日
  • 纯免费!shrek主讲 linux网络攻击及安全课程 2月8日
  • 纯免费!连续3天,Android开发入门实战免费公开课 12月27日
  • 纯免费!“云”指南“嵌入式”指北大型讲座! 12月24日
Linux培训●最新开班
  • [北京]UGA课程5月班热招!
  • [北京]UEA课程5月班热报!
  • [北京]ULP-S课程5月班热招
  • [上海]UEA课程5月班热招!
  • [上海]ULP-S课程5月班热招
  • [上海]UGA课程5月班热招!
  • [深圳]ULP-S课程5月班热招
  • [深圳]UEA课程5月班热招!
 
网络过滤器的基本结构(防火墙编程)
  • (1)当IP包接收器(ip_rcv)接收到正确的IP包后, 首先注入"路由前过滤器"(NF_IP_PRE_ROUTING), 路由前过滤器的输出(ip_rcv_finish)包经过绑定路由和编绎IP选项区之后输入到路由入口(dst->input). 对于本地接收包来说, 路由入口指向IP本地分发器(ip_local_deliver), 本地分发器首先进行IP碎片重组, 然后将IP合成包注入"本地输入过滤器"(NF_IP_LOCAL_IN),  本地输入过滤器的输出(ip_local_deliver_finish)包进一步传递到IP传输协议控制器(igmp_rcv,tcp_v4_rcv,udp_rcv,icmp_rcv), 最后包被投送到各个套接字的接收队列中. 对于转发包来说, 路由入口将指向IP转发器(ip_forward), 转发器对IP包预处理后注入"IP转发过滤器"(NF_IP_FORWARD), 转发过滤器的输出(ip_forward_finish)包经过分片处理后通过路由出口(dst->output)注入"IP路由后过滤器"(NF_IP_POST_ROUTING), 路由后过滤器的输出(ip_finish_output2)包通过邻居出口(dst->neighbour->output)创建硬件帧头后(或在ip_finish_output2中直接创建帧头从dst->hh->hh_output输出)输入到包调度器(dev_queue_xmit)中进行排队发射. 对于本地发送包来说, IP包生成器产生的输出包首先注入"本地输出过滤器"(NF_IP_LOCAL_OUT),  本地过滤器的输出(output_maybe_reroute)包经过分片处理(ip_fragment)后再通过路由出口从路由后过滤器输出.

    (2)
    网络过滤器用nf_hooks_ops结构描述, 系统中所有的网络包过滤器都登记在网络过滤器钩链数组(nf_hooks)中, 它是用网络协议族编号和过滤器编号索引的二维链头(list_head)结构数组, 数组的每一元素代表一种过滤器链. 网络过滤器以NF_HOOK(family,num,skb,indev,outdev,output)宏定义插入到代码中. 当执行到NF_HOOK()时, 如果nf_hooks[family][num]过滤器链非空, 系统将调用nf_hook_slow(family,num,skb,indev,outdev,output)将包依次传递给过滤链中的过滤函数. 在每一个过滤环节上, 如果过滤函数返回NF_ACCEPT,  则过滤包允许输出, 这时过滤包将注入下一链节过滤器或者调用output参数函数将过滤包输出. 如果过滤函数返回NF_DROP, 则过滤过程被终止, 过滤包禁止输出并被释放. 如果过滤函数返回NF_STOLEN, 说明输入包已被转移走, 终止过滤无输出,. 如果过滤函数返回NF_REPEAT,  过滤包将重新过滤一次. 如果过滤函数返回NF_QUEUE, 则当前过滤参数和输入包将被传递到过滤器协议族的过滤队列中进行处理(queue_handler).

    ; include/linux/netfilter.h:

    #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)))
    #endif

    /* Largest hook number + 1 */
    #define NF_MAX_HOOKS 8

    typedef unsigned int nf_hookfn(unsigned int hooknum,
                                struct sk_buff **skb,
                                const struct net_device *in,
                                const struct net_device *out,
                                int (*okfn)(struct sk_buff *));

    struct nf_hook_ops
    {
           struct list_head list;

           /* User fills in from here down. */
           nf_hookfn *hook;
    过滤函数
           int pf;
    过滤器的协议族
           int hooknum;
    过滤器编号
           /* Hooks are ordered in ascending priority. */
           int priority;
    过滤器优先级, 同一协议族的过滤器以priority值作升序排列
    };
    /* Each queued (to userspace) skbuff has one of these. */
    struct nf_info
    {
           /* The ops struct which sent us to userspace. */
           struct nf_hook_ops *elem;
          
           /* If we're sent to userspace, this keeps housekeeping info */
           int pf;
           unsigned int hook;
           struct net_device *indev, *outdev;
           int (*okfn)(struct sk_buff *);
    };

    ; net/core/netfilter.c:

    struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];

    /*
     * A queue handler may be registered for each protocol.  Each is protected by
     * long term mutex.  The handler must provide an an outfn() to accept packets
     * for queueing and must reinject all packets it receives, no matter what.
     */
    static struct nf_queue_handler_t {
           nf_queue_outfn_t outfn;
           void *data;
    } queue_handler[NPROTO];

    typedef int (*nf_queue_outfn_t)(struct sk_buff *skb,
                                    struct nf_info *info, void *data);

    ; net/core/netfilter.c:

    int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
                   struct net_device *indev,
                   struct net_device *outdev,
                   int (*okfn)(struct sk_buff *))
    {
           struct list_head *elem;
           unsigned int verdict;
           int ret = 0;

           /* We may already have this, but read-locks nest anyway */
           br_read_lock_bh(BR_NETPROTO_LOCK);

    #ifdef CONFIG_NETFILTER_DEBUG
           if (skb->nf_debug & (1 << hook)) {
                  printk("nf_hook: hook %i already set.\n", hook);
                  nf_dump_skb(pf, skb);
           }
           skb->nf_debug |= (1 << hook);
    #endif

           elem = &nf_hooks[pf][hook];
           verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
                              outdev, &elem, okfn);
           if (verdict == NF_QUEUE) {
                  NFDEBUG("nf_hook: Verdict = QUEUE.\n");
                  nf_queue(skb, elem, pf, hook, indev, outdev, okfn);
           }
          
           switch (verdict) {
           case NF_ACCEPT:
                  ret = okfn(skb);
                  break;

           case NF_DROP:
                  kfree_skb(skb);
                  ret = -EPERM;
                  break;
           }

           br_read_unlock_bh(BR_NETPROTO_LOCK);
           return ret;
    }

    static unsigned int nf_iterate(struct list_head *head,
                                struct sk_buff **skb,
                                int hook,
                                const struct net_device *indev,
                                const struct net_device *outdev,
                                struct list_head **i,
                                int (*okfn)(struct sk_buff *))
    迭代过滤器
    {
           for (*i = (*i)->next; *i != head; *i = (*i)->next) {
    扫描过滤器的环形链表
                  struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
    取过滤器结构
                  switch (elem->hook(hook, skb, indev, outdev, okfn)) {
    调用过滤函数
                  case NF_QUEUE:
                         return NF_QUEUE;

                  case NF_STOLEN:
                         return NF_STOLEN;

                  case NF_DROP:
                         return NF_DROP;

                  case NF_REPEAT:
                         *i = (*i)->prev;
                         break;

    #ifdef CONFIG_NETFILTER_DEBUG
                  case NF_ACCEPT:
                         break;

                  default:
                         NFDEBUG("Evil return from %p(%u).\n",
                                elem->hook, hook);
    #endif
                  }
           }
           return NF_ACCEPT;
    }
    /*
     * Any packet that leaves via this function must come back
     * through nf_reinject().
     */
    static void nf_queue(struct sk_buff *skb,
                       struct list_head *elem,
                       int pf, unsigned int hook,
                       struct net_device *indev,
                       struct net_device *outdev,
                       int (*okfn)(struct sk_buff *))
    {
           int status;
           struct nf_info *info;

           if (!queue_handler[pf].outfn) {
                  kfree_skb(skb);
                  return;
           }

           info = kmalloc(sizeof(*info), GFP_ATOMIC);
           if (!info) {
                  if (net_ratelimit())
                         printk(KERN_ERR "OOM queueing packet %p\n",
                                skb);
                  kfree_skb(skb);
                  return;
           }

           *info = (struct nf_info) {
                  (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
    保存过滤参数

           /* Bump dev refs so they don't vanish while packet is out */
           if (indev) dev_hold(indev);
           if (outdev) dev_hold(outdev);

           status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);
           if (status < 0) {
                  /* James M doesn't say [censored] enough. */
                  if (indev) dev_put(indev);
                  if (outdev) dev_put(outdev);
                  kfree(info);
                  kfree_skb(skb);
                  return;
           }
    }
    void nf_reinject(struct sk_buff *skb, struct nf_info *info,
                   unsigned int verdict)
    将包和它的过滤参数重新注入过滤器
    {
           struct list_head *elem = &info->elem->list;
           struct list_head *i;

           /* We don't have BR_NETPROTO_LOCK here */
           br_read_lock_bh(BR_NETPROTO_LOCK);
           for (i = nf_hooks[info->pf][info->hook].next; i != elem; i = i->next) {
                  if (i == &nf_hooks[info->pf][info->hook]) {
                         /* The module which sent it to userspace is gone. */
                         NFDEBUG("%s: module disappeared, dropping packet.\n",
                                  __FUNCTION__);
                         verdict = NF_DROP;
                         break;
                  }
           }

           /* Continue traversal iff userspace said ok... */
           if (verdict == NF_REPEAT) {
                  elem = elem->prev;
                  verdict = NF_ACCEPT;
           }

           if (verdict == NF_ACCEPT) {
                  verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
                                     &skb, info->hook,
                                     info->indev, info->outdev, &elem,
                                     info->okfn);
           }

           switch (verdict) {
           case NF_ACCEPT:
                  info->okfn(skb);
                  break;

           case NF_QUEUE:
                  nf_queue(skb, elem, info->pf, info->hook,
                          info->indev, info->outdev, info->okfn);
                  break;

           case NF_DROP:
                  kfree_skb(skb);
                  break;
           }
           br_read_unlock_bh(BR_NETPROTO_LOCK);

           /* Release those devices we held, or Alexey will kill me. */
           if (info->indev) dev_put(info->indev);
           if (info->outdev) dev_put(info->outdev);
          
           kfree(info);
           return;
    }

    int nf_register_hook(struct nf_hook_ops *reg)
    注册过滤器
    {
           struct list_head *i;

           br_write_lock_bh(BR_NETPROTO_LOCK);
           for (i = nf_hooks[reg->pf][reg->hooknum].next;
                i != &nf_hooks[reg->pf][reg->hooknum];
                i = i->next) {
                  if (reg->priority < ((struct nf_hook_ops *)i)->priority)
                         break;
           }
           list_add(®->list, i->prev);
           br_write_unlock_bh(BR_NETPROTO_LOCK);
           return 0;
    }
    void nf_unregister_hook(struct nf_hook_ops *reg)
    {
           br_write_lock_bh(BR_NETPROTO_LOCK);
           list_del(®->list);
           br_write_unlock_bh(BR_NETPROTO_LOCK);
    }
    int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
    注册过滤队列处理器
    {     
           int ret;

           br_write_lock_bh(BR_NETPROTO_LOCK);
           if (queue_handler[pf].outfn)
                  ret = -EBUSY;
           else {
                  queue_handler[pf].outfn = outfn;
                  queue_handler[pf].data = data;
                  ret = 0;
           }
           br_write_unlock_bh(BR_NETPROTO_LOCK);

           return ret;
    }
    /* The caller must flush their queue before this */
    int nf_unregister_queue_handler(int pf)
    {
           br_write_lock_bh(BR_NETPROTO_LOCK);
           queue_handler[pf].outfn = NULL;
           queue_handler[pf].data = NULL;
           br_write_unlock_bh(BR_NETPROTO_LOCK);
           return 0;
    }




    精彩Linux视频、嵌入式视频、Android视频、Oracle视频,免费先学!
    查看:尚观Linux培训学员最新就业薪资待遇统计报告!
    查看:UGA-4G Android开发架构师大纲
    查看:UDA-Linux服务器开发架构师大纲
    查看:UEA-嵌入式内核驱动开发者大纲
    查看:UOA-Oracle数据库集群架构大纲
    查看:ULA-Linux系统与集群架构师大纲

    填表获取 Linux、嵌入式、Oracle 技术资料

  • 姓    名:
  • 固    话:
  • 手    机:
  • E-Mail :
  • 所在地:
  •         

北京(总部)

电子地图
电话:(010)62113016/17 68949060
地址:北京海淀区中关村南大街 甲10号 银海大厦南区410-418

上海(Shanghai)

电子地图
电话:(021)64859996 64859889
地址:上海徐汇区钦江路333号漕河泾开发区38号楼申能科技3楼

深圳(Shenzhen)

电子地图
电话:(0755)82995128 82995168
地址:深圳福田区 彩田路 中深花园B2005室

沈阳(Shenyang)

电子地图
电话:(024)31500816 31500817
地址:沈阳和平区三好街54号物产科贸大厦2号楼201室

大连(Dalian)

电子地图
电话:(0411)84336822 84326822
地址:大连沙河口区西安路86号行政大厦(罗斯福广场对面)17楼1705室

成都(Chengdu)

电子地图
电话:(028)66677820 66677828
地址:成都青羊区上西顺城街252号顺吉大厦8楼B4

广州(Guangdong)

电子地图
电话:(020) 88900632 81368992
地址:广州市越秀区人民北路612号中广大厦9层(国际银行中心旁)

南京(Nanjing)

电子地图
电话:(025)83176720 83176710
地址:南京新街口广场中山东路9号天时科技园12层G、H单元

武汉(Wuhan)

电子地图
电话:(027)87596339
地址:武汉市洪山区鲁磨路118号国光大厦A座1201室1203室




2005-2009高新技术企业

LPI授权培训考试中心

CSDN战略伙伴

51Job战略伙伴

Oracle WDP授权培训与考试中心

Intel软件服务培训供应商

Redhat授权培训与考试中心

高新技术企业证书
 

友情链接(联系QQ:304853420):   LPI  RedHat  CSDN  ChinaUnix  ITPub  Eygle.Com  Linux培训  嵌入式培训  Linux联盟  Unix爱好者  51CTO开发 尚观知识库 天极导航  PHP中国  网易教育  天津赶集网  工具软件下载  连锁加盟  天极网南京站  个人简历模板  北京赶集网  畅享网  网页制作  Linux  ZOL服务器  广告联盟  颈椎病的症状  21CN教育  亿芯网  强直性脊柱炎  数码比价网  投资创业  DJ网站  嵌入式技术网  OCM培训  股票入门  大功率LED网   搜电网  杭州写字楼网  时尚论坛  医药营销联盟  Linux技术中心  泉州人才网  大学后  天天健康  RHCE培训  SVN中文技术网  网罗天下  Oracle培训  北京法律咨询  嵌入式资讯网  Fedora中文爱好者  沸点100网   教培英才网  中国二手车城  Linux公社  Oracle教程  深圳本地宝  狂人网  0090网址大全  数码比价网  中国程序员人才网  IT英才网

  • PR
COPYRIGHT © 2000-2009 北京尚观科技有限公司 - 北京市海淀区尚观培训学校 - Linux培训及嵌入式培训专家 ALL RIGHTS RESERVED

咨询热线:400-700-0056    800-810-0056
在线咨询:QQ:814996026    院校洽谈合作专线:13911737012(张老师)
京ICP备09018548号 | Linux就业信息 | 免责声明 | 隐私声明 |