测试环境为Red Hat 9.0,内核为2.4.20-8。由于2.4.*是一个稳定的内核,因此不能把当前开发的一些新功能提交到主内核中去,而只能首先在patch-o-matic中测试,然后打补丁到内核中。在CVS中可以找到最新的patch-o-matic包—Patch-o-matic-20040609.tar.bz2。

  有了内核支持后,还需要iptables支持,其中iptables-p2p-0.3.0a.tar.gz为netfilter/iptables组织开发的专门支持P2P的iptables扩展软件包;ipp2p-0.5c.tar.gz为Eicke Friedrich开发的一个支持P2P的iptables扩展包。这两个扩展包各有特色,后面将会分别介绍。

  装载模块

  首先在/usr/src下解压软件包:

  #bzip2 -d patch-o-matic-20040609.tar.bz2  

  生成patch-o-matic-20040609.tar.out。

  #tar xvf patch-o-matic-20040609.tar.out  

  生成补丁目录patch-o-matic-20040609。Red Hat 9.0中默认的内核目录为/usr/src/linux-2.4。进入补丁目录/usr/src/patch-o-matic-20040609,由于支持P2P协议控制选项需要CONNMARK模块,该模块在extra子目录下,因此需要运行如下命令来升级内核补丁。

  #KERNEL_DIR=/usr/src/linux-2.4 ./runme extra  

  运行该命令后会出现一个模块选择界面,界面有两个区域,一个给出相关的模块名、模块功能、用法和语法实例;另一个给出各种选项,如N/y/b/r.../q/?,其中第一个为大写字母,表示缺省选项,n表示下一个模块,y表示确定,b表示上一个模块,q表示退出。

  首先应该确定当前的模块是否需要,不需要就按“N”键后回车,继续显示下一个模块的相关信息。当出现需要的模块时,按“Y”键确认,同时应该将里面的相关语法实例抄录下来以备用。选择完所有需要的模块后,按“Q”键退出。

#p#

  编译内核

  进入内核文件所在目录/usr/src/linux-2.4,开始编译内核:

  #make mrproper  
 
  #make xconfig(或#make menuconfig)  

  注意,在配置选项中必须选择Networking options→IP:Netfilter Configuration→Connection mark tracking support和CONNMARK target support两个选项。确保关键文件在正确位置:

  #make dep 

  编译大内核:

  #make bzImage  

  编译选择的模块:

  #make modules  

  将编译后的模块转移到系统标准位置:

  #make modules_install  

  让系统自动修改启动配置文件grub.conf:

  #make install  

  重新启动系统,选择Red Hat Linux(2.4.20-8custom)选项,则启动了新编译的内核。

  升级iptables

  安装iptables-1.2.8

  首先解压iptables-1.2.8.tar.bz2文件:

  #bzip2 -d iptables-1.2.8.tar.bz2  
 
  #tar xvf iptables-1.2.8.tar.out  

  编译iptables-1.2.8:

  #make KERNEL_DIR=/usr/src/linux-2.4  
 
  #make install KERNEL_DIR=/usr/src/linux-2.4  
 
  #make install-devel  

  拷贝可执行文件到相应目录:

  #cp iptables iptables-save iptables-restore /sbin  

  安装iptables-p2p软件

  首先解压iptables-p2p-0.3.0a.tar.gz:

  #tar zxvf iptables-p2p-0.3.0a.tar.gz  
 
  #cd iptables-p2p-0.3.0a  

  拷贝iptables-1.2.8的头文件到适当的目录:

  #cp -a /usr/src/iptables-1.2.8/include/* /usr/include  

  运行“make”编译iptables-p2p,并拷贝相关文件到相应的目录:

  #make  
 
  #cp kernel/ipt_p2p.o /lib/modules/2.4.20-8custom/kernel/net/ipv4/netfilter/  
 
  #cp iptables/libipt_p2p.so /lib/iptables/  

  安装ipp2p软件

  首先修改Makefile文件中的源目录、内核目录和netfilter版本号,将以下内容:

  IKERNEL = -I/usr/src/linux/include  
 
  IUSER = -I/usr/src/iptables-1.2.7a/include  
 
  NETFILTER_VERSION = \"1.2.7a\" 

  改为:

  IKERNEL = -I/usr/src/linux-2.4/include  
 
  IUSER = -I/usr/src/iptables-1.2.8/include  
 
  NETFILTER_VERSION = \"1.2.8\"  

  编译软件,并拷贝库文件到相应的目录:

  #make  
 
  #cp libipt_ipp2p.so /lib/iptables 

  装入模块:

  #insmod ipt_ipp2p  

 

