netfilter 分析

56
www.kernelchina.org NETFILTER 分分 [email protected] 2006/2

Upload: odele

Post on 18-Mar-2016

257 views

Category:

Documents


15 download

DESCRIPTION

NETFILTER 分析. [email protected] 2006/2. 目录. introduction netfilter conntrack nat alg extension iptables match target programming netfilter. 防火墙是什么. 网络报文的选择,监控,过滤系统 部署在网络边界,关键路径上 网络报文的表示 策略的表示. 防火墙的类型. 包过滤 应用代理 状态检测. LINUX 防火墙的发展历史. linux2.0.x:ipfw linux2.2.x:ipchains - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: NETFILTER 分析

www.kernelchina.org

NETFILTER 分析[email protected]

2006/2

Page 2: NETFILTER 分析

www.kernelchina.org

目录 introduction netfilter conntrack nat alg extension iptables match target programming netfilter

Page 3: NETFILTER 分析

www.kernelchina.org

防火墙是什么 网络报文的选择,监控,过滤系统 部署在网络边界,关键路径上 网络报文的表示 策略的表示

Page 4: NETFILTER 分析

www.kernelchina.org

防火墙的类型 包过滤 应用代理 状态检测

Page 5: NETFILTER 分析

www.kernelchina.org

LINUX 防火墙的发展历史 linux2.0.x : ipfw linux2.2.x : ipchains linux2.4.x : iptables linux2.6.x : iptables

Page 6: NETFILTER 分析

www.kernelchina.org

nf_hooks[NPROTO][NF_MAX_HOOKS]

• NPROTO = 32 ,支持协议族的数量• NF_MAX_HOOKS = 8 ,支持检查点的数量• 检查点上的 nf_hook_ops 结构,按 priority 的值,从小到大排列

nf_hook_ops

检查点

Page 7: NETFILTER 分析

www.kernelchina.org

struct nf_hook_ops{

struct list_head list;nf_hookfn *hook;int pf;int hooknum; int priority;

};

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 *));

• list :链表结构; hook :检查点上调用的函数; pf :协议族;hooknum :检查点的编号; priority :此结构的优先级• nf_register_hook :注册 nf_hook_ops 结构• nf_unregister_hook :卸载 nf_hoop_ops 结构

检查点上的数据结构

Page 8: NETFILTER 分析

www.kernelchina.org

#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)))• NF_HOOK :定义检查点• (okfn)(skb) :如果检查点上没有钩子函数,直接调用这个函数;如果有钩子函数,则先遍历检查点上的钩子函数,并根据钩子函数的返回值来确定下一步的动作;如果钩子函数完全遍历,同样需要调用这个函数• nf_hook_slow :遍历检查点上的 nf_hook_ops 结构,并调用nf_hookfn

检查点的定义

Page 9: NETFILTER 分析

www.kernelchina.org

NF_DROP : 禁止包通过NF_ACCEPT : 允许包通过NF_STOLEN : 包被本机缓存NF_QUEUE : 把包发送到用户空间NF_REPEAT : 重复上一次遍历过程

NF_HOOK

nf_hook_slow

nf_hookfn

(okfn)返回值

检查点的调用流程

Page 10: NETFILTER 分析

www.kernelchina.org

检查点在 PF_INET 中的位置NF_IP_PRE_ROUTING

NF_IP_LOCAL_IN NF_IP_LOCAL_OUT

NF_IP_FORWARD

NF_IP_POST_ROUTING

ROUTE

ROUTE

链路层

传输层

网络层

Page 11: NETFILTER 分析

www.kernelchina.org

NF_IP_PRE_ROUTINGHOOK FUNCTION FILE

NF_IP_PRE_ROUTING ip_rcv ip_input.c

Page 12: NETFILTER 分析

www.kernelchina.org

NF_IP_LOCAL_INHOOK FUNCTION FILE

NF_IP_LOCAL_IN ip_local_deliver ip_input.c

Page 13: NETFILTER 分析

www.kernelchina.org

NF_IP_FORWARDHOOK FUNCTION FILE

NF_IP_FORWARDip_forward ip_forward.c

ipmr_queue_xmit ipmr.c

Page 14: NETFILTER 分析

www.kernelchina.org

NF_IP_LOCAL_OUTHOOK FUNCTION FILE

