Netfilter之DNAT和SNAT

来源:互联网 发布:java drawimage 厘米 编辑:程序博客网 时间:2024/05/29 13:47


NetfilterDNATSNAT

一.概述

netfilter中有四个表,filter, nat, mangle, raw表;其中常用的前三个表。Filter表执行过滤的功能,如包的放行,丢弃,转发至用户地址空间等;nat表,包的源地址或者目标地址转换等;mangle表,对包的参数就行更改,如设置mark值, ttl值等。本文重点描述nat表。

二.Nat

2.1初始化

static int __initnf_nat_standalone_init(void)

{

      intret = 0;

……………….

      ret= nf_nat_rule_init(); //初始化nat

……………….

      ret= nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); //注册NF_HOOK()中的钩子函数,定义在结构体nf_nat_ops该结构体函数被定义到框架nf_hooks[NPROTO][NF_MAX_HOOKS]中。

………………..

      returnret;

}

 

2.2钩子结构体nf_nat_ops

static struct nf_hook_ops nf_nat_ops[]__read_mostly = {

      /*Before packet filtering, change destination */

      {

             .hook            =nf_nat_in,

             .owner          = THIS_MODULE,

             .pf         = PF_INET,

             .hooknum      = NF_INET_PRE_ROUTING,

             .priority = NF_IP_PRI_NAT_DST,

      },

      /*After packet filtering, change source */

      {

             .hook            =nf_nat_out,

             .owner          = THIS_MODULE,

             .pf         = PF_INET,

             .hooknum      = NF_INET_POST_ROUTING,

             .priority = NF_IP_PRI_NAT_SRC,

      },

      /*Before packet filtering, change destination */

      {

             .hook            =nf_nat_local_fn,

             .owner          = THIS_MODULE,

             .pf         = PF_INET,

             .hooknum      = NF_INET_LOCAL_OUT,

             .priority = NF_IP_PRI_NAT_DST,

      },

      /*After packet filtering, change source */

      {

             .hook            =nf_nat_fn,

             .owner          = THIS_MODULE,

             .pf         = PF_INET,

             .hooknum      = NF_INET_LOCAL_IN,

             .priority = NF_IP_PRI_NAT_SRC,

      },

};

 

2.3表和target函数的定义

int __init nf_nat_rule_init(void)

{

      intret;

……………….

      nat_table= ipt_register_table(&init_net, &__nat_table,

                                 &nat_initial_table.repl);

……………….

      ret= xt_register_target(&ipt_snat_reg);

……………….

      ret= xt_register_target(&ipt_dnat_reg);//看下文将该target注册到链表xt[af].target

……………….

      returnret;

}

 

xt_register_target(struct xt_target*target)

{

      intret, af = target->family;

……………………

      list_add(&target->list,&xt[af].target);

……………………

      returnret;

}

 

注册了以下的两个target后,当用iptables命令设置DNAT或则SNAT时,会将该target及参数组织成规则rule,组装成struct ipt_entry,即为规则体。

 

iptables –t nat –A POSTROUTING –s 192.168.0.0/24 –j SNAT –to 1.1.1.1

iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 80 -jDNAT --to 192.168.0.1

 

static struct xt_targetipt_snat_reg __read_mostly = {

      .name            = "SNAT",

      .target           = ipt_snat_target,

      .targetsize      = sizeof(structnf_nat_multi_range_compat),

      .table            = "nat",

      .hooks           = 1 << NF_INET_POST_ROUTING,

      .checkentry    = ipt_snat_checkentry,

      .family          = AF_INET,

};

 

static struct xt_target ipt_dnat_reg __read_mostly = {

      .name            = "DNAT",

      .target           = ipt_dnat_target,

      .targetsize      = sizeof(structnf_nat_multi_range_compat),

      .table            = "nat",

      .hooks           = (1 << NF_INET_PRE_ROUTING) |(1 << NF_INET_LOCAL_OUT),

      .checkentry    = ipt_dnat_checkentry,

      .family          = AF_INET,

};

 

2.4钩子函数的执行,以nf_nat_in为例

nf_nat_in(unsigned int hooknum,

       struct sk_buff *skb,

       const struct net_device *in,

       const struct net_device *out,

       int (*okfn)(struct sk_buff *))

{

      unsignedint ret;

      __be32daddr = ip_hdr(skb)->daddr;

 

      ret=nf_nat_fn(hooknum, skb, in, out, okfn);

      if(ret != NF_DROP && ret != NF_STOLEN &&

         daddr != ip_hdr(skb)->daddr) {

             dst_release(skb->dst);//该路由项为空,后面会进入路由系统进行选择路由

             skb->dst= NULL;

      }

      returnret;

}

下面重点看nf_nat_fn()


2.5 target函数的执行


static unsigned int ipt_snat_target(structsk_buff *skb,

                              const struct net_device *in,

                              const struct net_device *out,

                              unsigned int hooknum,

                              const struct xt_target *target,

                              const void *targinfo)

{

………………….

             ct = nf_ct_get(skb, &ctinfo);

………………….

             nf_nat_setup_info(ct,&mr->range[0], IP_NAT_MANIP_SRC);

主要是为新的连接建立连接跟踪记录

………………….

}




0 0
原创粉丝点击