本篇是服务器运维系列第四篇,聚焦防火墙与网络安全。从基础概念到生产实践,涵盖 iptables、nftables、UFW、firewalld、云安全组、端口管理、DDoS 防护和入侵检测,帮助你构建扎实的服务器安全防线。
网络安全基础概念
为什么需要防火墙?
防火墙是服务器的第一道防线。没有防火墙的服务器,就像一栋没有门的房子——任何人都可以随意进出。
核心原则:最小权限(Principle of Least Privilege)
- 默认拒绝所有入站流量,仅开放业务必需端口
- 出站流量按需控制,不要放任所有出站
- 规则越少越好,定期清理过时规则
网络流量三要素
| 要素 | 说明 | 示例 |
|---|---|---|
| 源地址(Source IP) | 流量从哪里来 | 192.168.1.100 |
| 目的地址(Dest IP) | 流量去哪里 | 10.0.0.1 |
| 端口(Port) | 访问什么服务 | 22(SSH), 80(HTTP), 443(HTTPS) |
常见网络威胁
- 端口扫描:攻击者探测服务器开放了哪些端口
- 暴力破解:针对 SSH、数据库等服务的密码穷举
- DDoS 攻击:大量恶意流量使服务不可用
- 中间人攻击:拦截和篡改通信数据
- 未授权访问:通过漏洞直接入侵系统
防火墙技术分类
| 类型 | 工作层次 | 代表工具 |
|---|---|---|
| 包过滤防火墙 | 网络层(L3/L4) | iptables, nftables |
| 应用层防火墙 | 应用层(L7) | Nginx WAF, ModSecurity |
| 状态防火墙 | 跟踪连接状态 | iptables state 模块 |
| 下一代防火墙 | L3-L7 综合 | 商业硬件防火墙 |
从内核到用户:防火墙的分层结构
Netfilter 是 Linux 内核自带的包过滤框架,iptables / nftables 是管理它的用户态命令行工具,ufw / firewalld 是对前者的友好封装。三层各司其职。
| 层级 | 角色 |
|---|---|
| 内核 | Netfilter,所有发行版都内置 |
| 管理工具 | iptables / nftables,把规则写入内核 |
| 前端 | ufw / firewalld,生成并维护 iptables/nftables 规则 |
发行版默认预装不同:
| 发行版 | 默认预装 |
|---|---|
| Ubuntu / Debian 系 | ufw |
| CentOS / RHEL / Fedora 系 | firewalld |
| Arch | 都不预装,自行选择 |
ufw 和 firewalld 与发行版没有强绑定:Ubuntu 上可安装 firewalld,Fedora 上也可安装 ufw。
新发行版上执行的 iptables 命令往往是 iptables-nft 兼容层,把旧语法翻译成 nftables 规则执行:
iptables --version
# iptables v1.8.7 (nf_tables) ← 兼容层(背后是 nftables)
# iptables v1.8.7 (legacy) ← 真正的 iptables老教程的 iptables 命令在新系统上行为可能不一致,原因就在这里:表层命令相同,底层引擎已经换成 nftables。
iptables 详解
iptables 是 Linux 上最经典的防火墙工具,虽然在新版内核中逐渐被 nftables 取代,但理解 iptables 是掌握 Linux 防火墙的基础。
四表五链
四表(Tables)——按功能分类:
| 表名 | 功能 | 常用程度 |
|---|---|---|
| filter | 过滤流量(默认表) | 最高 |
| nat | 网络地址转换(DNAT/SNAT) | 较高 |
| mangle | 修改数据包头部 | 低 |
| raw | 连接跟踪豁免 | 极低 |
五链(Chains)——按位置分类:
数据包流向:
客户端 → [PREROUTING] → 路由判断 → [INPUT] → 本地进程
↓
本地进程响应 → [OUTPUT] → [POSTROUTING] → 客户端
↓
转发流量 → [FORWARD] → [POSTROUTING] → 外部| 链名 | 触发时机 | 典型用途 |
|---|---|---|
| PREROUTING | 数据包进入路由判断之前 | DNAT、端口映射 |
| INPUT | 数据包目标是本机 | 限制入站访问 |
| FORWARD | 数据包需要转发 | 路由/网关防火墙 |
| OUTPUT | 本机产生的数据包 | 限制出站访问 |
| POSTROUTING | 数据包离开路由之后 | SNAT、Masquerade |
基本语法
iptables [-t 表名] 命令选项 [链名] [匹配条件] [-j 目标动作]常用命令选项:
# 查看规则
iptables -L -n -v # 查看 filter 表所有规则
iptables -t nat -L -n -v # 查看 nat 表规则
iptables -L INPUT -n -v --line-numbers # 带行号查看 INPUT 链
# 添加规则
iptables -A INPUT ... # 追加到链末尾
iptables -I INPUT 1 ... # 插入到第 1 条
# 删除规则
iptables -D INPUT 3 # 删除第 3 条规则
iptables -F INPUT # 清空 INPUT 链
# 设置默认策略
iptables -P INPUT DROP # 默认拒绝入站
iptables -P FORWARD DROP # 默认拒绝转发
iptables -P OUTPUT ACCEPT # 默认允许出站常用匹配条件
# 按协议
-p tcp
-p udp
-p icmp
# 按端口
--dport 22 # 目标端口
--sport 1024:65535 # 源端口范围
--dport 80,443 # 多个端口(需要用 multiport 模块)
-m multiport --dports 80,443,8080
# 按 IP 地址
-s 192.168.1.0/24 # 源地址
-d 10.0.0.1 # 目标地址
-s 192.168.1.100/32 # 单个 IP
# 按网络接口
-i eth0 # 入站接口
-o eth0 # 出站接口
# 按连接状态(状态防火墙核心)
-m state --state NEW,ESTABLISHED,RELATED
-m conntrack --ctstate NEW,ESTABLISHED,RELATED
# 按速率限制
-m limit --limit 5/min # 每分钟最多 5 个包
-m recent --set # 记录最近连接常用规则示例
# ============ 基础规则 ============
# 允许回环接口
iptables -A INPUT -i lo -j ACCEPT
# 允许已建立的连接(关键!否则响应包无法回来)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 允许 SSH(仅限管理网段)
iptables -A INPUT -p tcp -s 10.0.0.0/8 --dport 22 -j ACCEPT
# 允许 HTTP/HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 允许 ICMP(ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# 丢弃无效数据包
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# 防 SYN Flood
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
# 限制 SSH 暴力破解(30 秒内超过 3 次连接则拒绝)
iptables -A INPUT -p tcp --dport 22 -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 30 --hitcount 3 --name SSH -j DROP
# 默认拒绝
iptables -P INPUT DROP# ============ 日志记录 ============
# 记录被丢弃的数据包(限速避免日志爆炸)
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPT-DROP: " --log-level 4
# 查看日志
tail -f /var/log/messages | grep IPT-DROP
# 或
journalctl -k | grep IPT-DROPDNAT 与 SNAT(网络地址转换)
DNAT(目标地址转换)——端口映射/转发:
# 将外部访问 8080 端口的流量转发到内网 192.168.1.100 的 80 端口
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
# 需要同时允许转发
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPTSNAT(源地址转换)——内网出站:
# 内网 192.168.1.0/24 出站时,源地址伪装为服务器公网 IP
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.1
# 如果是动态 IP(如拨号),用 MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ppp0 -j MASQUERADEnftables
nftables 是 iptables 的继任者,从 Linux 内核 3.13 开始引入,设计更现代、性能更好。
nftables vs iptables
| 特性 | iptables | nftables |
|---|---|---|
| 表/链管理 | 固定四表五链 | 自由定义 |
| 规则语法 | 分散的命令行参数 | 统一的规则语言 |
| 性能 | 线性匹配 | 集合和字典优化 |
| 原子操作 | 不支持 | 支持 |
| IPv4/IPv6 | 分别管理 | 统一管理 |
基本操作
# 查看所有规则
nft list ruleset
# 创建表和链
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
# 添加规则
nft add rule inet filter input iif lo accept
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input tcp dport 22 accept
nft add rule inet filter input tcp dport { 80, 443 } accept
nft add rule inet filter input ct state invalid drop
nft add rule inet filter input ip protocol icmp icmp type echo-request accept
# 删除规则(先列出获取 handle)
nft -a list chain inet filter input
# 输出示例: ... # handle 3
nft delete rule inet filter input handle 3nftables 配置文件
# /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# 允许回环
iif lo accept
# 允许已建立的连接
ct state established,related accept
ct state invalid drop
# 允许 SSH(仅管理网段)
ip saddr 10.0.0.0/8 tcp dport 22 accept
# 允许 HTTP/HTTPS
tcp dport { 80, 443 } accept
# 允许 ICMP
ip protocol icmp icmp type echo-request accept
# 日志并丢弃其余
limit rate 5/minute log prefix "NFT-DROP: " level warn
drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
# NAT 表(如有需要)
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
tcp dport 8080 dnat to 192.168.1.100:80
}
chain postrouting {
type nat hook postrouting priority 100;
ip saddr 192.168.1.0/24 oif eth0 masquerade
}
}# 应用配置
nft -f /etc/nftables.conf
# 设为开机启动
systemctl enable nftables集合(Set)——高效批量匹配
# 定义 IP 黑名单集合
nft add set inet filter blacklist { type ipv4_addr \; }
nft add element inet filter blacklist { 192.168.100.1, 192.168.100.2 }
nft add rule inet filter input ip saddr @blacklist drop
# 定义端口白名单集合
nft add set inet filter allowed_ports { type inet_service \; elements = { 22, 80, 443 } }
nft add rule inet filter input tcp dport @allowed_ports acceptUFW(Uncomplicated Firewall)
UFW 是 Ubuntu 推出的 iptables 前端,极大简化了防火墙管理,适合快速配置。
基本操作
# 安装
apt install ufw
# 启用/禁用
ufw enable
ufw disable
ufw status verbose
ufw reload
ufw --force reset # 清空所有规则
# 默认策略
ufw default deny incoming
ufw default allow outgoing
ufw default deny forward规则管理
# 允许端口
ufw allow 22/tcp # 允许 SSH
ufw allow 80,443/tcp # 允许 HTTP/HTTPS
ufw allow from 10.0.0.0/8 to any port 22 # 仅限管理网段 SSH
# 允许应用配置文件
ufw app list # 查看可用应用
ufw allow 'OpenSSH' # 按应用名放行
ufw allow 'Nginx Full' # Nginx HTTP+HTTPS
# 拒绝端口
ufw deny 23/tcp # 禁止 telnet
# 删除规则
ufw status numbered # 查看带编号的规则
ufw delete 3 # 按编号删除
ufw delete allow 80/tcp # 按规则删除
# 日志
ufw logging on # 开启日志
ufw logging low # 日志级别:off/low/medium/high/full应用配置文件
# 自定义应用配置
# /etc/ufw/applications.d/myapp
[MyApp]
title=My Custom Application
description=My custom TCP application
ports=8080/tcp|9090/tcp
# 加载
ufw app update MyApp
ufw allow MyApp高级:基于速率限制防暴力破解
# 限制 SSH 连接速率(30 秒内最多 6 次)
ufw limit 22/tcp
# 相当于:
# iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
# -m recent --set --name SSH
# iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
# -m recent --update --seconds 30 --hitcount 6 --name SSH -j DROP典型 VPS 配置
ufw default deny incoming
ufw default allow outgoing
ufw allow 22000/tcp # 修改后的 SSH 端口
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow from <办公室 IP> to any port 9090 # 面板限 IP
ufw enablefirewalld
firewalld 是 CentOS/RHEL/Fedora 的默认防火墙管理工具,支持动态规则更新(无需重启服务),使用区域(Zone)概念管理。
区域(Zone)概念
| 区域 | 默认行为 | 适用场景 |
|---|---|---|
| drop | 丢弃所有入站 | 最严格 |
| block | 拒绝所有入站(返回拒绝消息) | 严格 |
| public | 仅允许选定服务 | 公网服务器(默认) |
| external | 伪装开启,仅允许选定服务 | 外部网络 |
| internal | 仅允许选定服务 | 内部网络 |
| trusted | 允许所有流量 | 完全信任 |
基本操作
# 查看状态
firewall-cmd --state
firewall-cmd --get-active-zones
firewall-cmd --get-default-zone
firewall-cmd --list-all
# 切换区域
firewall-cmd --set-default-zone=public
firewall-cmd --change-interface=eth0 --zone=public
# 服务管理
firewall-cmd --list-services
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --remove-service=dhcpv6-client --permanent
# 端口管理
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --remove-port=8080/tcp --permanent
firewall-cmd --list-ports
# 重载配置(使 --permanent 生效)
firewall-cmd --reloadfirewalld 区分 runtime 与 permanent 两套规则:不加 --permanent 的修改重启即失效,永久修改后需要 firewall-cmd --reload 生效。
丰富规则(Rich Rules)
# 仅允许特定 IP 段 SSH
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="10.0.0.0/8"
port protocol="tcp" port="22"
accept'
# 限制连接速率
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
port protocol="tcp" port="22"
accept
limit value="3/m"'
# 拒绝特定 IP 并记录日志
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
source address="192.168.100.50"
port protocol="tcp" port="80"
log prefix="FWDROP: " level="info"
drop'
# 端口转发(DNAT)
firewall-cmd --permanent --add-rich-rule='
rule family="ipv4"
forward-port port="8080" protocol="tcp"
to-port="80" to-addr="192.168.1.100"'端口伪装(NAT)
# 开启伪装(相当于 SNAT/MASQUERADE)
firewall-cmd --permanent --zone=public --add-masquerade
# 查看
firewall-cmd --query-masquerade应急处理
# 紧急断网(panic 模式)
firewall-cmd --panic-on
firewall-cmd --panic-off
# 临时规则(重启后失效)
firewall-cmd --add-port=8080/tcp # 不加 --permanent规则持久化与工具的可见范围
规则持久化
| 工具 | 持久化方式 |
|---|---|
| ufw | 自带,重启自动恢复 |
| firewalld | 自带,runtime 与 permanent 双套规则 |
| 裸 iptables | 默认重启清空,需装 iptables-persistent |
| 裸 nftables | 默认重启清空,需写入 /etc/nftables.conf |
iptables-persistent 的配置文件在 /etc/iptables/rules.v4 与 /etc/iptables/rules.v6。apt purge iptables-persistent 会删除上述配置文件,apt remove 会保留配置文件,下次重装可复用。
各工具的可见范围
ufw 只显示自己写入的规则。Docker、fail2ban 等程序会直接写入 iptables/nftables 规则,ufw status 看不到。排查“ufw 没规则但仍有拦截或放行”时,要分清这一层。
# ufw 看到的(只是 ufw 自己的)
sudo ufw status
# iptables 看到的(所有规则,包括 docker、fail2ban 写的)
sudo iptables -L -n -v
sudo iptables -t nat -L -n -v
# nftables 看到的(新发行版)
sudo nft list ruleset| 现象 | 原因 |
|---|---|
ufw deny 80 后 docker 容器仍能从公网访问 |
Docker 自己在 nat 表里写了 DNAT 规则,绕开了 ufw 的 INPUT 链 |
| fail2ban 封了 IP,但 ufw status 看不到 | fail2ban 写入自己创建的链,不走 ufw 的规则集 |
防火墙规则重置
拿到手发现防火墙规则混乱想从头开始时,按顺序执行。先把默认策略改为 ACCEPT,再清空规则,避免清空过程中 SSH 通道直接中断:
# 1. 停掉 / 卸载所有防火墙前端
sudo systemctl stop ufw
sudo systemctl disable ufw
sudo apt purge -y iptables-persistent ufw
# 2. 清空内存中的规则
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo ip6tables -F
sudo ip6tables -X
# 3. 默认策略先设为 ACCEPT
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
# 4. 重启确认
sudo reboot
# 5. 重启后再装回想用的工具
sudo apt install -y ufw云厂商镜像与托管环境的 nft/iptables 兼容层随版本不同,清空规则前先确认当前用的是哪个前端与后端,避免 SSH 断连后只能靠 VNC 恢复访问。
云服务器安全组
云服务器(AWS、阿里云、腾讯云等)的防火墙通常通过「安全组」实现,在操作系统之外再加一层防护。
安全组最佳实践
# 典型安全组规则示例(以 CLI 伪代码表示)
# 入站规则
inbound_rules = [
# SSH - 仅限办公网段
{ protocol: "tcp", port: 22, source: "114.114.0.0/16", desc: "办公网 SSH" },
# HTTP/HTTPS - 全网
{ protocol: "tcp", port: 80, source: "0.0.0.0/0", desc: "HTTP" },
{ protocol: "tcp", port: 443, source: "0.0.0.0/0", desc: "HTTPS" },
# 数据库 - 仅限应用服务器
{ protocol: "tcp", port: 3306, source: "10.0.1.0/24", desc: "内网 MySQL" },
# ICMP - 允许 ping
{ protocol: "icmp", port: -1, source: "0.0.0.0/0", desc: "Ping" },
]
# 出站规则
outbound_rules = [
{ protocol: "all", port: -1, destination: "0.0.0.0/0", desc: "允许所有出站" },
]安全组设计原则
┌──────────────────────────────────────────────┐
│ 互联网 │
└──────────┬───────────────────────────┬────────┘
│ │
┌─────▼─────┐ ┌──────▼──────┐
│ Web 安全组 │ │ SSH 安全组 │
│ 80/443 开放 │ │ 22 限办公网 │
└─────┬─────┘ └──────┬──────┘
│ │
┌─────▼──────────────────────────────▼────┐
│ 应用服务器(Web 层) │
└─────────────────┬───────────────────────┘
│
┌─────▼─────┐
│ DB 安全组 │
│ 3306 仅限 │
│ 应用层网段 │
└─────┬─────┘
│
┌─────▼─────┐
│ 数据库服务器 │
└───────────┘关键规则:
- 分层设计:Web 层、应用层、数据库层使用不同安全组
- 最小暴露:数据库端口只对应用层开放,不对外网开放
- 按角色授权:管理端口(SSH/RDP)仅限运维网段
- 定期审计:每月检查安全组规则,清理不再需要的规则
- 避免 0.0.0.0/0 开放敏感端口:SSH、RDP、数据库端口绝对不能对全网开放
端口管理
端口扫描与检测
# 查看本机监听端口
ss -tlnp # 推荐,比 netstat 更快
netstat -tlnp # 传统方式
lsof -i -P -n | grep LISTEN # 查看哪些进程在监听
# 检查特定端口
ss -tlnp | grep :22
ss -tlnp | grep :3306
# 从外部扫描(需要 nmap)
nmap -sT -p 1-65535 10.0.0.1 # TCP 全端口扫描
nmap -sU -p 1-1000 10.0.0.1 # UDP 扫描(慢)
nmap -sV 10.0.0.1 # 服务版本探测
nmap -O 10.0.0.1 # 操作系统探测
# 快速检查特定端口是否开放
nc -zv 10.0.0.1 22 # 测试 TCP 连接
nc -zuv 10.0.0.1 53 # 测试 UDP 连接常见端口清单
| 端口 | 服务 | 安全建议 |
|---|---|---|
| 22 | SSH | 限制来源 IP,禁用密码登录 |
| 80 | HTTP | 开放,注意 Web 安全 |
| 443 | HTTPS | 开放,使用强证书 |
| 3306 | MySQL | 仅内网,不要对外暴露 |
| 6379 | Redis | 仅内网,设置密码 |
| 27017 | MongoDB | 仅内网,启用认证 |
| 5432 | PostgreSQL | 仅内网,配置 pg_hba.conf |
| 8080 | HTTP 备用 | 按需开放 |
| 9090 | Prometheus | 仅内网 |
| 3389 | RDP (Windows) | 限制来源 IP |
修改 SSH 默认端口
# /etc/ssh/sshd_config
Port 22222
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
LoginGraceTime 30
# 重启前确保新端口在防火墙中放行!
# iptables
iptables -A INPUT -p tcp --dport 22222 -j ACCEPT
# 或 UFW
ufw allow 22222/tcp
# 重启 SSH
systemctl restart sshd改 SSH 端口时先把新端口放进防火墙,否则改完新连接进不来。验证新端口可登录后再删旧策略。
端口敲门(Port Knocking)
端口敲门是一种隐蔽技术:只有按特定顺序访问一组端口后,才开放真正的服务端口。
# 安装 knockd
apt install knockd
# /etc/knockd.conf
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 10
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22222 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 10
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22222 -j ACCEPT
tcpflags = syn
# 启动
systemctl start knockd
# 客户端敲门
knock -v server_ip 7000 8000 9000
ssh -p 22222 user@server_ip
knock -v server_ip 9000 8000 7000DDoS 基础防护
常见 DDoS 攻击类型
| 类型 | 层次 | 说明 | 防护难度 |
|---|---|---|---|
| SYN Flood | L4 | 大量半连接耗尽连接表 | 中 |
| UDP Flood | L4 | 大量 UDP 包消耗带宽 | 中 |
| ICMP Flood | L3 | Ping 洪水 | 低 |
| HTTP Flood | L7 | 正常 HTTP 请求的洪泛 | 高 |
| Slowloris | L7 | 慢速连接占用资源 | 中 |
| DNS Amplification | L3/L4 | 利用 DNS 反射放大 | 高 |
内核参数调优
# /etc/sysctl.conf
# SYN Flood 防护
net.ipv4.tcp_syncookies = 1 # 启用 SYN Cookie
net.ipv4.tcp_max_syn_backlog = 8192 # SYN 队列长度
net.ipv4.tcp_synack_retries = 2 # SYN+ACK 重试次数
net.ipv4.tcp_syn_retries = 3 # SYN 重试次数
# 连接跟踪优化
net.netfilter.nf_conntrack_max = 262144 # 最大连接跟踪数
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
# 其他安全参数
net.ipv4.conf.all.rp_filter = 1 # 反向路径过滤
net.ipv4.conf.all.accept_redirects = 0 # 禁止 ICMP 重定向
net.ipv4.conf.all.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1 # 忽略广播 ping
net.ipv4.conf.all.accept_source_route = 0 # 禁止源路由
net.ipv4.ip_forward = 1 # 如需转发则开启# 立即生效
sysctl -piptables 防 DDoS 规则集
# ============ SYN Flood 防护 ============
# 限制 SYN 包速率
iptables -A INPUT -p tcp --syn -m limit --limit 100/s --limit-burst 200 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
# ============ 连接数限制 ============
# 单 IP 最大并发连接数
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP
# 单 IP 每分钟新建连接数限制
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW \
-m recent --set --name HTTP
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW \
-m recent --update --seconds 60 --hitcount 100 --name HTTP -j DROP
# ============ UDP/ICMP Flood 防护 ============
iptables -A INPUT -p udp -m limit --limit 50/s -j ACCEPT
iptables -A INPUT -p udp -j DROP
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
# ============ 丢弃异常包 ============
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP # NULL 包
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP # XMAS 包
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # SYN+FIN
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP # SYN+RST使用 fail2ban 自动封禁
# 安装
apt install fail2ban
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600 # 封禁时间(秒)
findtime = 600 # 检测时间窗口
maxretry = 5 # 最大失败次数
banaction = iptables-multiport
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
# 自定义过滤器示例
# /etc/fail2ban/filter.d/nginx-cc.conf
[Definition]
failregex = ^<HOST> .* "(GET|POST).*" (403|444) .*$
ignoreregex =
# 启动
systemctl enable fail2ban
systemctl start fail2ban
# 常用命令
fail2ban-client status
fail2ban-client status sshd
fail2ban-client set sshd unbanip 1.2.3.4fail2ban 的封禁直接写入 iptables,若使用 ufw 管理,查看封禁状态请用 fail2ban-client status sshd,不要在 ufw status 里找。
入侵检测基础
AIDE(文件完整性检测)
# 安装
apt install aide
# 初始化数据库
aideinit
# 移动为正式数据库
cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# 检查变更
aide --check
# 更新数据库(确认变更合法后)
aide --update
cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# 定时检查(crontab)
0 3 * * * /usr/bin/aide --check | mail -s "AIDE Report" admin@example.comrkhunter(Rootkit 检测)
# 安装
apt install rkhunter
# 更新数据库
rkhunter --update
rkhunter --propupd
# 全面扫描
rkhunter --check --sk
# 查看日志
cat /var/log/rkhunter.logOSSEC(主机入侵检测系统)
# 安装(简化步骤)
wget https://github.com/ossec/ossec-hids/archive/3.7.0.tar.gz
tar xzf 3.7.0.tar.gz
cd ossec-hids-3.7.0
./install.sh
# 主要功能:
# - 日志分析(syslog, auth.log, Apache/Nginx 日志)
# - 文件完整性监控
# - Rootkit 检测
# - 实时告警(邮件通知)
# - 主动响应(自动封禁恶意 IP)安全日志分析
# 查看失败的 SSH 登录
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -20
# 查看成功登录
grep "Accepted" /var/log/auth.log
# 查看可疑的 sudo 使用
grep "sudo:" /var/log/auth.log | grep -i "command"
# 查看最近登录用户
last -a | head -20
lastb -a | head -20 # 失败的登录
# 实时监控可疑活动
tail -f /var/log/auth.log | grep -i "failed\|invalid\|error"
# 使用 journalctl 查看安全事件
journalctl -u sshd --since "1 hour ago"
journalctl _COMM=sshd --since today | grep "Failed"网络安全检查清单
初始部署检查清单
□ 防火墙已启用(iptables/nftables/ufw/firewalld)
□ 默认策略设置为 DENY/DROP
□ SSH 端口已修改(非默认 22)
□ root 远程登录已禁用
□ SSH 已禁用密码登录,仅允许密钥
□ SSH 连接速率已限制
□ 只开放了业务必需端口
□ 数据库端口未对外暴露
□ 管理端口仅限特定 IP 段
□ 云安全组规则已配置且与系统防火墙一致
□ fail2ban 已安装并启用
□ 内核安全参数已调优
□ 文件完整性检测已配置(AIDE)
□ 安全日志已开启并定期检查
□ 自动安全更新已启用定期安全审计
#!/bin/bash
# security-audit.sh - 安全审计脚本
echo "====== 端口检查 ======"
echo "监听中的端口:"
ss -tlnp
echo ""
echo "====== 防火墙规则 ======"
if command -v ufw &>/dev/null; then
ufw status verbose
elif command -v firewall-cmd &>/dev/null; then
firewall-cmd --list-all
else
iptables -L -n -v --line-numbers
fi
echo ""
echo "====== SSH 配置检查 ======"
echo "PermitRootLogin: $(grep -i '^PermitRootLogin' /etc/ssh/sshd_config || echo '未设置')"
echo "PasswordAuth: $(grep -i '^PasswordAuthentication' /etc/ssh/sshd_config || echo '未设置')"
echo "Port: $(grep -i '^Port' /etc/ssh/sshd_config || echo '默认 22')"
echo ""
echo "====== 最近失败登录 ======"
grep "Failed password" /var/log/auth.log 2>/dev/null | tail -10
echo ""
echo "====== 安全更新 ======"
apt list --upgradable 2>/dev/null | head -20
echo ""
echo "====== 磁盘使用 ======"
df -h | awk '$5 > 80 {print "警告: " $0}'
echo ""
echo "====== 运行中的进程 ======"
ps aux | wc -l
echo "总进程数如上"应急响应流程
发现可疑活动
│
▼
1. 确认攻击类型和来源
- 检查 /var/log/auth.log
- 检查防火墙日志
- ss -tlnp 查看异常连接
│
▼
2. 立即封禁攻击源
- iptables -A INPUT -s <攻击IP> -j DROP
- 云安全组添加拒绝规则
│
▼
3. 评估影响范围
- 检查是否有未授权进程
- 检查是否有新增用户
- 检查关键文件是否被修改(AIDE --check)
│
▼
4. 清理和修复
- 终止可疑进程
- 删除未授权账户和 SSH 密钥
- 更新所有密码和密钥
- 修补安全漏洞
│
▼
5. 加固防护
- 收紧防火墙规则
- 更新 fail2ban 配置
- 部署更严格的监控
│
▼
6. 记录和复盘
- 编写事故报告
- 更新应急响应预案
- 分享经验教训附录:快速参考卡
A. 防火墙选择指南
| 场景 | 推荐工具 |
|---|---|
| Ubuntu 快速配置 | UFW |
| CentOS/RHEL 生产环境 | firewalld |
| 复杂 NAT 和路由 | iptables |
| 现代 Linux 内核(5.x+) | nftables |
| 容器 / 复杂规则 / 脚本 | nftables |
| 维护老系统 | iptables |
| 配合面板统一托管 | ufw(由 1Panel / 宝塔托管) |
| 云服务器 | 安全组 + 系统防火墙(双重防护) |
同一台机器不要同时启用 ufw 和 firewalld,两套规则叠加之后难以排查。新系统直接学 nftables,iptables 属于历史包袱。
B. 批量安全加固脚本
#!/bin/bash
# quick-hardening.sh - 快速安全加固(适用于新服务器)
set -e
echo "[1/6] 更新系统..."
apt update && apt upgrade -y
echo "[2/6] 配置 UFW..."
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow 22222/tcp # 修改后的 SSH 端口
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
echo "[3/6] 加固 SSH..."
sed -i 's/#Port 22/Port 22222/' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
echo "MaxAuthTries 3" >> /etc/ssh/sshd_config
systemctl restart sshd
echo "[4/6] 安装 fail2ban..."
apt install -y fail2ban
cat > /etc/fail2ban/jail.local <<EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
[sshd]
enabled = true
port = 22222
EOF
systemctl enable fail2ban
systemctl start fail2ban
echo "[5/6] 内核安全参数..."
cat >> /etc/sysctl.conf <<EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
EOF
sysctl -p
echo "[6/6] 启用自动安全更新..."
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
echo "安全加固完成!"
echo "请确保 SSH 密钥已配置,然后尝试用新端口 22222 连接。"C. 实用经验
- 先放行 SSH 再启用防火墙,否则自己把管理通道封掉。
- 改 SSH 端口务必同步加防火墙规则,否则改完新连接进不来。
- Docker 容器端口对外可达由 Docker 自己写入的规则决定,要限制对外暴露,改 docker-compose 的 ports 写法(绑定 127.0.0.1)。
- fail2ban 封禁直接写 iptables,看封禁状态用
fail2ban-client status sshd。 - 配置文件写了 deny 只能证明规则文本存在,生效与否要分别从本机、内网和外部地址实测。
按实际包路径验证规则
主机入站、转发和容器端口发布可能经过不同规则链。按Docker 防火墙交互说明核对实际后端,再分别从本机、内网和外部地址测试。配置文件写了 deny,只能证明规则文本存在。
先允许管理来源,再以第二个 SSH 会话验证,保留恢复通道。对 IPv4 与 IPv6 分别检查默认策略和监听地址,避免只关闭一条访问路径。
← 返回文章