#p#

  应用和检测P2P限制功能

  iptables-p2p的应用

  1.iptables-p2p目前支持如下协议:

  ◆ FastTrack(KaZaa、Grokster......)

  ◆ eDonkey(eDonkey、eMule......)

  ◆ Direct Connect

  ◆ Gnutella(regular clients and Shareaza's gnutella 2)

  ◆ BitTorrent

  ◆ OpenFT(giFT)

  需要安装CONNMARK模块,通过CONNMARK模块的标记包来使用iptables-p2p。

  2.通过-help参数获取帮助:

  #iptables -m p2p -help

  ……

  P2P match v0.3.0a options:

  --p2p-protocol [!] protocol[,...]

  --p2p ...

  match application-layer protocol(匹配的应用层协议)

  Valid p2p protocols:(P2P支持的有效协议如下:)

  fasttrack

  gnutella

  edonkey

  dc

  bittorrent

  openft

  iptables-p2p模块通过-m p2p参数来实现对所有已知P2P连接请求的识别。注意,-m p2p只能识别P2P类型的连接请求,不能识别所有的P2P包,可以通过--p2p-protocol子参数来识别P2P的各种已知协议类型。

  3.应用实例

  #iptables -A FORWARD -m p2p -j DROP

  阻塞网络上所有的P2P连接请求。

  #iptables -A FORWARD -m p2p --p2p-protocol fasttrack,bittorrent -j DROP

  阻塞网络上fasttrack和bittorrent协议连接请求。

  在实际使用过程中必须和CONNMARK目标结合起来,然后通过tc过滤才能真正对所有P2P包进行限制。更多的信息可以参考example/limit-p2p.sh的实例脚本。

#p#

  ipp2p的应用

  1.ipp2p目前支持如下Linux内核和iptables版本:

  ◆ Linux-Kernels 2.6:2.6.3

  ◆ Linux-Kernels 2.4:2.4.18、2.4.19、2.4.20、2.4.21、2.4.22、2.4.23

  ◆ iptables(www.netfilter.org)1.2.7a、1.2.8、1.2.9

  2.获取ipp2p帮助

  # iptables -m ipp2p --help

  ……

  IPP2P v0.5c options:

  --ipp2p Grab all known p2p packets

  (抓所有已知的P2P包)

  --ipp2p-data Grab all known p2p data packets

  (抓所有已知P2P数据包)

  --edk Grab all known eDonkey/eMule/Overnet packets

  (抓所有已知的eDonkey/eMule/Overnet类型的包)

  --edk-data Grab all eDonkey/eMule/Overnet data packets

  (抓所有已知的eDonkey/eMule/Overnet数据包)

  --dc Grab all known Direct Connect packets

  (抓所有已知的直接连接包)

  --dc-data Grab all Direct Connect data packets

  (抓所有已知的直接连接数据包)

  --kazaa Grab all KaZaA packets

  (抓所有KaZaA包)

  --kazaa-data Grab all KaZaA data packets

  (抓所有KaZaA数据包)

  --gnu Grab all Gnutella packets

  (抓所有Gnutella包)

  --gnu-data Grab all Gnutella data packets

  (抓所有Gnutella数据包)

  --bit Grab all BitTorrent packets (beta - handle with care)

  (抓所有BitTorrent包)

  --apple Grab all AppleJuice packets (beta - handle with care)

  (抓所有AppleJuice包)

  --soul SoulSeek (beta - handle with care)

  (SoulSeek类型的包)

  ……

  3.应用实例

  ipp2p只能识别P2P连接请求,而不能识别所有P2P包,因此也必须和CONNMARK目标结合在一起使用,目前只支持TCP协议标示。下面来看一个实例。

  #iptables -A PREROUTING -t mangle -p tcp -j CONNMARK --restore-mark

  上面代码表明从CONNMARK目标中恢复标记。

  #iptables -A PREROUTING -t mangle -p tcp -m mark ! --mark 0 -j ACCEPT

  上面代码表明接收所有非0的标记包。

  #iptables -A PREROUTING -t mangle -p tcp -m ipp2p --ipp2p -j MARK --set-mark 1

  上面代码表明将ipp2p连接标记为“1”。

  #iptables -A PREROUTING -t mangle -p tcp -m mark --mark 1 -j CONNMARK --save-mark

  上面代码表明保存所有标记为“1”的包到CONNMARK目标中。

  通过上面设置得到的结果是,每一个标示为P2P连接的包被标记成“1”,然后再通过tc过滤,执行下面的操作:

  #tc filter add dev eth0 parent 1:0 protocol ip prio 4 handle 1 fw classid 1:11

  #tc filter add dev eth1 parent 2:0 protocol ip prio 4 handle 1 fw classid 2:11

  使用HTB和过滤,将所有标记为“1”的包放到每一个设备类中,通过对这些设备类的限制来达到对P2P连接带宽的限制。