注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BCB-DG's Blog

...

 
 
 

日志

 
 

Linux Netfilter 分析六  

2013-10-04 15:28:03|  分类: Linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
//轉
3. nat表的实现

        nat表的初始化和实现与filter极为相似。

    在初始化上,其初始化位于net/ipv4/netfilter/ip_nat_rule.c,Line104,初始化所用模板则位于net/ipv4/netfilter/ip_nat_rule.c,Line50。

    在实现上,其实现函数就是NAT模块的初始化函数init_or_cleanup()(位于net/ipv4/netfilter /ip_nat_standalone.c,Line278)。其工作主要是依次调用ip_nat_rule_init()、ip_nat_init() 以及nf_register_hook()。

首先ip_nat_rule_init()(位于net/ipv4/netfilter/ip_nat_rule.c,Line278)调用 ipt_register_table()来初始化并注册nat表,然后利用ipt_register_target()来初始化并注册SNAT和 DNAT,在这个注册过程中,关键的函数是ip_nat_setup_info(位于net/ipv4/netfilter /ip_nat_core.c,Line511),其工作是:

首先调用invert_tupler()(net/ipv4/netfilter/ip_conntrack_core.c,Line879),将记录反转

然后调用get_unique_tuple()(net/ipv4/netfilter/ip_nat_core.c,Line393,在指定的地址范围(ip_nat_multi_range结构)中查找空闲的地址),如果没有空闲地址可用则会返回NF_DROP

判断源和目的是否改变,如果改变,则更新ip_nat_info。

然后ip_nat_init()(位于net/ipv4/netfilter/ip_nat_core.c,Line953)会给nat所用的两个hash表(bysource、byipsproto)分配空间并初始化各种协议

最后会通过nf_register_hook()注册相应HOOK的函数ip_nat_fn()、ip_nat_local_fn()和ip_nat_out(),并增加连接跟踪的计数器。

    在具体的HOOK函数实现上,后两者其实都是基于ip_nat_fn()的,而这其中最重要的处理函数,也就是实际的网络地址转换函数是do_bindings(),下面将对其进行分析:

        do_bindings()位于net/ipv4/netfilter/ip_nat_core.c,Line747,其主要工作是将ip_nat_info中的地址绑定应用于数据报:

它首先在ip_nat_info->manip数组中查找能够匹配的绑定

然后调用manip_pkt()函数(位于net/ipv4/netfilter/ip_nat_core.c,Line701)进行相应的地址转换:

manip_pkt()这个函数会根据不同的方向进行转换,并且对校验和进行处理

同时,它是递归调用自己以处理不同协议的情况

最后调用helper模块进行执行(当然,如果有的话),特别是避免在同一个数据报上执行多次同一个helper模块

 

        nat表与filter表还有一个较大的不同:在一个连接中,只有第一个数据报才会经过nat表,而其转换的结果会作用于此连接中的其它所有数据报。
4. 协议的扩展

    要想扩展NAT的协议,那么必须写入两个模块,一个用于连接跟踪,一个用于NAT实现。

    与连接跟踪类似,nat中协议也由一个列表protos存放,位于include/linux/netfilter_ipv4 /ip_nat_core.h,Line17。协议的注册和注销分别是由函数ip_nat_protocol_register()和 ip_nat_protocol_unregister()实现的,位于net/ipv4/netfilter /ip_nat_standalone.c,Line242。

        nat的协议是由结构ip_nat_protocol描述的,其定义位于include/linux/netfilter_ipv4/ip_nat_protocol.h,Line10:

struct ip_nat_protocol

{

struct list_head list;

const char *name;

unsigned int protonum;

void (*manip_pkt)(struct iphdr *iph, size_t len,

const struct ip_conntrack_manip *manip,

enum ip_nat_manip_type maniptype);

int (*in_range)(const struct ip_conntrack_tuple *tuple,

enum ip_nat_manip_type maniptype,

const union ip_conntrack_manip_proto *min,

const union ip_conntrack_manip_proto *max);

int (*unique_tuple)(struct ip_conntrack_tuple *tuple,

const struct ip_nat_range *range,

enum ip_nat_manip_type maniptype,

const struct ip_conntrack *conntrack);

unsigned int (*print)(char *buffer,

const struct ip_conntrack_tuple *match,

const struct ip_conntrack_tuple *mask);

unsigned int (*print_range)(char *buffer,

const struct ip_nat_range *range);

};

    其中重要成员:

