用过ipset的朋友应该知道,在ip数量非常多的情况下,使用ipset来做防火墙的白名单或者黑名单是非常方便的,在centos6系列及以上的系统中安装ipset都很简单,直接使用yum命令安装即可,但是在centos5系统中ipset就无法使用yum安装了,只能手动编译,而且由于官方源代码包的安装说明太过于简单了,之前好几次安装都以失败告终了,直到最近服务器老是受到攻击,才彻底研究了一下,现将整个安装的过程记录下来,希望也能给有需要的朋友一个参考。
在ipset4.5安装包的README文件中要求内核版本为(version >= 2.6.16 or 2.4.36.x)原则上centos5系列的操作系统应该都满足要求,如不满足则使用yum升级内核即可
#编译ipset4.5需要依赖内核源代码,使用yum安装kernel-devel即可
yum install kernel-devel
#查看安装是否成功
rpm -qa | grep kernel
kernel-headers-2.6.18-419.el5
kernel-2.6.18-398.el5
kernel-devel-2.6.18-419.el5
#安装好的内核源代码路径
ls -1 /usr/src/kernels/2.6.18-419.el5-x86_64/
arch
block
crypto
drivers
fs
include
init
ipc
kabi_whitelist
kernel
lib
Makefile
mm
Module.kabi
Module.markers
Module.symvers
net
samples
scripts
security
sound
symsets-2.6.18-419.el5.tar.gz
usr
#下载ipset4.5
https://github.com/Olipro/ipset/tree/v4.5
unzip ipset-4.5.zip
cd ipset-4.5
#开始编译 KERNEL_DIR 为内核源代码的路径
make KERNEL_DIR=/usr/src/kernels/2.6.18-419.el5-x86_64
make KERNEL_DIR=/usr/src/kernels/2.6.18-419.el5-x86_64 install
make KERNEL_DIR=/usr/src/kernels/2.6.18-419.el5-x86_64 clean
make KERNEL_DIR=/usr/src/kernels/2.6.18-419.el5-x86_64 binaries
make KERNEL_DIR=/usr/src/kernels/2.6.18-419.el5-x86_64 binaries_install
make KERNEL_DIR=/usr/src/kernels/2.6.18-419.el5-x86_64 patch_kernel
#编译好的ipset模块,存放于extra目录中
cd /lib/modules/2.6.18-419.el5/extra
ls -1
ip_set_iphash.ko
ip_set_ipmap.ko
ip_set_ipporthash.ko
ip_set_ipportiphash.ko
ip_set_ipportnethash.ko
ip_set_iptree.ko
ip_set_iptreemap.ko
ip_set.ko
ip_set_macipmap.ko
ip_set_nethash.ko
ip_set_portmap.ko
ip_set_setlist.ko
ipt_set.ko
ipt_SET.ko
#将extra目录下的所有模块使用insmod命令导入(注意:insmod导入的模块,服务器重启后会失效)想要开机自动导入ipset模块,请看后文中第四步的管理脚本,使用管理脚本加入rc.local文件的方式来开机自动导入模块(这一步官方README的安装过程就没有提及)
insmod ip_set.ko
insmod ip_set_iphash.ko
insmod ip_set_ipmap.ko
insmod ip_set_ipporthash.ko
insmod ip_set_ipportiphash.ko
insmod ip_set_ipportnethash.ko
insmod ip_set_iptree.ko
insmod ip_set_iptreemap.ko
insmod ip_set_macipmap.ko
insmod ip_set_nethash.ko
insmod ip_set_portmap.ko
insmod ip_set_setlist.ko
insmod ipt_set.ko
insmod ipt_SET.ko
#默认的iptables是1.3.5版本的,不支持ipset模块,需要升级到1.4版本
rpm -qa | grep iptables
iptables-1.3.5-9.2.el5_8
iptables-ipv6-1.3.5-9.2.el5_8
#下载iptables
wget https://netfilter.org/projects/iptables/files/iptables-1.4.21.tar.bz2
#编译升级iptables
tar -xjf iptables-1.4.21.tar.bz2
cd iptables-1.4.21
./configure && make && make install
cd /usr/local/sbin/
cp iptables /sbin/
cp iptables-restore /sbin/
cp iptables-save /sbin/
#验证是否升级成功
iptables -V
iptables v1.4.21
ipset4.5源码包目录下并没有提供管理脚本,为了后期使用方便,所以特意写了这个管理脚本
touch /etc/init.d/ipset
chmod 755 /etc/init.d/ipset
echo '/etc/init.d/ipset start' >> /etc/rc.local
echo '/etc/init.d/iptables start' >> /etc/rc.local
这里添加了ipset的开机启动,但是为什么还需要添加iptables的启动脚本呢,这是因为如果在防火墙规则中引用了ipset集合,那么ipset就必须要比iptables先启动,所以这里ipset启动后,必须再次启动iptables,这样防火墙才能正常工作
脚本有一处需要根据你的服务器真实情况进行修改,即ipset编译后的模块路径需要修改为你的真实路径,下面代码中也注释了
脚本使用方法:service ipset start|stop|restart|save|status
或者是:/etc/init.d/ipset start|stop|restart|save|status
#!/bin/bash
# chkconfig: 2345 07 93
# description: start stops and save ipset
# processname: ipset
# config: /etc/sysconfig/ipset
RETVAL=0
IPSET=ipset
IPSET_BIN=/usr/local/sbin/$IPSET
IPSET_DATA=/etc/sysconfig/$IPSET
[ $EUID != 0 ] && {
echo 'not the root user'; exit 1; }
print_log() {
echo -n "$1"
echo -ne "\t\t\t\t["
if [[ $2 == "OK" ]]; then
echo -ne "\033[32m $2 \033[0m"
elif [[ $2 == "FAILED" ]]; then
echo -ne "\033[31m $2 \033[0m"
else
echo -ne "\033[33m $2 \033[0m"
fi
echo -n "]"
echo -ne "\n"
}
if_print_log() {
[[ $RETVAL -eq 0 ]] && print_log "$1" "OK" || print_log "$1" "FAILED"
}
start() {
lsmod | grep ip_set > /dev/null 2>&1
if [[ $? -ne 0 ]]; then
#此路径需要修改为ipset模块的真实路径
cd /lib/modules/2.6.18-419.el5/extra/
insmod ip_set.ko
insmod ip_set_nethash.ko
insmod ip_set_iphash.ko
insmod ip_set_ipmap.ko
insmod ip_set_ipporthash.ko
insmod ip_set_ipportiphash.ko
insmod ip_set_ipportnethash.ko
insmod ip_set_iptree.ko
insmod ip_set_iptreemap.ko
insmod ip_set_macipmap.ko
insmod ip_set_portmap.ko
insmod ip_set_setlist.ko
insmod ipt_set.ko
insmod ipt_SET.ko
fi
[[ ! -f "$IPSET_DATA" ]] && {
print_log "${IPSET_DATA} does not exist" "FAILED"; exit 1; }
if [[ -n "$($IPSET_BIN -L)" ]]; then
print_log "ipset is running..." "WARNING"
else
$IPSET_BIN -R < $IPSET_DATA
RETVAL=$?
if_print_log "start ipset"
fi
}
stop() {
if [[ -n "$($IPSET_BIN -L)" ]]; then
$IPSET_BIN -X
RETVAL=$?
if_print_log "stop ipset"
else
print_log "ipset has stopped" "WARNING"
fi
}
restart() {
stop
start
}
save() {
[[ ! -f "$IPSET_DATA" ]] && {
print_log "${IPSET_DATA} does not exist" "FAILED"; exit 1; }
if [[ -n "$($IPSET_BIN -L)" ]]; then
$IPSET_BIN -S > ${IPSET_DATA}
RETVAL=$?
if_print_log "ipset save config to ${IPSET_DATA}"
else
print_log "ipset is stopped" "WARNING"
fi
}
status() {
if [[ -n "$($IPSET_BIN -L)" ]]; then
$IPSET_BIN -L
else
print_log "ipset is stopped" "WARNING"
fi
}
case "$1" in
start)
start;;
stop)
stop;;
restart)
restart;;
save)
save;;
status)
status;;
*)
echo $"Usage: $0 {start|stop|restart|save|status}"
esac
exit $RETVAL
安装好ipset后,我们在iptables中引用ipset实现ip白名单
白名单:即只允许指定的ip访问服务器的指定端口
#创建ipset配置文件,将ip以网段的方式写入ipset的china_ip集合中
vi /etc/sysconfig/ipset
-N china_ip nethash --hashsize 1024 --probes 4 --resize 50
-A china_ip 10.0.0.0/8
-A china_ip 127.0.0.1/31
-A china_ip 192.168.0.0/16
-A china_ip 114.114.114.114/31
-A china_ip 223.5.5.5/31
-A china_ip 8.8.8.8/31
COMMIT
#在防火墙中引用ipset,如下防火墙规则,只有在ipset的china_ip集合中的ip才能访问服务器开放的22端口
vi /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m set ! --match-set china_ip src -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -j DROP
-A FORWARD -m set ! --match-set china_ip src -j DROP
-A FORWARD -m set ! --match-set china_ip dst -j DROP
-A OUTPUT -p udp --sport 123 -j ACCEPT
-A OUTPUT -m set ! --match-set china_ip dst -j DROP
COMMIT
#启动ipset和iptables
service ipset start
service iptables start
centos5系列最高只能安装ipset4.5版本,centos6系列可以安装更高的版本,centos5和centos6在ipset命令的使用方式上有很大区别,下面列出了centos5下常用的管理ipset的命令
ipset -N china_ip nethash #创建一个名为china_ip类型为nethash的集合
ipset -R < /etc/sysconfig/ipset #导入ipset配置文件
ipset -X china_ip #清除china_ip集合
ipset -X #清除所有集合
ipset -S > /etc/sysconfig/ipset #将集合存储到配置文件中