Chinaunix首页 | 论坛 | 博客
  • 博客访问: 966008
  • 博文数量: 184
  • 博客积分: 10030
  • 博客等级: 上将
  • 技术积分: 1532
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-27 18:32
文章分类

全部博文(184)

文章存档

2009年(1)

2008年(63)

2007年(39)

2006年(79)

2005年(2)

我的朋友

分类: LINUX

2006-08-07 19:45:44

CentOS 的内核编译郁闷了很久,才知道原因.把这个文章载下来.有空试试 :)

ipt_connlimit是个很好用的iptables模块,可以匹配端口的单ip链接数量,这对于高负载的服务器是很不错的选择,例如我们可以限制21端口每个ip只能链接2个线程等等。但因为connlimit的2.6版本是针对2.6.11以后的 内核版本的,而CentOS4.X和RedHat AS4都是2.6.9内核,这两个版本之间netfilter有几个结构变量不同,所以正常的编译是不可能成功的。我被这个问题郁闷了好久,在得到cu的colddawn帮助之后才成功的把它编译并应用。在此,跟colddawn说声谢谢。
一,反编译得到centos的内核源码包(这一步主要转colddawn的原创)
RedHat企业版自从AS4开始,桌面版本自从FC3开始,不再单独提供kernel-sourcecode的rpm安装包,原因是RedHat认为没有必要维护单独的kernel-sourcecode包,因为所有的源代码包都应该包含在.src.rpm中而不是rpm中。所以在这些高版本的RedHat Linux上,我们如果需要定制内核的话,没有直接的源代码rpm可以安装,只能通过kernel.org下载的tar.gz的包手工安装,或者通过kernel-*.src.rpm编译出kernel-source包再来安装。后面一种方法可以享受到RedHat针对内核的某些参数和代码的优化,因此对使用RedHat发行版特别是企业版本的,是有一定好处的。
但是目前很多人至今分不清内核,内核开发,内核源代码一些包之间的关系,因此在编译内核的时候经常走弯路,同时RedHat官方对于如果得到kernel-source也没有明确的指示,导致很多人不得要领。

首先认清楚各rpm包的内容和用途
kernel-*.rpm ------------- 内核二进制包,没有的话系统都起不来
kernel-sourcecode-*.rpm------------------- 内核源代码包,安装到/usr/src/linux-*下面的,包含内核源代码,编译内核必须(当然是不考虑用kernel.tar.gz编译的情况),但高版本RedHat Linux不再提供此rpm,原因参见官方Release Note,这篇文章的最终目的就是要我们自己把这个包搞出来。
kernel-devel-*.rpm----------------内核开发包,安装到/usr/src/kernels,用于内核模块开发,组织形式跟内核源代码包类似,包含了部分内核源代码。注意很多人误认为这个就是内核源代码包,直接拿它来编译内核,当然不可能成功。这个包只是用于内核模块一级开发,例如驱动程序等,虽然也可以make menuconfig make dep等,但make bzImage是不可能成功的,因为缺失了核心源代码。
kernel-*.src.rpm---------------RedHat提供的用于建立rpm的源代码包,安装到/usr/src/redhat中,使用rpmbuild可以从这个包中build出上面所说的所有包。

现在就来从src.rpm编译出上面的所有的包,除了sourcecode这个包其他的包都可以在不用修改任何地方的情况下直接rpmbuild出来,唯有sourcecode这个比较麻烦,一定要按照下面的步骤来做,我以centos4.3版本为例,其 他版本相同。
#首先安装src.rpm
rpm -ivh kernel-2.6.9-34L.src.rpm
#进入相应目录,要修改spec文件
cd /usr/src/redhat/SPECS
vi kernel-2.6.spec
#主要修改如下地方:
1,define buildsource 0------------我的这个在第8行,改为1,这就是为什么没有源代码包的原因,因为默认不生成源代码包
2, Requires: qt-devel, gtk2-devel readline-devel ncurses-devel-------我的在572行,如果没用用X的话,把这句注释掉,这样编译出来的包就不依赖于X-window的某些包,因为内核配置是可以make xconfig的,所以默认依赖X-window,我没装X-window,因此这个就去掉了。
#保存退出
touch /etc/beehive-root
#这句命令非必须,如果不做的话,最后编译出来的包都会变成kernel-*.*-root.rpm,多了个root,据说是为了标示包的编译人的,如果touch了这个文件,就没有这个问题了,命名和官方rpm一样。
rpmbuild -ba --target=i686 ./kernel-2.6.spec
#编译i686平台的所有包,这样上面介绍的所有包都会生成,或者换成rpmbuild -bb --target=i686 ./kernel-2.6.spec只编译非src.rpm。
#所有包就会生成到/usr/src/redhat/RPMS/i686下面

#如果只需要sourcecode而并非所有rpm包,那在修改spec文件时还要修改如下行:

