linux内核不支持 分片包,LINUX内核中Netfilter Hook的使用

2.6内核中netfilter hook点一览

本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。

msn:

来源:http://yfydz.cublog.cn

1. 5个挂接点

以下内核代码版本2.6.17.11。

1.1 PREROTING

/* net/ipv4/ip_input.c */

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)

{

......

return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,

ip_rcv_finish);

......

}

1.2 INPUT

/* net/ipv4/ip_input.c */

int ip_local_deliver(struct sk_buff *skb)

{

......

return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,

ip_local_deliver_finish);

}

1.3 FORWARD

/* net/ipv4/ip_forward.c */

int ip_forward(struct sk_buff *skb)

{

......

return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, rt->u.dst.dev,

ip_forward_finish);

......

}

1.4 OUTPUT

/* net/ipv4/ip_output.c */

int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,

u32 saddr, u32 daddr, struct ip_options *opt)

{

......

return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,

dst_output);

}

int ip_queue_xmit(struct sk_buff *skb, int ipfragok)

{

......

return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,

dst_output);

......

}

int ip_push_pending_frames(struct sock *sk)

{

......

/* Netfilter gets whole the not fragmented skb. */

err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,

skb->dst->dev, dst_output);

......

}

1.5 POSTROUTING

/* net/ipv4/ip_output.c */

int ip_output(struct sk_buff *skb)

{

struct net_device *dev = skb->dst->dev;

IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);

skb->dev = dev;

skb->protocol = htons(ETH_P_IP);

return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,

ip_finish_output,

!(IPCB(skb)->flags & IPSKB_REROUTED));

}

2. 每个挂接点所挂接的hook操作

只考虑是AF_INET协议族的挂接点,以下各点的hook操作按执行顺序排序,优先级数值越小,级别越高,执行顺序越靠前。

如果用户可以通过iptables规则进行控制的处理点称为用户可控,否则为不可控。

2.1 PREREOUTING

/* net/bridge/br_netfilter.c */

// 这个hook点只丢弃skb结构中设置桥参数但没有相关桥标志的包

// 用户不可控

{ .hook = ip_sabotage_in,

.owner = THIS_MODULE,

.pf = PF_INET,

.hooknum = NF_IP_PRE_ROUTING,

// 优先级最高

.priority = NF_IP_PRI_FIRST,

},

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 这个hook点完成分片重组,以后处理过程中的包都是非分片包

// 直到发送出去重新分片。注意2.6重组后的分片包并不进行线性

// 化,所以逻辑上应该连在一起的两字节数据可能分属不同的页,

// 存储是不连续的

// 该点操作用户不可控

{

.hook  = ip_conntrack_defrag,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_PRE_ROUTING,

// 优先级为-400

.priority = NF_IP_PRI_CONNTRACK_DEFRAG,

},

/* net/ipv4/netfilter/iptable_raw.c */

// 这个hook点为raw表,提供对收到的数据包在连接跟踪前进行处理的手段

// 该点用户可加载iptables规则进行控制

{

.hook = ipt_hook,

.pf = PF_INET,

.hooknum = NF_IP_PRE_ROUTING,

// 优先级为-300

.priority = NF_IP_PRI_RAW,

.owner = THIS_MODULE,

},

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 这个hook点完成连接跟踪,为每个skb找到所属连接(ESTABLISHED, REPLY)

// 或新建连接(NEW, RELATED)

// 该点操作用户不可控

{

.hook  = ip_conntrack_in,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_PRE_ROUTING,

// 优先级为-200

.priority = NF_IP_PRI_CONNTRACK,

},

/* net/ipv4/netfilter/iptable_mangle.c */

// 这个hook点为mangle表,提供对收到的数据包进行修改的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_route_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_PRE_ROUTING,

// 优先级为-150

.priority = NF_IP_PRI_MANGLE,

},

/* net/ipv4/netfilter/ip_nat_standalone.c */

// 该hook点对刚收到本机的skb包进行目的NAT操作

// 用户规则可控,nat表,但规则只对NEW包进行处理,后续包自动处理

{

.hook  = ip_nat_in,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_PRE_ROUTING,

// 优先级为-100

.priority = NF_IP_PRI_NAT_DST,

},

/* net/sched/sch_ingress.c */

// 该hook点对j进入本机的skb包进行排队处理,QoS操作

// 用户不可控

static struct nf_hook_ops ing_ops = {

.hook           = ing_hook,

.owner  = THIS_MODULE,

.pf             = PF_INET,

.hooknum        = NF_IP_PRE_ROUTING,

// 优先级为1

.priority       = NF_IP_PRI_FILTER + 1,

};

2.2 INPUT

/* net/ipv4/netfilter/iptable_mangle.c */

// 这个hook点为mangle表,提供对收到的数据包进行修改的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_route_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_IN,