NF_IP_LOCAL_OUT

 

ip_build_and_send_pkt

ip_output.c

ip_queue_xmit ip_output.cip_build_xmit_slow ip_output.c

ip_build_xmit ip_output.csend_reset ipt_REJECT.c

send_unreach ipt_REJECT.cigmpv3_sendpack igmp.cigmp_send_report igmp.c

Page 15: NETFILTER 分析

www.kernelchina.org

NF_IP_POST_ROUTINGHOOK FUNCTION FILE

NF_IP_POST_ROUTING

 

__ip_finish_output ip_output.cip_mc_output ip_output.cip_mc_output ip_output.c

Page 16: NETFILTER 分析

www.kernelchina.org

conntrack 的检查点NF_IP_PRE_ROUTING

NF_IP_LOCAL_IN NF_IP_LOCAL_OUT

NF_IP_FORWARD

NF_IP_POST_ROUTING

ROUTE

ROUTE

链路层

传输层

网络层

Page 17: NETFILTER 分析

www.kernelchina.org

ip_conntrack_in• if ((*pskb)->nfct)

return NF_ACCEPT;• *pskb = ip_ct_gather_frags(*pskb);• icmp_error_track(*pskb, &ctinfo,

hooknum)• if (!(ct = resolve_normal_ct(*pskb,

proto,&set_reply,hooknum,&ctinfo)))• ret = proto->packet(ct, (*pskb)-

>nh.iph, (*pskb)->len, ctinfo);• ret = ct->helper->help((*pskb)-

>nh.iph, (*pskb)->len, ct, ctinfo);

•每个包与一个状态结构关联,如果关联已存在,就不需要重复检查•在连接跟踪前要先把分片包组装成完整的包•如果是 icmp 协议的包,需要特殊处理•查找是否有与此包相关的状态结构,如果有,则根据包的信息进行状态转换,如果没有,则创建新的状态结构•不同协议对此协议包的特殊处理•此状态结构是否有相关的 helper ,如果有,就执行相应的 helper 函数

Page 18: NETFILTER 分析

www.kernelchina.org

ip_confirm• !is_confirmed((struct ip_conntrack

*)skb->nfct->master)• ct = __ip_conntrack_get(nfct, &ctinfo);• if (CTINFO2DIR(ctinfo) !=

IP_CT_DIR_ORIGINAL)return

NF_ACCEPT;• hash = hash_conntrack(&ct-

>tuplehash[IP_CT_DIR_ORIGINAL].tuple);repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);

• list_prepend(&ip_conntrack_hash[hash], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);

list_prepend(&ip_conntrack_hash[repl_hash], &ct->tuplehash[IP_CT_DIR_REPLY]);

• set_bit(IPS_CONFIRMED_BIT, &ct->status);

•如果是已确认过的包就不需要再次确认•从 skbuff 的信息中找到与之相关的状态结构•只有 ORIGINAL 方向的包可以创建状态结构, REPLY 方向的包只需匹配状态结构•计算 ORIGINAL 方向和 REPLY 方向的哈希值•如果此状态结构不在哈希表中,就把它加入哈希表•设置状态结构的已确认标记

Page 19: NETFILTER 分析

www.kernelchina.org

ip_conntrack 状态结构......

tuplehash[O]tuplehash[R]

ip_conntrack......

......

......

sk_buff

......

......

......

sk_buff

struct ip_conntrack_tuple{

src.ipsrc.u // 不同协议,这个值不同dst.ipdst.u // 不同协议,这个值不同dst. protonum

}

ORIGINAL 方向的包REPLY 方向的包

Page 20: NETFILTER 分析

www.kernelchina.org

ct_general............

......nfct......nf_ct_info

ip_conntracksk_buff

• 每个 sk_buff 都将与一个 ip_conntrack 关联,所以从 sk_buff 中可以得到与之关联的 ip_conntrack• 每个 sk_buff 都将与 ip_conntrack 的一个状态关联,所以从 sk_buff可以得到相应 ip_conntrack 的状态

ip_conntrack 与 sk_buff 的关系

Page 21: NETFILTER 分析

www.kernelchina.org

......tuplehash[O]tuplehash[R]

bysource......

byipsproto

ip_conntrack_hash

bysource (for nat)

