Chinaunix首页 | 论坛 | 博客

分类: LINUX

2014-02-13 19:58:34

    最近定位了内核中某模块与带宽管理联动的问题。最终发现是模块和CONNMARK target联动时出现了问题,导致带宽管理没有效果。于是本文就结合内核的代码和网上的一些文章来系统的分析一下iptables以及对应内核Netfilter(文中简称NF)框架中CONNMARK的用法和实现。
    本篇先分析iptables命令中如何使用CONNMARK以及相关参数的介绍。在网上搜到一篇介绍Netfilter Connmark的英文文章,连接为:。本文就借鉴这篇文章来讲述iptables中CONNMARK的使用,一来翻译这篇文章,二来也会适当加上个人的一些理解。
  
    本文欢迎自由转载,但请标明出处和本文链接,并保持本文的完整性
   CU
Godbach
   Blog
http://blog.chinaunix.net/u/33048/index.html
   Oct 30, 2009

1.简介

CONNMARK是NF框架中一个很有用的特性。它实现了往链接跟踪记录上打标记的方法。一旦某个链接被打上一个标记,则该标记同样会应用到该链接的RELATED连接上。因此,如果你给FTP的链接打上了标记,则该标记同样会被记录在FTP的数据连接ftp-data上。

所有Linux下的工具(比如Qos或路由)只能够在数据包上打标记。因此,更有用的是,CONNMARK能够将链接跟踪上的标记记录在数据包上,反之亦然。因此,CONNMARK可以用在Qos或路由上已建链接的管理。

更多关于CONNMARK的信息可以在NF的网站上找到。2.6.12以上版本的内核都支持该模块。

2.示例

一个简单的例子

以下是iptables命令行配置的规则:

iptables -A POSTROUTING -t mangle -j CONNMARK --restore-mark
iptables -A POSTROUTING -t mangle -m mark ! --mark 0 -j ACCEPT
iptables -A POSTROUTING -p tcp --dport 21 -t mangle -j MARK --set-mark 1
iptables -A POSTROUTING -p tcp --dport 80 -t mangle -j MARK --set-mark 2
iptables -A POSTROUTING -t mangle -j CONNMARK --save-mark

这几条规则的处理流程如下:

  1. 重新保存CONNMARK上的标记。实际上,该条规则只是只是简单的将链接跟踪上记录的CONNMARK值赋给数据包上的MARK。 TC是从数据包的MARK读取标记。
  2. 如果数据包上已经有了MARK,则直接接受该数据包,不需要匹配下面的规则了。
  3. 我们给协议为TCP并且目的端口为21的数据包打上标记,标记值为1.
  4. 我们给协议为TCP并且目的端口为80的数据包打上标记,标记值为2.
  5. 我们将数据包上记录的标记值保存到该数据包对应的链接跟踪上,以后属于该链接的所有数据包都会使用该标记值。随后属于该链接的数据包会经过第1条规则时,规则会将链接上记录的标记值重新保存到数据报上,这就是–-restore-mark的功能。

一个完整的例子

如果你想实现的更加具体(或者使用复杂的过滤器,--原文:imbricated filters),你可以将规则按照精确的程度进行排序:

iptables -A POSTROUTING -t mangle -j CONNMARK --restore-mark
iptables -A POSTROUTING -t mangle -m mark ! --mark 0 -j ACCEPT
iptables -A POSTROUTING -m mark --mark 0 -p tcp --dport 21 -t mangle -j MARK --set-mark 1
iptables -A POSTROUTING -m mark --mark 0 -p tcp --dport 80 -t mangle -j MARK --set-mark 2
iptables -A POSTROUTING -m mark --mark 0 -t mangle -p tcp -j MARK --set-mark 3
iptables -A POSTROUTING -t mangle -j CONNMARK --save-mark

我们使用-m mark –mark 0来避免一个带标记的数据包被重复打标记。作者这样解释个人认为应该是单独就这一条规则来说的。

第二条规则是可选的,但是它可以保证所有和一条已建链接相关的数据包都只被检测一次,避免被后数据包还要经过后面的几条规则。

3.相关提示

Connmark处理入口的数据包

如果你使用的是一条进入系统的规则,你在PREROUTING点的规则链上通过CONNMARK重新保存数据包的mark值。因此可以这样配置规则:

iptables -A PREROUTING -t mangle -j CONNMARK --restore-mark

修改过的ip_conntrack文件

加载了CONNMARK模块之后,文件/proc/net/ip_conntrack显示的每一条记录上都包含了链接的标记,即mark字段

tcp 6 432000 ESTABLISHED src=62.212.98.117 dst=XXX.XXX.XXX.XXX sport=35027 dport=22 src=217.15.82.6 dst=62.212.98.117 sport=22 dport=35027 [ASSURED] use=1 mark=0

udp 17 24 src=127.0.0.1 dst=127.0.0.1 sport=1024 dport=53 [UNREPLIED] 
src=127.0.0.1 dst=127.0.0.1 sport=53 dport=1024 use=1 mark=0

使用ip_conntrack计数

可以很容易的通过以下规则替代规则iptables -A POSTROUTING -t mangle -m mark ! –mark 0 -j ACCEPT:

iptables -A POSTROUTING -t mangle -m mark  --mark 1 -j ACCEPT
iptables -A POSTROUTING -t mangle -m mark --mark 2 -j ACCEPT
...

使用上面的规则配置之后,就可以通过命令iptables -L POSTROUTING -t mangle -v给出每条规则的详细计数。同上所述,它也会统计RELATED链接的计数。

不过仍然有一个问题,因为我们前面没有特意去关注一个链接的第一个数据包。因此,有必要增加加关于设置--set-mark和ACCEPT规则的计数。

以上简单的介绍了CONNMARK,其实还包括MARK和mark模块的用法和功能。下一篇文章我们将从内核的源码分析这三个模块的实现。


阅读(635) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~