// 优先级为-150

.priority = NF_IP_PRI_MANGLE,

},

/* net/ipv4/netfilter/iptable_filter.c */

// 这个hook点为filter表,提供对进入本机的数据包进行过滤的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_IN,

// 优先级为0

.priority = NF_IP_PRI_FILTER,

},

/* net/ipv4/netfilter/ip_nat_standalone.c */

// 对进入本机的skb包进行源NAT操作

// 用户规则可控,nat表,但规则只对NEW包进行处理,后续包自动处理

{

.hook  = ip_nat_fn,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_IN,

// 优先级为100

.priority = NF_IP_PRI_NAT_SRC,

},

/* net/ipv4/ipvs/ip_vs_core.c */

// 该hook点对进入本机的skb包均衡分配

// 用户不可控

static struct nf_hook_ops ip_vs_in_ops = {

.hook  = ip_vs_in,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum        = NF_IP_LOCAL_IN,

.priority       = 100,

};

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 该hook点对进入本机的skb包完成对连接跟踪的help,也就是

// 多连接协议中对子连接的处理

// 用户不可控

{

.hook  = ip_conntrack_help,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_IN,

// 优先级为INT_MAX-2,相当低

.priority = NF_IP_PRI_CONNTRACK_HELPER,

},

/* net/ipv4/netfilter/ip_nat_standalone.c */

// 对进入本机的skb包进行TCP序列号调整操作,主要是因为跟踪多连接协议时

// 修改了数据包内容可能导致数据包长度发生变化,相应序列号和确认号需要

// 自动调整

// 用户规则不可控

{

.hook  = ip_nat_adjust,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_IN,

// 优先级为INR_MAX-1,相当低

.priority = NF_IP_PRI_NAT_SEQ_ADJUST,

},

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 该hook点对进入本机的skb包完成最后的确认,只对NEW包处理

// 确认NEW的连接信息在当前的连接表中是不存在的

// 用户不可控

{

.hook  = ip_confirm,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_IN,

// 优先级为INT_MAX,最低

.priority = NF_IP_PRI_CONNTRACK_CONFIRM,

},

2.3 FORWARD

/* net/bridge/br_netfilter.c */

// 这个hook点对由桥网卡转发的skb包设置桥信息和物理网卡等信息

// 该函数可能会返回NF_STOP不进行后续hook点的处理

// 用户不可控

{ .hook = ip_sabotage_out,

.owner = THIS_MODULE,

.pf = PF_INET,

.hooknum = NF_IP_FORWARD,

// 优先级为-175

.priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD,

},

/* net/ipv4/netfilter/iptable_mangle.c */

// 这个hook点为mangle表,提供对收到的数据包进行修改的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_route_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_FORWARD,

// 优先级为-150

.priority = NF_IP_PRI_MANGLE,

},

/* net/ipv4/netfilter/iptable_filter.c */

// 这个hook点为filter表,提供对转发的数据包进行过滤的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_FORWARD,

// 优先级为0

.priority = NF_IP_PRI_FILTER,

},

/* net/ipv4/ipvs/ip_vs_core.c */

// 该hook点对转发的skb包均衡分配前处理ICMP异常

// 用户不可控

static struct nf_hook_ops ip_vs_forward_icmp_ops = {

.hook  = ip_vs_forward_icmp,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum        = NF_IP_FORWARD,

.priority       = 99,

};

/* net/ipv4/ipvs/ip_vs_core.c */

// 该hook点对转发的skb包均衡分配

// 用户不可控

static struct nf_hook_ops ip_vs_out_ops = {

.hook  = ip_vs_out,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum        = NF_IP_FORWARD,

.priority       = 100,

};

3.4 OUTPUT

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 这个hook点对自身发出的包完成分片重组,以后处理过程中的包都是非分片包

// 直到最后发送出去重新分片。注意2.6重组后的分片包并不进行线性

// 化,所以逻辑上应该连在一起的两字节数据可能分属不同的页,

// 存储是不连续的

// 该点操作用户不可控

{

.hook  = ip_conntrack_defrag,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为-400

.priority = NF_IP_PRI_CONNTRACK_DEFRAG,

},

/* net/ipv4/netfilter/iptable_raw.c */

// 这个hook点为raw表,提供对本机发出数据包在连接跟踪前进行处理的手段

// 该点用户可加载iptables规则进行控制

{

.hook = ipt_hook,

.pf = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为-300

.priority = NF_IP_PRI_RAW,

.owner = THIS_MODULE,

},

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 这个hook点对自身发出的包完成连接跟踪,为每个skb找到所属连接

// (ESTABLISHED, REPLY)或新建连接(NEW, RELATED)

// 该点操作用户不可控

{

.hook  = ip_conntrack_local,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为-200

.priority = NF_IP_PRI_CONNTRACK,

},