byipsproto (for nat)

ip_conntrack

ip_conntrack 与全局表的关系ip_conntrack 与全局表的关系

Page 22: NETFILTER 分析

www.kernelchina.org

ip_conntrack 状态转换 [1]IP_CT_NEW IP_CT_RELATED

IP_CT_ESTABLISHED + IP_CT_IS_REPLY

IP_CT_ESTABLISHED

ORIGINAL

REPLY

ORIGINAL

0 4321nf_ct_info

Page 23: NETFILTER 分析

www.kernelchina.org

ip_conntrack 状态转换 [2]任意有效状态

IP_CT_RELATED + IP_CT_IS_REPLY

0 4321nf_ct_info

IP_CT_RELATED

ORIGINAL icmp error

REPLY icmp error

Page 24: NETFILTER 分析

www.kernelchina.org

ip_conntrack 与 tcp 协议struct ip_conntrack_protocol_tcp{

tcp_pkt_to_tuple // 从 tcp 包中得到 tupletcp_invert_tuple // 从 tcp 包中得到反向的 tupletcp_packet //tcp 协议私有状态处理tcp_new // 创建 tcp 协议的状态结构时调用tcp_exp_matches_pkt // 这个包是否符合 expect 的要求......

}struct ip_ct_tcp 状态结构中与 tcp 协议相关的私有状态

Page 25: NETFILTER 分析

www.kernelchina.org

ip_conntrack 与 udp 协议struct ip_conntrack_protocol_udp{

udp_pkt_to_tuple // 从 udp 包中得到 tupleudp_invert_tuple // 从 udp 包中得到反向的 tupleudp_packet //udp 协议对状态结构的特殊处理udp_new // 创建 udp 协议的状态结构时调用.......

}

Page 26: NETFILTER 分析

www.kernelchina.org

ip_conntrack 与 icmp 协议struct ip_conntrack_protocol_icmp{

icmp_pkt_to_tuple // 从 icmp 包中得到 tupleicmp_invert_tuple // 从 icmp 包中得到反向的 tupleicmp_packet //icmp 协议对状态结构的特殊处理icmp_new // 创建 icmp 协议的状态结构时调用......

}struct ip_ct_icmp 状态结构中,与 icmp 协议相关的私有信息

Page 27: NETFILTER 分析

www.kernelchina.org

nat 的检查点NF_IP_PRE_ROUTING

NF_IP_LOCAL_IN NF_IP_LOCAL_OUT

NF_IP_FORWARD

NF_IP_POST_ROUTING

ROUTE

ROUTE

链路层

传输层

网络层

Page 28: NETFILTER 分析

www.kernelchina.org

num_manips

nat 与 ip_conntrack

......initialized

bysource......

byipsproto

bysource

byipsproto

ip_conntrack:ip_nat_info

struct ip_nat_info_manipdirection 包的方向hooknum 检查点编号maniptype 转换类型manip 替换地址和端口 ( 或 id)

Page 29: NETFILTER 分析

www.kernelchina.org

ip_nat_fn• ct = ip_conntrack_get(*pskb, &ctinfo);• ret = call_expect(master_ct(ct), pskb,

hooknum, ct, info);

• ret = ip_nat_rule_find(pskb, hooknum, in, out, ct, info);

• do_bindings(ct, ctinfo, info, hooknum, pskb);

•首先找到与包关联的状态结构•如果这个状态结构是从 expect 创建出来的,就调用它的父连接的 nat helper的 expect 函数来创建本连接的地址转换结构•如果状态结构的状态是IP_CT_RELATED 、 IP_CT_RELATED+IP_CT_IS_REPLY 、 IP_CT_NEW ,就查找地址转换规则来创建本连接的地址转换结构•根据状态结构中的地址转换结构对包进行地址和端口的修改

Page 30: NETFILTER 分析

www.kernelchina.org

ip_nat_setup_info• get_unique_tuple• ip_conntrack_alter_reply• ip_ct_tuple_src_equal• ip_ct_tuple_dst_equal• place_in_hashes

•找到一个唯一的 ip 地址和端口,生成一个新的 tuple•修改 ip_conntrack 中 REPLY 方向的tuple•如果是源转换,生成 ORIGINAL 方向和REPLY 方向的地址转换结构•如果是目的转换,生成 ORIGINAL 方向和 REPLY 方向的地址转换结构•把 ip_conntrack 放入 nat 的哈希表