48 %ifarch noarch
49 %define builddoc 1
50 %define buildsource 0----------------这里0修改为1
在编译的时候使用rpmbuild -ba --target=noarch ./kernel-2.6.spec,这样仅仅编译soucecode和doc包,会节省很多时间。
执行上述步骤之后会在/usr/src/redhat/RPMS/noarch/里生成一个kernel-sourcecode-*.rpm包,这就是我们想要的。
执行rpm -ivh kernel-sourcecode-*.rpm,在/usr/src底下就会生成linux-2.6.9-34.EL这个文件夹,这就是内核的源代码。
二,编译netfilter
1,下载解开压缩包
wget
wget
tar xjvf iptables-1.3.1.tar.bz2
tar xjvf patch-o-matic-ng-20060429.tar.bz2
2 给netfilter打补丁
cd /usr/src/linux-2.6.9-34.EL
make mrproper
make menuconfig,什么都不做,直接保存退出
vi Makefile,将“EXTRAVERSION = -34.ELcustom”改为“EXTRAVERSION = -34EL”
cd /usr/src/patch-o-matic-ng-20060429-
KERNEL_DIR=/usr/src/linux-2.6.9_34EL IPTABLES_DIR=/usr/src/iptables-1.3.1 ./runme ipt_connlimit
cd /usr/src/linux-2.6.9-34.EL
在Device Drivers->;Networking support->;Networking options->;Network packet filtering (replaces ipchains)
->;IP: Netfilter Configuration中把ipt_connlimit项选上
. 然后保存退出
3,编译安装模块
这步很重要,前面提到connlimit的2.6版本是针对2.6.11以后的内核版本的,所以直接编译会失败,所以我们必须先改变一下ipt_connlimit.c的部分代码,详见以下
--- BUILD-connlimit/ipt_connlimit.c.RH 2005-07-04 20:53:55.000000000 +0200
+++ BUILD-connlimit/ipt_connlimit.c 2005-07-04 20:56:12.619285450 +0200
@@ -63,9 +63,9 @@
for (lh = hash->next; lh != hash; lh = lh->next) {
conn = list_entry(lh,struct ipt_connlimit_conn,list);
found = ip_conntrack_find_get(&conn->tuple,ct);
- if (found != NULL &&
- 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
- found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
+ if (found != NULL
+ && 0 == memcmp(&conn->tuple,&tuple,sizeof(tuple))
+ && found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
/* Just to be sure we have it only once in the list.
We should'nt see tuples twice unless someone hooks this
into a table without "-p tcp --syn" */
@@ -91,14 +91,14 @@
lh = lh->prev;
list_del(lh->next);
kfree(conn);
- nf_conntrack_put(&found->ctrack->infos[0]);
+ nf_conntrack_put(&found->ctrack->ct_general);
continue;
}
if ((addr & mask) == (conn->tuple.src.ip & mask)) {
/* same source IP address -> be counted! */
matches++;
}
- nf_conntrack_put(&found->ctrack->infos[0]);
+ nf_conntrack_put(&found->ctrack->ct_general);
}
if (addit) {
/* save the new connection in our list */
@@ -109,8 +109,10 @@
NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
#endif
conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
if (NULL == conn) {
spin_unlock_bh(&data->lock);
return -1;
}
memset(conn,0,sizeof(*conn));
INIT_LIST_HEAD(&conn->list);
conn->tuple = tuple;
@@ -127,8 +129,6 @@
const struct net_device *out,
const void *matchinfo,
int offset,
const void *hdr,
u_int16_t datalen,
int *hotdrop)
{
const struct ipt_connlimit_info *info = matchinfo;
@@ -204,8 +204,14 @@
kfree(info->data);
}

static struct ipt_match connlimit_match = {
.list = { NULL, NULL },
.name = "connlimit",
.match = &match,
.checkentry = &check,
.destroy = &destroy,
.me = THIS_MODULE
};

static int __init init(void)
{

改完之后保存退出
执行make modules_prepare
执行make modules SUBDIRS=net/ipv4/netfilter
cp /usr/src/llinux-2.6.9-34.EL/net/ipv4/netfilter/ipt_connlimit.ko /lib/modules/2.6.9-34.EL/kernel/net/ipv4/netfilter/
chmod +x /lib/modules/2.6.9-34.EL/kernel/net/ipv4/netfilter/ipt_connlimit.ko
depmod –a
4,编译iptables
cd /usr/src/iptables.1.3.1
参照INSTALL文件我们进行编译安装
make KERNEL_DIR=/usr/src/linux-2.6.9-34.EL
会有错误编译不过
vi /usr/src/linux/include/ linux-2.6.9-34.EL /config.h把下面的三行注释掉
//#ifndef __KERNEL__
//#error including kernel header in userspace; use the glibc headers instead!
//#endif

然后重新编译安装
make KERNEL_DIR=/usr/src/linux-2.6.9-34.EL
make install KERNEL_DIR=/usr/src/linux-2.6.9-34.EL

完成安装以后测试一下

modprobe ipt_connlimit
iptables -A INPUT -p tcp --dport 21 -m connlimit --connlimit-above 1 -j REJECT

ok,到此全部结束•
ps,前天发现捷克已经有人把ipt_connlimit做成一个rpm包,顿时产生一种相恨见晚的感觉!拿出来分享给大家吧·注意版本

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