8.1 iptables 日志基础
LOG 目标详解
LOG 目标是 iptables 中用于记录数据包信息的非终止目标,它不会改变数据包的处理流程,只是记录匹配的数据包信息到系统日志中。
LOG 目标的基本语法
# 基本 LOG 语法
iptables -A chain -match_conditions -j LOG [log_options]
# LOG 选项
--log-level level # 日志级别(0-7)
--log-prefix "prefix" # 日志前缀(最多29个字符)
--log-tcp-sequence # 记录 TCP 序列号
--log-tcp-options # 记录 TCP 选项
--log-ip-options # 记录 IP 选项
--log-uid # 记录发送进程的 UID
日志级别说明
# 日志级别对应关系
0 = emerg # 系统不可用
1 = alert # 需要立即处理
2 = crit # 严重错误
3 = err # 一般错误
4 = warning # 警告信息
5 = notice # 正常但重要的信息
6 = info # 一般信息
7 = debug # 调试信息
# 默认级别是 warning (4)
基本日志记录配置
1. 简单日志记录
# 记录所有被拒绝的连接
iptables -A INPUT -j LOG --log-prefix "[INPUT-DENIED]: "
iptables -A INPUT -j DROP
# 记录转发被拒绝的数据包
iptables -A FORWARD -j LOG --log-prefix "[FORWARD-DENIED]: "
iptables -A FORWARD -j DROP
# 记录特定端口的访问
iptables -A INPUT -p tcp --dport 22 -j LOG --log-prefix "[SSH-ACCESS]: "
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
2. 详细日志记录
# 记录 TCP 连接的详细信息
iptables -A INPUT -p tcp --syn -j LOG --log-prefix "[TCP-SYN]: " --log-tcp-sequence --log-tcp-options
# 记录 UDP 流量
iptables -A INPUT -p udp -j LOG --log-prefix "[UDP-TRAFFIC]: " --log-ip-options
# 记录 ICMP 流量
iptables -A INPUT -p icmp -j LOG --log-prefix "[ICMP-TRAFFIC]: " --log-level info
3. 条件日志记录
# 只记录来自特定网段的流量
iptables -A INPUT -s 192.168.1.0/24 -j LOG --log-prefix "[INTERNAL-TRAFFIC]: "
# 记录高频访问(可能的攻击)
iptables -A INPUT -p tcp --dport 80 -m limit --limit 10/min --limit-burst 20 -j LOG --log-prefix "[HTTP-HIGH-FREQ]: "
# 记录端口扫描
iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j LOG --log-prefix "[PORT-SCAN]: "
8.2 日志配置和管理
rsyslog 配置
1. 基本 rsyslog 配置
# 编辑 rsyslog 配置文件
vim /etc/rsyslog.conf
# 添加 iptables 日志配置
# 将 kern.warning 级别的日志写入 iptables.log
kern.warning /var/log/iptables.log
# 或者更具体的配置
:msg,contains,"[INPUT-DENIED]" /var/log/iptables-input.log
:msg,contains,"[FORWARD-DENIED]" /var/log/iptables-forward.log
:msg,contains,"[SSH-ACCESS]" /var/log/iptables-ssh.log
# 重启 rsyslog 服务
systemctl restart rsyslog
2. 高级 rsyslog 配置
# 创建专门的 iptables 日志配置文件
vim /etc/rsyslog.d/10-iptables.conf
# 内容如下:
# iptables 日志分类配置
:msg,contains,"[INPUT-DENIED]" /var/log/iptables/input-denied.log
:msg,contains,"[FORWARD-DENIED]" /var/log/iptables/forward-denied.log
:msg,contains,"[OUTPUT-DENIED]" /var/log/iptables/output-denied.log
:msg,contains,"[SSH-ACCESS]" /var/log/iptables/ssh-access.log
:msg,contains,"[HTTP-ACCESS]" /var/log/iptables/http-access.log
:msg,contains,"[PORT-SCAN]" /var/log/iptables/port-scan.log
:msg,contains,"[DDoS-ATTACK]" /var/log/iptables/ddos-attack.log
# 停止进一步处理这些消息
:msg,contains,"[INPUT-DENIED]" stop
:msg,contains,"[FORWARD-DENIED]" stop
:msg,contains,"[OUTPUT-DENIED]" stop
:msg,contains,"[SSH-ACCESS]" stop
:msg,contains,"[HTTP-ACCESS]" stop
:msg,contains,"[PORT-SCAN]" stop
:msg,contains,"[DDoS-ATTACK]" stop
# 创建日志目录
mkdir -p /var/log/iptables
# 重启 rsyslog
systemctl restart rsyslog
3. 日志轮转配置
# 创建 logrotate 配置文件
vim /etc/logrotate.d/iptables
# 内容如下:
/var/log/iptables/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0644 root root
postrotate
/bin/systemctl reload rsyslog > /dev/null 2>&1 || true
endrotate
}
/var/log/iptables.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0644 root root
postrotate
/bin/systemctl reload rsyslog > /dev/null 2>&1 || true
endrotate
}
# 测试 logrotate 配置
logrotate -d /etc/logrotate.d/iptables
日志性能优化
1. 限制日志频率
# 使用 limit 模块限制日志频率
iptables -A INPUT -m limit --limit 5/min --limit-burst 10 -j LOG --log-prefix "[INPUT-DENIED]: "
iptables -A INPUT -j DROP
# 使用 hashlimit 模块按源 IP 限制
iptables -A INPUT -m hashlimit --hashlimit-above 10/min --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name ddos -j LOG --log-prefix "[DDoS-ATTACK]: "
iptables -A INPUT -m hashlimit --hashlimit-above 10/min --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name ddos -j DROP
# 使用 recent 模块记录重复攻击
iptables -A INPUT -m recent --name attackers --rcheck --seconds 60 --hitcount 10 -j LOG --log-prefix "[REPEAT-ATTACK]: "
iptables -A INPUT -m recent --name attackers --rcheck --seconds 60 --hitcount 10 -j DROP
iptables -A INPUT -m recent --name attackers --set
2. 选择性日志记录
# 只记录外网访问
iptables -A INPUT -i eth0 -j LOG --log-prefix "[EXTERNAL-ACCESS]: "
# 只记录特定端口
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j LOG --log-prefix "[IMPORTANT-PORTS]: "
# 只记录新连接
iptables -A INPUT -m state --state NEW -j LOG --log-prefix "[NEW-CONNECTION]: "
# 不记录内网流量
iptables -A INPUT ! -s 192.168.0.0/16 -j LOG --log-prefix "[NON-INTERNAL]: "
8.3 ULOG 和 NFLOG
ULOG 目标(已废弃)
ULOG 是较老的用户空间日志记录机制,现在已被 NFLOG 替代。
# ULOG 示例(不推荐使用)
iptables -A INPUT -j ULOG --ulog-nlgroup 1 --ulog-prefix "INPUT: "
NFLOG 目标
NFLOG 是现代的用户空间日志记录机制,提供更好的性能和功能。
1. NFLOG 基本配置
# 基本 NFLOG 语法
iptables -A INPUT -j NFLOG --nflog-group group_id --nflog-prefix "prefix"
# 示例配置
iptables -A INPUT -p tcp --dport 22 -j NFLOG --nflog-group 1 --nflog-prefix "SSH: "
iptables -A INPUT -p tcp --dport 80 -j NFLOG --nflog-group 2 --nflog-prefix "HTTP: "
iptables -A INPUT -p tcp --dport 443 -j NFLOG --nflog-group 3 --nflog-prefix "HTTPS: "
# NFLOG 选项
--nflog-group group_id # 指定 netlink 组 ID(0-65535)
--nflog-prefix "prefix" # 日志前缀
--nflog-range size # 复制到用户空间的数据包大小
--nflog-threshold count # 批量发送的数据包数量
2. 使用 ulogd2 处理 NFLOG
# 安装 ulogd2
apt-get install ulogd2 # Ubuntu/Debian
yum install ulogd # CentOS/RHEL
# 配置 ulogd2
vim /etc/ulogd.conf
# 基本配置示例
[global]
loglevel=5
rmem=131071
bufsize=150000
# NFLOG 输入插件
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inppkt_NFLOG.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_raw2packet_BASE.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inpflow_NFCT.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IFINDEX.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IP2STR.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_PRINTPKT.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_LOGEMU.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_SYSLOG.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_MYSQL.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_PGSQL.so"
plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_SQLITE3.so"
# 堆栈配置
stack=log1:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU
stack=log2:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,sys1:SYSLOG
# NFLOG 输入配置
[log1]
group=1
[log2]
group=2
# 输出配置
[emu1]
file="/var/log/ulogd/ulogd.log"
sync=1
[sys1]
facility=LOG_LOCAL0
level=LOG_INFO
# 启动 ulogd2
systemctl enable ulogd2
systemctl start ulogd2
8.4 实时监控和分析
实时日志监控
1. 使用 tail 实时查看日志
# 实时查看 iptables 日志
tail -f /var/log/iptables.log
# 实时查看特定类型的日志
tail -f /var/log/iptables.log | grep "SSH-ACCESS"
# 多文件同时监控
tail -f /var/log/iptables/*.log
# 彩色输出
tail -f /var/log/iptables.log | grep --color=always "DENIED\|ACCEPT\|DROP"
2. 使用 journalctl 查看日志
# 查看 iptables 相关的系统日志
journalctl -f | grep iptables
# 查看内核日志
journalctl -f -k | grep "\[INPUT-DENIED\]\|\[FORWARD-DENIED\]"
# 查看特定时间段的日志
journalctl --since "2024-01-01 00:00:00" --until "2024-01-01 23:59:59" | grep iptables
# 查看特定服务的日志
journalctl -u iptables -f
3. 自定义监控脚本
#!/bin/bash
# iptables 实时监控脚本
LOG_FILE="/var/log/iptables.log"
ALERT_EMAIL="admin@example.com"
THRESHOLD=100
# 监控函数
monitor_attacks() {
local count=$(tail -n 1000 $LOG_FILE | grep "$(date '+%b %d %H:%M')" | grep "DENIED" | wc -l)
if [ $count -gt $THRESHOLD ]; then
echo "ALERT: High number of denied connections: $count" | mail -s "iptables Alert" $ALERT_EMAIL
# 自动封禁攻击 IP
tail -n 1000 $LOG_FILE | grep "$(date '+%b %d %H:%M')" | grep "DENIED" | \
grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq -c | sort -nr | head -10 | \
while read count ip; do
if [ $count -gt 10 ]; then
iptables -I INPUT -s $ip -j DROP
echo "Blocked IP: $ip (count: $count)"
fi
done
fi
}
# 分析端口扫描
analyze_port_scan() {
local scan_ips=$(tail -n 1000 $LOG_FILE | grep "PORT-SCAN" | \
grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq -c | sort -nr)
if [ -n "$scan_ips" ]; then
echo "Port scan detected from:"
echo "$scan_ips"
# 自动封禁扫描 IP
echo "$scan_ips" | while read count ip; do
if [ $count -gt 5 ]; then
iptables -I INPUT -s $ip -j DROP
echo "Blocked scanning IP: $ip"
fi
done
fi
}
# 主循环
while true; do
monitor_attacks
analyze_port_scan
sleep 60
done
日志分析工具
1. 基本统计分析
#!/bin/bash
# iptables 日志分析脚本
LOG_FILE="/var/log/iptables.log"
echo "=== iptables 日志分析报告 ==="
echo "分析时间: $(date)"
echo "日志文件: $LOG_FILE"
echo
# 总体统计
echo "=== 总体统计 ==="
echo "总日志条数: $(wc -l < $LOG_FILE)"
echo "今日日志条数: $(grep "$(date '+%b %d')" $LOG_FILE | wc -l)"
echo "最近1小时日志条数: $(grep "$(date '+%b %d %H:')" $LOG_FILE | wc -l)"
echo
# 按类型统计
echo "=== 按类型统计 ==="
echo "INPUT 拒绝: $(grep "INPUT-DENIED" $LOG_FILE | wc -l)"
echo "FORWARD 拒绝: $(grep "FORWARD-DENIED" $LOG_FILE | wc -l)"
echo "SSH 访问: $(grep "SSH-ACCESS" $LOG_FILE | wc -l)"
echo "HTTP 访问: $(grep "HTTP-ACCESS" $LOG_FILE | wc -l)"
echo "端口扫描: $(grep "PORT-SCAN" $LOG_FILE | wc -l)"
echo
# 按源 IP 统计
echo "=== 前10个源 IP ==="
grep -oE 'SRC=[0-9.]+' $LOG_FILE | cut -d= -f2 | sort | uniq -c | sort -nr | head -10
echo
# 按目标端口统计
echo "=== 前10个目标端口 ==="
grep -oE 'DPT=[0-9]+' $LOG_FILE | cut -d= -f2 | sort | uniq -c | sort -nr | head -10
echo
# 按协议统计
echo "=== 按协议统计 ==="
grep -oE 'PROTO=[A-Z]+' $LOG_FILE | cut -d= -f2 | sort | uniq -c | sort -nr
echo
# 按时间统计
echo "=== 按小时统计(今日) ==="
for hour in {00..23}; do
count=$(grep "$(date '+%b %d') $hour:" $LOG_FILE | wc -l)
printf "%s:00 - %4d 条\n" $hour $count
done
echo
# 可疑活动检测
echo "=== 可疑活动检测 ==="
echo "高频访问 IP (>100次):"
grep -oE 'SRC=[0-9.]+' $LOG_FILE | cut -d= -f2 | sort | uniq -c | sort -nr | awk '$1 > 100 {print $2 " (" $1 " 次)"}'
echo
echo "端口扫描活动:"
grep "PORT-SCAN" $LOG_FILE | grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq -c | sort -nr | head -5
echo
echo "DDoS 攻击迹象:"
grep "DDoS-ATTACK" $LOG_FILE | grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq -c | sort -nr | head -5
2. 高级分析脚本
#!/bin/bash
# 高级 iptables 日志分析
LOG_FILE="/var/log/iptables.log"
OUTPUT_DIR="/var/log/iptables-analysis"
DATE=$(date '+%Y%m%d')
mkdir -p $OUTPUT_DIR
# 生成 IP 地理位置信息
generate_geo_report() {
echo "=== IP 地理位置分析 ===" > $OUTPUT_DIR/geo-report-$DATE.txt
grep -oE 'SRC=[0-9.]+' $LOG_FILE | cut -d= -f2 | sort | uniq -c | sort -nr | head -20 | \
while read count ip; do
# 使用 geoiplookup 或 API 查询地理位置
location=$(geoiplookup $ip 2>/dev/null | cut -d: -f2 | tr -d ' ')
echo "$ip ($count 次) - $location" >> $OUTPUT_DIR/geo-report-$DATE.txt
done
}
# 生成攻击模式分析
generate_attack_pattern() {
echo "=== 攻击模式分析 ===" > $OUTPUT_DIR/attack-pattern-$DATE.txt
# 分析攻击时间模式
echo "按小时攻击分布:" >> $OUTPUT_DIR/attack-pattern-$DATE.txt
for hour in {00..23}; do
count=$(grep "$(date '+%b %d') $hour:" $LOG_FILE | grep "DENIED" | wc -l)
printf "%s:00 - %4d 次攻击\n" $hour $count >> $OUTPUT_DIR/attack-pattern-$DATE.txt
done
echo "" >> $OUTPUT_DIR/attack-pattern-$DATE.txt
# 分析攻击端口模式
echo "攻击端口分布:" >> $OUTPUT_DIR/attack-pattern-$DATE.txt
grep "DENIED" $LOG_FILE | grep -oE 'DPT=[0-9]+' | cut -d= -f2 | sort | uniq -c | sort -nr | head -20 >> $OUTPUT_DIR/attack-pattern-$DATE.txt
echo "" >> $OUTPUT_DIR/attack-pattern-$DATE.txt
# 分析攻击协议模式
echo "攻击协议分布:" >> $OUTPUT_DIR/attack-pattern-$DATE.txt
grep "DENIED" $LOG_FILE | grep -oE 'PROTO=[A-Z]+' | cut -d= -f2 | sort | uniq -c | sort -nr >> $OUTPUT_DIR/attack-pattern-$DATE.txt
}
# 生成威胁情报报告
generate_threat_intel() {
echo "=== 威胁情报分析 ===" > $OUTPUT_DIR/threat-intel-$DATE.txt
# 提取攻击 IP
grep "DENIED" $LOG_FILE | grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq > $OUTPUT_DIR/attack-ips-$DATE.txt
# 检查是否在已知恶意 IP 列表中
if [ -f "/etc/iptables/malicious-ips.txt" ]; then
echo "已知恶意 IP 匹配:" >> $OUTPUT_DIR/threat-intel-$DATE.txt
comm -12 <(sort $OUTPUT_DIR/attack-ips-$DATE.txt) <(sort /etc/iptables/malicious-ips.txt) >> $OUTPUT_DIR/threat-intel-$DATE.txt
fi
# 生成建议封禁的 IP 列表
echo "" >> $OUTPUT_DIR/threat-intel-$DATE.txt
echo "建议封禁的 IP (攻击次数 > 50):" >> $OUTPUT_DIR/threat-intel-$DATE.txt
grep "DENIED" $LOG_FILE | grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq -c | sort -nr | awk '$1 > 50 {print $2}' >> $OUTPUT_DIR/threat-intel-$DATE.txt
}
# 生成性能分析报告
generate_performance_report() {
echo "=== 性能分析报告 ===" > $OUTPUT_DIR/performance-$DATE.txt
# 规则匹配统计
echo "规则匹配统计:" >> $OUTPUT_DIR/performance-$DATE.txt
iptables -L -n -v | grep -E "Chain|pkts" >> $OUTPUT_DIR/performance-$DATE.txt
echo "" >> $OUTPUT_DIR/performance-$DATE.txt
# NAT 表统计
echo "NAT 表统计:" >> $OUTPUT_DIR/performance-$DATE.txt
iptables -t nat -L -n -v | grep -E "Chain|pkts" >> $OUTPUT_DIR/performance-$DATE.txt
echo "" >> $OUTPUT_DIR/performance-$DATE.txt
# 连接跟踪统计
echo "连接跟踪统计:" >> $OUTPUT_DIR/performance-$DATE.txt
if [ -f "/proc/net/stat/nf_conntrack" ]; then
cat /proc/net/stat/nf_conntrack >> $OUTPUT_DIR/performance-$DATE.txt
fi
echo "" >> $OUTPUT_DIR/performance-$DATE.txt
echo "当前连接数: $(cat /proc/net/nf_conntrack | wc -l)" >> $OUTPUT_DIR/performance-$DATE.txt
echo "最大连接数: $(cat /proc/sys/net/netfilter/nf_conntrack_max)" >> $OUTPUT_DIR/performance-$DATE.txt
}
# 执行所有分析
echo "开始生成 iptables 分析报告..."
generate_geo_report
generate_attack_pattern
generate_threat_intel
generate_performance_report
echo "分析报告已生成到 $OUTPUT_DIR"
echo "报告文件:"
ls -la $OUTPUT_DIR/*-$DATE.txt
8.5 监控工具集成
与 Nagios 集成
1. Nagios 插件脚本
#!/bin/bash
# check_iptables_log.sh - Nagios 插件
LOG_FILE="/var/log/iptables.log"
WARNING_THRESHOLD=100
CRITICAL_THRESHOLD=500
TIME_WINDOW=5 # 分钟
# 获取最近 N 分钟的攻击次数
attack_count=$(grep "$(date -d "$TIME_WINDOW minutes ago" '+%b %d %H:%M')" $LOG_FILE | grep "DENIED" | wc -l)
# 检查阈值
if [ $attack_count -ge $CRITICAL_THRESHOLD ]; then
echo "CRITICAL - $attack_count attacks in last $TIME_WINDOW minutes"
exit 2
elif [ $attack_count -ge $WARNING_THRESHOLD ]; then
echo "WARNING - $attack_count attacks in last $TIME_WINDOW minutes"
exit 1
else
echo "OK - $attack_count attacks in last $TIME_WINDOW minutes"
exit 0
fi
2. Nagios 配置
# 在 Nagios 配置中添加
# /etc/nagios/objects/commands.cfg
define command {
command_name check_iptables_attacks
command_line /usr/local/nagios/libexec/check_iptables_log.sh
}
# /etc/nagios/objects/services.cfg
define service {
use generic-service
host_name firewall-server
service_description iptables Attacks
check_command check_iptables_attacks
check_interval 5
retry_interval 1
max_check_attempts 3
}
与 Zabbix 集成
1. Zabbix 用户参数
# 在 zabbix_agentd.conf 中添加
UserParameter=iptables.attacks[*],grep "$1" /var/log/iptables.log | grep "DENIED" | wc -l
UserParameter=iptables.connections,cat /proc/net/nf_conntrack | wc -l
UserParameter=iptables.rules.count,iptables -L | grep -c "^Chain"
UserParameter=iptables.dropped.packets,iptables -L -n -v | awk '/DROP/ {sum += $1} END {print sum+0}'
2. Zabbix 监控脚本
#!/bin/bash
# zabbix_iptables_discovery.sh
# 发现 iptables 链
echo '{"data":['
iptables -L | grep "^Chain" | awk '{print $2}' | while read chain; do
echo '{"#{#CHAIN}":"'$chain'"},'
done | sed 's/,$/'
echo ']}'
与 Prometheus 集成
1. iptables_exporter
#!/usr/bin/env python3
# iptables_exporter.py
import subprocess
import time
import re
from prometheus_client import start_http_server, Gauge, Counter
# 定义指标
iptables_rules_total = Gauge('iptables_rules_total', 'Total number of iptables rules')
iptables_packets_total = Counter('iptables_packets_total', 'Total packets processed', ['chain', 'target'])
iptables_bytes_total = Counter('iptables_bytes_total', 'Total bytes processed', ['chain', 'target'])
iptables_connections_current = Gauge('iptables_connections_current', 'Current number of tracked connections')
def collect_iptables_metrics():
# 收集规则统计
try:
output = subprocess.check_output(['iptables', '-L', '-n', '-v'], universal_newlines=True)
# 解析输出
for line in output.split('\n'):
if re.match(r'^\s*\d+', line):
parts = line.split()
if len(parts) >= 3:
packets = int(parts[0])
bytes_count = int(parts[1])
target = parts[2]
# 更新指标(这里简化处理)
iptables_packets_total.labels(chain='INPUT', target=target)._value._value = packets
iptables_bytes_total.labels(chain='INPUT', target=target)._value._value = bytes_count
# 收集连接跟踪信息
with open('/proc/net/nf_conntrack', 'r') as f:
connections = len(f.readlines())
iptables_connections_current.set(connections)
except Exception as e:
print(f"Error collecting metrics: {e}")
def main():
# 启动 HTTP 服务器
start_http_server(8000)
while True:
collect_iptables_metrics()
time.sleep(30)
if __name__ == '__main__':
main()
2. Prometheus 配置
# prometheus.yml
scrape_configs:
- job_name: 'iptables'
static_configs:
- targets: ['localhost:8000']
scrape_interval: 30s
3. Grafana 仪表板
{
"dashboard": {
"title": "iptables Monitoring",
"panels": [
{
"title": "Packet Rate",
"type": "graph",
"targets": [
{
"expr": "rate(iptables_packets_total[5m])",
"legendFormat": "{{chain}} - {{target}}"
}
]
},
{
"title": "Current Connections",
"type": "singlestat",
"targets": [
{
"expr": "iptables_connections_current"
}
]
}
]
}
}
8.6 安全事件响应
自动响应脚本
1. 攻击检测和自动封禁
#!/bin/bash
# auto_block.sh - 自动攻击检测和封禁
LOG_FILE="/var/log/iptables.log"
BLOCK_LIST="/etc/iptables/blocked_ips.txt"
WHITE_LIST="/etc/iptables/whitelist.txt"
THRESHOLD=20
TIME_WINDOW=5 # 分钟
# 创建必要的文件
touch $BLOCK_LIST $WHITE_LIST
# 检测攻击函数
detect_attacks() {
local current_time=$(date '+%b %d %H:%M')
local window_start=$(date -d "$TIME_WINDOW minutes ago" '+%b %d %H:%M')
# 分析最近时间窗口内的攻击
grep "$current_time\|$window_start" $LOG_FILE | grep "DENIED" | \
grep -oE 'SRC=[0-9.]+' | cut -d= -f2 | sort | uniq -c | sort -nr | \
while read count ip; do
# 检查是否在白名单中
if grep -q "^$ip$" $WHITE_LIST; then
continue
fi
# 检查是否已经被封禁
if grep -q "^$ip$" $BLOCK_LIST; then
continue
fi
# 如果攻击次数超过阈值,则封禁
if [ $count -ge $THRESHOLD ]; then
echo "$(date): Blocking IP $ip (attack count: $count)" | tee -a /var/log/auto_block.log
# 添加 iptables 规则
iptables -I INPUT -s $ip -j DROP
# 记录到封禁列表
echo "$ip" >> $BLOCK_LIST
# 发送告警邮件
echo "IP $ip has been automatically blocked due to $count attacks in $TIME_WINDOW minutes." | \
mail -s "Auto Block Alert" admin@example.com
fi
done
}
# 清理过期封禁
cleanup_blocks() {
local temp_file=$(mktemp)
# 检查每个被封禁的 IP
while read ip; do
# 检查最近24小时是否还有攻击
local recent_attacks=$(grep "$(date '+%b %d')" $LOG_FILE | grep "DENIED" | grep "SRC=$ip" | wc -l)
if [ $recent_attacks -eq 0 ]; then
echo "$(date): Unblocking IP $ip (no recent attacks)" | tee -a /var/log/auto_block.log
# 删除 iptables 规则
iptables -D INPUT -s $ip -j DROP 2>/dev/null
else
echo "$ip" >> $temp_file
fi
done < $BLOCK_LIST
mv $temp_file $BLOCK_LIST
}
# 主循环
while true; do
detect_attacks
# 每小时清理一次过期封禁
if [ $(date '+%M') -eq 0 ]; then
cleanup_blocks
fi
sleep 60
done
2. DDoS 检测和缓解
#!/bin/bash
# ddos_protection.sh - DDoS 检测和缓解
LOG_FILE="/var/log/iptables.log"
DDOS_THRESHOLD=1000 # 每分钟连接数
SYN_FLOOD_THRESHOLD=100 # SYN 包阈值
# DDoS 检测函数
detect_ddos() {
local current_minute=$(date '+%b %d %H:%M')
# 检测连接洪水
local connection_count=$(grep "$current_minute" $LOG_FILE | grep "NEW" | wc -l)
if [ $connection_count -gt $DDOS_THRESHOLD ]; then
echo "$(date): DDoS attack detected - $connection_count connections per minute"
# 启用 DDoS 防护规则
enable_ddos_protection
# 发送告警
echo "DDoS attack detected with $connection_count connections per minute" | \
mail -s "DDoS Alert" admin@example.com
fi
# 检测 SYN 洪水攻击
local syn_count=$(grep "$current_minute" $LOG_FILE | grep "SYN" | wc -l)
if [ $syn_count -gt $SYN_FLOOD_THRESHOLD ]; then
echo "$(date): SYN flood attack detected - $syn_count SYN packets per minute"
# 启用 SYN flood 防护
enable_syn_flood_protection
fi
}
# 启用 DDoS 防护
enable_ddos_protection() {
echo "Enabling DDoS protection..."
# 限制新连接速率
iptables -I INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
iptables -I INPUT -p tcp --syn -j DROP
# 限制 ICMP
iptables -I INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT
iptables -I INPUT -p icmp -j DROP
# 限制每个 IP 的连接数
iptables -I INPUT -p tcp --syn -m connlimit --connlimit-above 10 -j DROP
echo "DDoS protection enabled"
}
# 启用 SYN flood 防护
enable_syn_flood_protection() {
echo "Enabling SYN flood protection..."
# 启用 SYN cookies
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# 调整 SYN 队列大小
echo 2048 > /proc/sys/net/ipv4/tcp_max_syn_backlog
# 减少 SYN-ACK 重试次数
echo 3 > /proc/sys/net/ipv4/tcp_synack_retries
echo "SYN flood protection enabled"
}
# 禁用 DDoS 防护
disable_ddos_protection() {
echo "Disabling DDoS protection..."
# 删除临时规则
iptables -D INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT 2>/dev/null
iptables -D INPUT -p tcp --syn -j DROP 2>/dev/null
iptables -D INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT 2>/dev/null
iptables -D INPUT -p icmp -j DROP 2>/dev/null
iptables -D INPUT -p tcp --syn -m connlimit --connlimit-above 10 -j DROP 2>/dev/null
echo "DDoS protection disabled"
}
# 主循环
while true; do
detect_ddos
sleep 60
done
事件通知系统
1. 邮件通知脚本
#!/bin/bash
# notify_security_event.sh
EMAIL="admin@example.com"
SMS_API="https://api.sms-service.com/send"
SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
# 发送邮件通知
send_email() {
local subject="$1"
local message="$2"
echo "$message" | mail -s "$subject" $EMAIL
}
# 发送 SMS 通知
send_sms() {
local message="$1"
curl -X POST $SMS_API \
-d "to=+1234567890" \
-d "message=$message"
}
# 发送 Slack 通知
send_slack() {
local message="$1"
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"$message\"}" \
$SLACK_WEBHOOK
}
# 综合通知函数
notify_security_event() {
local event_type="$1"
local details="$2"
local severity="$3"
local subject="Security Alert: $event_type"
local message="Security Event Detected\n\nType: $event_type\nSeverity: $severity\nTime: $(date)\nDetails: $details"
# 根据严重程度选择通知方式
case $severity in
"CRITICAL")
send_email "$subject" "$message"
send_sms "CRITICAL: $event_type detected"
send_slack "🚨 CRITICAL: $event_type detected at $(date)"
;;
"HIGH")
send_email "$subject" "$message"
send_slack "⚠️ HIGH: $event_type detected at $(date)"
;;
"MEDIUM")
send_email "$subject" "$message"
;;
"LOW")
send_slack "ℹ️ LOW: $event_type detected at $(date)"
;;
esac
}
# 示例使用
# notify_security_event "Port Scan" "Multiple port scan attempts from 192.168.1.100" "HIGH"
本章小结
本章详细介绍了 iptables 的日志记录和监控功能:
- 日志基础:LOG 和 NFLOG 目标的使用方法
- 日志配置:rsyslog 配置、日志轮转和性能优化
- 实时监控:日志监控工具和自定义脚本
- 日志分析:统计分析和威胁情报生成
- 监控集成:与 Nagios、Zabbix、Prometheus 的集成
- 安全响应:自动攻击检测、DDoS 防护和事件通知
本章练习
基础练习:
- 配置基本的日志记录规则
- 设置 rsyslog 日志分类
- 编写简单的日志分析脚本
进阶练习:
- 配置 NFLOG 和 ulogd2
- 实现实时攻击检测
- 集成监控系统
实战练习:
- 搭建完整的日志监控系统
- 实现自动安全响应
- 配置多渠道告警通知
分析练习:
- 分析真实的攻击日志
- 生成安全分析报告
- 优化日志记录性能
下一章我们将学习 iptables 的性能优化技巧。