CentOS7 ipset + iptables限制国外IP访问

CentOS7 ipset + iptables限制国外IP访问

ipset -version

yum install -y ipset wget

优化核心参数

vi /etc/sysctl.conf
vm.swappiness=0
net.ipv4.tcp_max_tw_buckets=5000

# 文件句柄上限
fs.file-max = 1048576

# TCP基础优化
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3

# 后端出站临时端口范围
net.ipv4.ip_local_port_range = 1024 65535

# nftables conntrack 10W并发预留2倍以上容量
net.netfilter.nf_conntrack_max = 1310720
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 15

# 连接队列扩容
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# TCP缓冲区
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216


echo "nf_conntrack" >> /etc/modules-load.d/netfilter.conf
echo "nf_conntrack_ipv4" >> /etc/modules-load.d/netfilter.conf

modprobe nf_conntrack
modprobe nf_conntrack_ipv4

sysctl -p


# 修改系统文件句柄限制
vi /etc/security/limits.conf
* soft nofile 1048576
* hard nofile 1048576

root soft nofile 1048576
root hard nofile 1048576
mkdir -p /opt/ipset/
touch /opt/ipset/manual_white.txt


加载iptables规则

[root@nftables-test ~]# cat install_ipset.sh 
#!/bin/bash

BASE_DIR=/opt/ipset

CACHE_CIDR=${BASE_DIR}/china_ip.txt
WHITE_FILE=${BASE_DIR}/manual_white.txt

FIXED_WHITE=(
"192.168.0.0/16"
"172.30.0.0/16"
"10.0.0.0/8"
)


# 缓存时间,7天更新一次
CACHE_TTL=$((7*24*3600))

log()
{
    echo "$(date '+%F %T') $1"
}

mkdir -p $BASE_DIR

#################################################
# 下载中国IP段
#################################################

NEED_DOWNLOAD=true


if [ -s "$CACHE_CIDR" ]; then
    FILE_TIME=$(stat -c %Y "$CACHE_CIDR")
    NOW=$(date +%s)
    AGE=$((NOW - FILE_TIME))

    if [ "$AGE" -lt "$CACHE_TTL" ]; then
        log "本地CIDR缓存有效,已经 $((AGE/3600)) 小时,跳过下载"
        NEED_DOWNLOAD=false
    fi
fi

if [ "$NEED_DOWNLOAD" = true ]; then

    log "开始从APNIC下载中国IPv4网段"

    TMP_FILE=${CACHE_CIDR}.tmp

    if wget --timeout=60 -q -O- \
    'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' \
    | awk -F\| '/CN\|ipv4/ {
        printf("%s/%d\n",$4,32-log($5)/log(2))
    }' > $TMP_FILE
    then

        # 防止空文件覆盖
        if [ -s "$TMP_FILE" ]; then
            mv $TMP_FILE $CACHE_CIDR
            log "中国CIDR更新成功"
        else
            rm -f $TMP_FILE
            log "下载结果为空,继续使用旧缓存"
        fi
    else
        rm -f $TMP_FILE
        log "APNIC下载失败,继续使用旧缓存"
    fi
fi


if [ ! -s "$CACHE_CIDR" ]; then
    log "错误:中国CIDR文件不存在"
    exit 1
fi


#################################################
# 创建ipset
#################################################

create_set()
{
    SET_NAME=$1

    ipset list -n | grep -w "$SET_NAME" >/dev/null
    if [ $? -ne 0 ]; then
        ipset create \
        $SET_NAME \
        hash:net \
        family inet \
        hashsize 65536 \
        maxelem 200000
    else
        ipset flush $SET_NAME
    fi
}

create_set china_net
create_set fixed_white
create_set manual_white

#################################################
# 导入固定白名单
#################################################

log "加载固定白名单"

for ip in ${FIXED_WHITE[@]}
do
    ipset add fixed_white $ip -exist
done


#################################################
# 导入中国CIDR
#################################################

log "加载中国IP网段"

while read ip
do
    [[ -z "$ip" ]] && continue
    [[ "$ip" =~ ^# ]] && continue
    ipset add china_net $ip -exist
done < $CACHE_CIDR


#################################################
# 导入手工白名单
#################################################

if [ -f "$WHITE_FILE" ]; then
log "加载手工白名单"
while read ip
do
    [[ -z "$ip" ]] && continue
    [[ "$ip" =~ ^# ]] && continue
    ipset add manual_white $ip -exist
done < $WHITE_FILE
fi

#################################################
# 保存ipset
#################################################

ipset save > /etc/sysconfig/ipset

#################################################
# iptables规则
#################################################

iptables -N CHINA_FILTER 2>/dev/null
iptables -F CHINA_FILTER

# 放行必要端口
iptables -A CHINA_FILTER \
-m conntrack --ctstate ESTABLISHED,RELATED \
-j ACCEPT

# 本机回环
iptables -A CHINA_FILTER \
-i lo \
-j ACCEPT

# ICMP
iptables -A CHINA_FILTER \
-p icmp \
-j ACCEPT

# 固定白名单
iptables -A CHINA_FILTER \
-m set --match-set fixed_white src \
-j ACCEPT


# 手工白名单
iptables -A CHINA_FILTER \
-m set --match-set manual_white src \
-j ACCEPT


# 中国IP
iptables -A CHINA_FILTER \
-m set --match-set china_net src \
-j ACCEPT

# 默认拒绝
iptables -A CHINA_FILTER \
-j DROP


# INPUT挂载
iptables -C INPUT -j CHINA_FILTER 2>/dev/null
if [ $? -ne 0 ];then
    iptables -I INPUT 1 -j CHINA_FILTER
fi

#service iptables save

#################################################
# 输出统计
#################################################

log "更新完成"
echo "放行中国IP网段数量:"
ipset list china_net | grep "Number of entries"

echo "手动白名单IP网段数量:"
ipset list manual_white | grep "Number of entries"

echo "固定白名单网段数量:"
ipset list fixed_white | grep "Number of entries"

手动加载部分

配置手动白名单

vi /opt/ipset/manual_white.txt

[root@nftables-test ~]# cat reload_manual_white.sh 
#!/bin/bash

WHITE_FILE=/opt/ipset/manual_white.txt

if [ ! -f "$WHITE_FILE" ];then
    echo "文件不存在:$WHITE_FILE"
    exit 1
fi

echo "刷新手工白名单"

ipset flush manual_white

while read ip
do
    [[ -z "$ip" ]] && continue
    [[ "$ip" =~ ^# ]] && continue
    ipset add manual_white $ip -exist
done < $WHITE_FILE

ipset save > /etc/sysconfig/ipset

echo "完成"

ipset list manual_white | grep "Number"


# 执行
chmod +x reload_manual_white.sh
./reload_manual_white.sh

运维操作

查看所有规则和命中数量

[root@nftables-test ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 2346  198K CHINA_FILTER  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 258 packets, 35392 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain CHINA_FILTER (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  449 29868 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
  142 14659 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set fixed_white src
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set manual_white src
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            match-set china_net src
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0

查看全部的ipset列表

# 查看所有的ipset列表
ipset list -n
ipset list china_net

全部放行兜底

清理全部规则

iptables -F
posted @ 2026-08-10 09:04  Gshelldon  阅读(5)  评论(0)    收藏  举报