Page 31: NETFILTER 分析

www.kernelchina.org

do_bindings• manip_pkt((*pskb)->nh.iph->protocol,

(*pskb)->nh.iph, (*pskb)->len,&info->manips[i].manip, info->manips[i].maniptype,

&(*pskb)->nfcache);• ret = helper->help(ct, exp, info,

ctinfo, hooknum, pskb);

•根据 ip_conntrack 中的地址转换结构修改包的地址和端口,并重新计算校验和•如果这个 ip_conntrack 有 nat helper ,则调用它的 help 函数

Page 32: NETFILTER 分析

www.kernelchina.org

nat 与 tcp 协议struct ip_nat_protocol_tcp{

tcp_manip_pkt // 修改包的 tcp 端口tcp_in_range // 包的 tcp 端口是否在指定的范围之内tcp_unique_tuple // 找到一个唯一的 tuple.......

}

Page 33: NETFILTER 分析

www.kernelchina.org

nat 与 udp 协议struct ip_nat_protocol_udp{

udp_manip_pkt // 修改 udp 包的端口udp_in_range //udp 包的端口是否在指定的范围之内udp_unique_tuple // 找到一个唯一的 tuple.......

}

Page 34: NETFILTER 分析

www.kernelchina.org

nat 与 icmp 协议struct ip_nat_protocol_icmp{

icmp_manip_pkt // 修改 icmp 包的 idicmp_in_range //icmp 的 id 是否在指定的范围之内icmp_unique_tuple // 找到一个唯一的 tuple.......

}

Page 35: NETFILTER 分析

www.kernelchina.org

......helperhelp

nat.info.helpernat.help

......

ip_conntrack_helper

ip_nat_helper

conntrack 中与 ALG 相关的参数nat 中与 ALG 相关的参数

ip_conntrack

ip_conntrack 与 ALG 的关系

Page 36: NETFILTER 分析

www.kernelchina.org

ip_conntrack->helper->help

ip_conntrack.nat->helper->help

ip_conntrack->helper->help

ip_conntrack.nat->helper->expect

ip_conntrack_expect->expectfn

ip_conntrack.nat->helper->help控制连接流程

数据连接流程

ALG 调用流程

Page 37: NETFILTER 分析

www.kernelchina.org

......master

.......sibling_list

listexpected_list

expectantsibling

......

......

sibling_listmaster

.......

......

ip_conntrack_expect_list

parent ip_conntrack

child ip_conntrack

parent ip_conntrack的所有子连接都可以通过 sibling_list 找到

ip_conntrack_expect

如果找到与 ip_conntrack关联的 ip_conntrack_expect ,就把它从全局链表中删掉

ip_conntrack 与 expect 的关系

Page 38: NETFILTER 分析

www.kernelchina.org

iptables 一个包选择、监控、过滤系统 table,chain,rule 系统预定义了三个 table :

filter,nat,mangle 用户空间的数据结构和内核空间的数据结构不同 一个可扩展的架构

Page 39: NETFILTER 分析

www.kernelchina.org

ipt_table

struct ipt_table{

struct list_head list;char name[IPT_TABLE_MAXNAMELEN];struct ipt_replace *table; // 表初始化时的数据unsigned int valid_hooks; // 表监听的检查点rwlock_t lock;struct ipt_table_info *private; // 表的数据最后存储在这里struct module *me;

};

Page 40: NETFILTER 分析

www.kernelchina.org

ipt_entrytarget_offsetnext_offset

matchs

targettarget_offsetnext_offset

matchs

target

hook_entry[]underflow[]

ipt_table_info

ipt_entry

Page 41: NETFILTER 分析

www.kernelchina.org

规则匹配策略 不能从一个预定义的 chain跳转到另一个预定义

的 chain ,只能从预定义的 chain跳转用户定义的 chain ,或者用户定义的 chain 之间相互跳转

不同检查点上的 chain 不能相互跳转 预定义的 chain 有默认的包处理方式,如果

chain 上的规则都没有匹配,就使用默认的处理方式 如果用户定义的 chain 上的规则都没有匹配,则返回指向这个 chain 的规则所在的 chain 的下一条规则

