使用iptables实现一个简单的安全组

阿里云教程2个月前发布
14 0 0

Linux 主机安全组并非 Linux 系统内核原生自带的独立组件,而是基于 Linux 系统中的防火墙技术(如iptables、nftables,或云环境中厂商封装的防火墙服务)实现的逻辑访问控制单元。它本质上是一组 “流量过滤规则的集合”,通过对网络数据包的 “源 IP、目标 IP、端口、协议” 等关键信息进行匹配,决定是否允许数据包进入(入站)或离开(出站)Linux 主机。

列如移动云:

使用iptables实现一个简单的安全组

简单来说,当外部设备(如其他服务器、用户电脑)尝试与 Linux 主机通信时,安全组会先 “检查” 该请求的数据包信息:若符合预设的 “允许” 规则,就放行数据包;若不符合任何允许规则(或触发 “拒绝” 规则),则直接拦截数据包,阻止通信建立。

当然了,有的时候你不需要那么复杂的软件,只需要允许某些IP访问本主机的某些端口。这个时候,这个短小精悍的小工具就会派上用场。

输入

下面使用iptables开发一个,限制IP列表访问端口列表的功能,即白名单(安全组)场景。

尤其是在内网的同一VPC下的主机一些基础服务,只供内部服务使用,内部服务暴露在外面不安全。由于,可以给这些主机的IP加白名单,限制只有指定的IP访问这些主机的特定端口

  • allow_ips
10.22.1.0/24 # 网段
10.55.134.8   # 单个IP
  • allow_ports
2379       # 特定端口
3001-3005  # 端口范围
9000

脚本

  • apply-rules.sh
# 配置文件路径
ALLOWED_IPS_FILE="allow_ips"          # IP 白名单(每行一个IP或者网段)
ALLOWED_PORTS_FILE="allow_ports"   # 端口列表(每行一个端口或范围,如 30000-31000)

# 检查文件是否存在
if [ ! -f "$ALLOWED_IPS_FILE" ]; then
    echo "错误:IP 白名单文件 $ALLOWED_IPS_FILE 不存在!" >&2
    exit 1
fi

if [ ! -f "$ALLOWED_PORTS_FILE" ]; then
    echo "错误:端口列表文件 $ALLOWED_PORTS_FILE 不存在!" >&2
    exit 1
fi

# 读取 IP 白名单(跳过空行和注释)
ALLOWED_IPS=()
while IFS= read -r ip; do
    if [[ -n "$ip" && ! "$ip" =~ ^# ]]; then
        ALLOWED_IPS+=("$ip")
    fi
done < "$ALLOWED_IPS_FILE"

if [ ${#ALLOWED_IPS[@]} -eq 0 ]; then
    echo "错误:未找到有效的 IP 地址!" >&2
    exit 1
fi

# 读取端口列表(支持单个端口或范围)
ALLOWED_PORTS=()
while IFS= read -r port_spec; do
    if [[ -n "$port_spec" && ! "$port_spec" =~ ^# ]]; then
        ALLOWED_PORTS+=("$port_spec")
    fi
done < "$ALLOWED_PORTS_FILE"

if [ ${#ALLOWED_PORTS[@]} -eq 0 ]; then
    echo "错误:未找到有效的端口!" >&2
    exit 1
fi

# 创建自定义链(如果不存在)
CUSTOM_CHAIN="ALLOW_SPECIFIC_PORTS"
if ! iptables -L "$CUSTOM_CHAIN" &>/dev/null; then
    iptables -N "$CUSTOM_CHAIN"
fi

# 清空旧规则(防止重复)
iptables -F "$CUSTOM_CHAIN"

# 为每个 IP 和端口添加允许规则
for port_spec in "${ALLOWED_PORTS[@]}"; do
    if [[ "$port_spec" == *-* ]]; then
        # 处理端口范围(如 30000-31000 → 30000:31000)
        start_port=$(cut -d'-' -f1 <<< "$port_spec")
        end_port=$(cut -d'-' -f2 <<< "$port_spec")
        for ip in "${ALLOWED_IPS[@]}"; do
            iptables -A "$CUSTOM_CHAIN" -s "$ip" -p tcp --dport "${start_port}:${end_port}" -j ACCEPT
            echo "允许 IP $ip 访问端口范围 ${start_port}-${end_port}"
        done
    else
        # 处理单个端口
        for ip in "${ALLOWED_IPS[@]}"; do
            iptables -A "$CUSTOM_CHAIN" -s "$ip" -p tcp --dport "$port_spec" -j ACCEPT
            echo "允许 IP $ip 访问端口 $port_spec"
        done
    fi
done

# 将自定义链挂载到 INPUT 链(如果尚未挂载)
for port_spec in "${ALLOWED_PORTS[@]}"; do
    if [[ "$port_spec" == *-* ]]; then
        start_port=$(cut -d'-' -f1 <<< "$port_spec")
        end_port=$(cut -d'-' -f2 <<< "$port_spec")
        if ! iptables -C INPUT -p tcp --dport "${start_port}:${end_port}" -j "$CUSTOM_CHAIN" &>/dev/null; then
            iptables -A INPUT -p tcp --dport "${start_port}:${end_port}" -j "$CUSTOM_CHAIN"
        fi
    else
        if ! iptables -C INPUT -p tcp --dport "$port_spec" -j "$CUSTOM_CHAIN" &>/dev/null; then
            iptables -A INPUT -p tcp --dport "$port_spec" -j "$CUSTOM_CHAIN"
        fi
    fi
done

# 拒绝其他 IP 访问这些端口(直接 DROP,无日志)
for port_spec in "${ALLOWED_PORTS[@]}"; do
    if [[ "$port_spec" == *-* ]]; then
        start_port=$(cut -d'-' -f1 <<< "$port_spec")
        end_port=$(cut -d'-' -f2 <<< "$port_spec")
        if ! iptables -C INPUT -p tcp --dport "${start_port}:${end_port}" -j DROP &>/dev/null; then
            iptables -A INPUT -p tcp --dport "${start_port}:${end_port}" -j DROP
        fi
    else
        if ! iptables -C INPUT -p tcp --dport "$port_spec" -j DROP &>/dev/null; then
            iptables -A INPUT -p tcp --dport "$port_spec" -j DROP
        fi
    fi
done

# 保存规则(持久化)
if command -v iptables-save >/dev/null; then
    iptables-save > /etc/iptables.rules
    echo "规则已保存到 /etc/iptables.rules"
else
    echo "警告:未找到 iptables-save 命令,规则需手动持久化!" >&2
fi

echo "配置完成!当前规则:"
iptables -L INPUT -n --line-numbers
iptables -L "$CUSTOM_CHAIN" -n --line-numbers

使用方法

bash apply-rules.sh

按“IP+端口”组合添加 ACCEPT 规则,脚本会输出每条规则的添加日志,最终生成以下6条允许规则(均存入 ALLOW_SPECIFIC_PORTS 链):

白名单IP/网段

允许访问的端口/范围

规则效果

10.22.1.0/24

2379

允许该网段所有IP访问TCP 2379端口

10.22.1.0/24

3001-3005

允许该网段所有IP访问TCP 3001-3005端口

10.22.1.0/24

9000

允许该网段所有IP访问TCP 9000端口

10.55.134.8

2379

允许该单个IP访问TCP 2379端口

10.55.134.8

3001-3005

允许该单个IP访问TCP 3001-3005端口

10.55.134.8

9000

允许该单个IP访问TCP 9000端口

© 版权声明

相关文章

暂无评论

none
暂无评论...