`void (*manip_pkt)(……)`:其指向的函数会根据ip_nat_info->manip参数进行数据报的转换,即do_bindings()中调用的manip_pkt()函数

`int (*in_range)(……)`:其指向的函数检查多元组的协议部分值是否在指定的区间之内

`int (*unique_tuple)(……)`:其指向函数的作用是根据manip的类型修改多元组中的协议部分,以获得一个唯一的地址,多元组的协议部分被初始化为ORIGINAL方向
八、数据报修改模块──mangle表
1. 概述

        mangle这个词的原意是撕裂、破坏,这里所谓“packet mangling”是指对packet的一些传输特性进行修改。mangle表被用来真正地对数据报进行修改,它可以在所有的5个HOOK上进行操作。

    从源码看来,在mangle表中所允许修改的传输特性目前有:

TOS(服务类型):修改IP数据报头的TOS字段值

TTL(生存时间):修改IP数据报头的TTL字段值

MARK:修改skb的nfmark域设置的nfmark字段值。

nfmark是数据报的元数据之一,是一个用户定义的数据报的标记,可以是unsigned long范围内的任何值。该标记值用于基于策略的路由,通知ipqmpd(运行在用户空间的队列分拣器守护进程)将该数据报排队给哪个进程等信息。

TCP MSS(最大数据段长度):修改TCP数据报头的MSS字段值
2. mangle表的实现

    遍历整个源码,没有发现mangle表的独有数据结构。

        mangle表的初始化和实现与filter极为相似。在初始化上,其初始化位于net/ipv4/netfilter /iptable_mangle.c,Line117,初始化所用模板则位于net/ipv4/netfilter /iptable_mangle.c,Line43。

    在实现上,其实现函数就是mangle模块的初始化函数init()(位于net/ipv4/netfilter /iptable_mangle.c,Line183)。其工作就是依次注册packet_mangler表以及5个HOOK。其中 NF_IP_LOCAL_OUT的处理函数为ipt_local_hook(),其余均为ipt_route_hook(),分别位于net/ipv4 /netfilter/iptable_mangle.c,Line132 & 122,二者的关键实现都是通过调用ipt_do_table()实现的。
3. 数据报的修改

    对数据报不同位的修改都是通过单独的模块实现的,也就是说由ipt_tos.o、ipt_ttl.o、ipt_mark.o、ipt_tcpmss.o实现上面所说的四种传输特性的修改。

    以TOS为例,其涉及的文件为net/ipv4/netfilter/ipt_tos.c以及include/linux/netfilter_ipv4/ipt_tos.h。

    其专有数据结构为ipt_tos_info,定义于ipt_tos.h中:

struct ipt_tos_info {

u_int8_t tos;

u_int8_t invert;

};

    其模块的添加/卸载函数很简单,其实就是添加/删除TOS的MATCH:tos_match(定义并初始化于ipt_tos.c,Line37):

static struct ipt_match tos_match

= { { NULL, NULL }, "tos", &match, &checkentry, NULL, THIS_MODULE };

    而在tos_match的处理函数match()中,已经完成了对相应位的赋值,这似乎是违反match仅仅匹配而不修改的一个特例。
九、其它高级功能模块

        Netfilter中还有一些其它的高级功能模块,基本是为了用户操作方便的,没有对它们进行分析,如:

REJECT,丢弃包并通知包的发送者,同时返回给发送者一个可配置的ICMP错误信息,由ipt_REJECT.o完成

MIRROR,互换源和目的地址以后并重新发送,由ipt_MIRROR.o完成

LOG, 将匹配的数据报传递给系统的syslog()进行记录,由ipt_LOG.o完成

ULOG,Userspace logging,将数据报排队转发到用户空间中,将匹配的数据适用用户空间的log进程进行记录,由ip_ULOG.o完成。这是Netfilter的一个关键技术,可以使用户进程可以进行复杂的数据报操作,从而减轻内核空间中的复杂度

Queuing,这是上面ULOG技术的基础,由ip_queue.o完成,提供可靠的异步包处理以及性能两号的libipq库来进行用户空间数据报操作的开发。

  评论这张
 
阅读(631)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017