Page 42: NETFILTER 分析

www.kernelchina.org

filter 表NF_IP_PRE_ROUTING

NF_IP_LOCAL_IN NF_IP_LOCAL_OUT

NF_IP_FORWARD

NF_IP_POST_ROUTING

ROUTE

ROUTE

链路层

传输层

网络层

Page 43: NETFILTER 分析

www.kernelchina.org

nat 表NF_IP_PRE_ROUTING

NF_IP_LOCAL_IN NF_IP_LOCAL_OUT

NF_IP_FORWARD

NF_IP_POST_ROUTING

ROUTE

ROUTE

链路层

传输层

网络层

Page 44: NETFILTER 分析

www.kernelchina.org

mangle 表NF_IP_PRE_ROUTING

NF_IP_LOCAL_IN NF_IP_LOCAL_OUT

NF_IP_FORWARD

NF_IP_POST_ROUTING

ROUTE

ROUTE

链路层

传输层

网络层

Page 45: NETFILTER 分析

www.kernelchina.org

hook 的顺序NF_IP_POST_ROUTINGNF_IP_PRE_ROUTING

NF_IP_FORWARDNF_IP_LOCAL_OUT

conntrack[-200]

nat[dnat][-100]mangle[-150]

conntrack[max]nat[snat][100]mangle[-150]

NF_IP_LOCAL_IN

filter[0]

conntrack[max-1]

mangle[-150]mangle[-150]

filter[0]

filter[0]nat[dnat][-100]mangle[-150]

conntrack[-200]

nat[100]

Page 46: NETFILTER 分析

www.kernelchina.org

ipt_match

struct ipt_match{

......match // 匹配 skbuffcheckentry // 检查参数是否合法destroy //模块释放时调用

};

Page 47: NETFILTER 分析

www.kernelchina.org

ipt_entry_match

ipt_ip

ipt_entry_matchipt_entry_target

iptables_match

ipt_match

用户空间内核空间

Page 48: NETFILTER 分析

www.kernelchina.org

ipt_target

struct ipt_target{

......target // 对包做出修改或判断checkentry // 检查参数是否合法destroy //模块释放时调用

};

Page 49: NETFILTER 分析

www.kernelchina.org

ipt_entry_target

ipt_ip

ipt_entry_matchipt_entry_target

iptables_target

ipt_target

用户空间内核空间

Page 50: NETFILTER 分析

www.kernelchina.org

增加一个 table 在内核中增加一个表,注意表所监听的检查点 这个表可以使用哪些match 和

target ,这个表的用途是什么

Page 51: NETFILTER 分析

www.kernelchina.org

增加一个 match 在 iptables 中增加一个 extension ,也就是增加一个 iptables_match 增加一个内核模块,这个内核模块注册一个 ipt_match 注意用户空间向内核空间传递数据的大小

Page 52: NETFILTER 分析

www.kernelchina.org

增加一个 target 在 iptables 中增加一个 extension ,也就是增加一个 iptables_target 增加一个内核模块,这个内核模块注册一个 ipt_target 注意用户空间向内核空间传递数据的大小

Page 53: NETFILTER 分析

www.kernelchina.org

programming nf_hook_ops 注意网络包的流程,不要与其他功能冲突 检查点 优先级 返回值

Page 54: NETFILTER 分析

www.kernelchina.org

programming nf_sockopt_ops pf :协议簇的编号 get_optmin , get_optmax :

getsockopt 的 optname参数的范围,不能与其他模块冲突 set_optmin , set_optmax :

setsockopt 的 optname参数的范围,不能与其他模块冲突

Page 55: NETFILTER 分析

www.kernelchina.org

programming nf_queue_handler_t queue_handler[NPROTO] ,每个协议簇只能注册一个 queue_handler 内核空间与用户空间通过 netlink

socket收发包 用户空间注入的包被重新发送到缓存它的检查点上继续完成后续的检查 从用户空间重新注入内核空间,需要调

用 nf_reinject

Page 56: NETFILTER 分析

www.kernelchina.org

注意事项 在自己的钩子函数中,如果修改了包,需要执行 (*pskb)->nfcache |= NFC_ALTERED ,表示这个包已经被修改,如果不能确定,则

用 NFC_UNKNOWN