linux内核网络实现的一些问题

晨曦之光 发布于 2012/04/10 14:59
阅读 67
收藏 0

1.“也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就是我们为什么不应该在这个表中做任何过滤的主要原因”这段话说明不能在nat规则中作过滤,因为linux的链接跟踪机制,只有每个流的第一个包才会经过nat表,并将匹配的规则设置到连接跟踪的数据结构中,接下来的包都是直接取连接跟踪相关数据结构的结果,而不再经过nat表,如果在nat中做了过滤,那么只有第一个包会匹配规则,而后面的则无法匹配,也许你会问,第一个包过不去后面的能过吗?事实上,仅举最简单的两个例子,第一,udp包,第二,tcp包的第一个包过去后再设置nat的过滤规则。
2.dnat为何要在output链中有个钩子。dnat路由器将世界所有的主机分为三类,第一类是自己一个网卡口一侧的主机,第二类是自己所有其它网卡口一侧的主机,第三类是它自己。所有非自己的请求都会经过pre-routing链,然后被forward,而dnat则是在pre-routing上做的,但是对于自己发出的请求,则无法经过pre-routing链,而是经过output链,因此需要在output链上做dnat。
3.reject target这是一个咋看上去很不错的target,因为它避免了请求在发出后在该连接被中间路由器drop的时候源端在超时时间内的忙等,但是其只有有限的几种通告类型,简单说就是tcp-reset和icmp。看看会有什么问题,tcp-reset无法用于udp,而icmp可能会在通告给源主机的路上被丢弃。
4.queue target是一个很有趣的target,它可以在用户空间决定如何处置这个数据包。
5.MASQUERADE target在内核中会按照一定的策略选择源ip地址,这确实是“一定的策略”,并且内核的实现很不同,因此需要注意。
6.windows的死网关检测机制是一种坡脚的机制,第一,该机制的算法非常傻,第二,如果用户自己不设置,系统为何要帮用户设置呢?很多时候,你会发现,在windows上配置了一条静态路由,然而当该静态路由的下一跳不可达的时候,用route print查看,发现该路由被莫名奇妙的改变了,下一跳被改变了...
7.unix上直接提供了pf_packet,它不但能抓包,还能让你彻底绕开tcp/ip协议栈,包括路由,netfilter等,直接将数据发送到网卡,任何数据都行,设置你可以自己定义协议。
8.为何桥接过滤要走ip层的钩子呢?这是因为linux主机往往同时配置成网桥和路由器,linux网桥可以基于三层信息进行二层过滤。
9.linux 2.6.10以前的内核的nat模块有个问题,首先在ip_nat_fn这个终极钩子函数中会失效校验码,这是没有必要的,因为很多包根本就不进行nat,只是走一下过场罢了,因此最好的办法是仅仅对真正需要nat的家伙们进行失效校验和的操作。不管怎样,虽然这是一个缺陷,然而更大的弊端在于其做的不干净,在失效校验码的函数中如果当前skb的使用者不止一个,那么会复制一个skb副本出来,然后传输该副本,但是在复制的时候并没有复制tso的信息,这样在经过了netfilter接下来的是否分段的判断中就会误判,skb_shinfo(skb)->tso_size为0:
if ((skb->len > dst_pmtu(skb->dst) || skb_shinfo(skb)->frag_list) && !skb_shinfo(skb)->tso_size)
    return ip_fragment(skb, ip_finish_output);
因此即使网卡有tso的能力也会分段,特别是在应用设置了mtu发现并且skb的长度超过mtu的时候还会发送icmp出错报告,这就大大延迟了应用的响应时间。还好,2.6.10之后这个问题被修正了,在2.6.1x(x>8)之后,不需要nat的家伙们不再失效校验码...。唉...独立发现了问题,却迟了一步解决问题,自己的能力还满意,不过速度不够快!


原文链接:http://blog.csdn.net/dog250/article/details/5913001
加载中
返回顶部
顶部