/* net/ipv4/netfilter/iptable_mangle.c */

// 这个hook点为mangle表,提供对收到的数据包进行修改的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_local_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为-150

.priority = NF_IP_PRI_MANGLE,

},

/* net/ipv4/netfilter/ip_nat_standalone.c */

// 对本机发出的skb包进行目的NAT操作

// 用户规则可控,nat表,但规则只对NEW包进行处理,后续包自动处理

{

.hook  = ip_nat_local_fn,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为-100

.priority = NF_IP_PRI_NAT_DST,

},

/* net/bridge/br_netfilter.c */

// 这个hook点对由桥网卡发出的skb包设置桥信息和物理网卡等信息

// 该函数会返回NF_STOP,提前终止检查而返回

// 用户不可控

{ .hook = ip_sabotage_out,

.owner = THIS_MODULE,

.pf = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为-50

.priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT,

},

/* net/ipv4/netfilter/iptable_filter.c */

// 这个hook点为filter表,提供对本机发出的数据包进行过滤的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_local_out_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_LOCAL_OUT,

// 优先级为0

.priority = NF_IP_PRI_FILTER,

},

2.5 POSTROUTING

/* net/bridge/br_netfilter.c */

// 这个hook点对由桥网卡发出的skb包设置桥信息和物理网卡等信息

// 该函数会返回NF_STOP,提前终止检查而返回

// 用户不可控

{ .hook = ip_sabotage_out,

.owner = THIS_MODULE,

.pf = PF_INET,

.hooknum = NF_IP_POST_ROUTING,

// 优先级最高

.priority = NF_IP_PRI_FIRST, },

/* net/ipv4/netfilter/iptable_mangle.c */

// 这个hook点为mangle表,提供对收到的数据包进行修改的处理

// 该点用户可加载iptables规则进行控制

{

.hook  = ipt_route_hook,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_POST_ROUTING,

// 优先级为-150

.priority = NF_IP_PRI_MANGLE,

},

/* net/ipv4/ipvs/ip_vs_core.c */

// 该hook点对IPVS本身的控制包直接返回NF_STOP不进行后续hook点处理

// 用户不可控

static struct nf_hook_ops ip_vs_post_routing_ops = {

.hook  = ip_vs_post_routing,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum        = NF_IP_POST_ROUTING,

// 优先级为99

.priority       = NF_IP_PRI_NAT_SRC-1,

};

/* net/ipv4/netfilter/ip_nat_standalone.c */

// 对本机发出的skb包进行源NAT操作

// 用户规则可控,nat表,但规则只对NEW包进行处理,后续包自动处理

{

.hook  = ip_nat_out,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_POST_ROUTING,

// 优先级为100

.priority = NF_IP_PRI_NAT_SRC,

},

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 该hook点对转发的skb包完成对连接跟踪的help,也就是

// 多连接协议中对子连接的处理

// 用户不可控

{

.hook  = ip_conntrack_help,

.owner  = THIS_MODULE,

.pf  = PF_INET,

// 优先级为INT_MAX-2,相当低

.hooknum = NF_IP_POST_ROUTING,

.priority = NF_IP_PRI_CONNTRACK_HELPER,

},

/* net/ipv4/netfilter/ip_nat_standalone.c */

// 对发出本机的skb包进行TCP序列号调整操作,主要是因为跟踪多连接协议时

// 修改了数据包内容可能导致数据包长度发生变化,相应序列号和确认号需要

// 自动调整

// 用户规则不可控

{

.hook  = ip_nat_adjust,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_POST_ROUTING,

// 优先级为INR_MAX-1,相当低

.priority = NF_IP_PRI_NAT_SEQ_ADJUST,

},

/* net/ipv4/netfilter/ip_conntrack_standalone.c */

// 该hook点对进入本机的skb包完成最后的确认,只对NEW包处理

// 确认NEW的新连接信息在当前的连接表中是不存在的

// 用户不可控

{

.hook  = ip_confirm,

.owner  = THIS_MODULE,

.pf  = PF_INET,

.hooknum = NF_IP_POST_ROUTING,

// 优先级为INT_MAX,最低

.priority = NF_IP_PRI_CONNTRACK_CONFIRM,

},

3. 结论

由此可见,即使内核不支持bridge,

ipvs和sched,一个转发包通过netfilter时也会经过12个处理点的处理,任何一点的拒绝都会使该包丢弃,在各点的控制处理功能可以高度集

中,象流水线的各个环节一样。如果能用多核处理器能让比较费资源的点单独跑一个核,各个核的处理结果进行流水线,系统效率的提升肯定会很高,可惜这种

AMP处理还是"Mission

impossible",当前的SMP处理方式只会使netfilter架构效率很低,什么时候可以把“im”去掉还要等待。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值