33. 访问控制
33.1 基于IP的访问控制
33.1.1 防火墙白名单
仅允许特定IP连接:
#!/bin/bash
# setup-ip-whitelist.sh
# 允许的IP列表
ALLOWED_IPS=(
"203.0.113.10" # 办公室
"198.51.100.0/24" # 分支机构网段
"192.0.2.50" # 家庭网络
)
echo "=== 配置IP白名单 ==="
# 1. 设置默认策略(拒绝所有)
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
# 2. 允许已建立的连接
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# 3. 允许本地回环
sudo iptables -A INPUT -i lo -j ACCEPT
# 4. 添加白名单IP
echo "添加允许的IP..."
for ip in "${ALLOWED_IPS[@]}"; do
echo " 允许: $ip"
sudo iptables -A INPUT -p udp --dport 51820 -s $ip -j ACCEPT
done
# 5. 记录被拒绝的连接
sudo iptables -A INPUT -p udp --dport 51820 -j LOG --log-prefix "WG-BLOCKED: "
sudo iptables -A INPUT -p udp --dport 51820 -j DROP
# 6. 保存规则
sudo netfilter-persistent save
echo ""
echo "✓ IP白名单配置完成"
echo ""
echo "当前规则:"
sudo iptables -L INPUT -n -v --line-numbers | grep 51820
33.1.2 地理位置限制
使用GeoIP限制连接:
#!/bin/bash
# setup-geoip-blocking.sh
echo "=== 配置地理位置限制 ==="
# 1. 安装GeoIP模块
echo "[1] 安装GeoIP..."
sudo apt install -y xtables-addons-common libtext-csv-xs-perl
# 2. 下载GeoIP数据库
echo ""
echo "[2] 下载GeoIP数据库..."
sudo mkdir -p /usr/share/xt_geoip
cd /usr/share/xt_geoip
# 下载数据
sudo wget https://download.db-ip.com/free/dbip-country-lite-$(date +%Y-%m).csv.gz
sudo gunzip dbip-country-lite-*.csv.gz
# 转换数据
sudo /usr/lib/xtables-addons/xt_geoip_build -D . dbip-country-lite-*.csv
# 3. 配置iptables规则
echo ""
echo "[3] 配置规则..."
# 仅允许中国IP连接(示例)
sudo iptables -A INPUT -p udp --dport 51820 -m geoip --src-cc CN -j ACCEPT
# 拒绝其他国家
sudo iptables -A INPUT -p udp --dport 51820 -j LOG --log-prefix "GEOIP-BLOCK: "
sudo iptables -A INPUT -p udp --dport 51820 -j DROP
# 4. 保存规则
sudo netfilter-persistent save
echo ""
echo "✓ 地理位置限制配置完成"
查看被阻止的连接:
# 查看日志
sudo journalctl -k | grep "GEOIP-BLOCK"
# 实时监控
sudo tail -f /var/log/kern.log | grep "GEOIP-BLOCK"
33.2 端口敲门
33.2.1 配置knockd
安装和配置:
# 安装knockd
sudo apt install -y knockd
# 配置knockd
sudo nano /etc/knockd.conf
配置内容:
[options]
UseSyslog
[openWireGuard]
sequence = 7000,8000,9000
seq_timeout = 15
command = /usr/sbin/iptables -I INPUT -s %IP% -p udp --dport 51820 -j ACCEPT
tcpflags = syn
[closeWireGuard]
sequence = 9000,8000,7000
seq_timeout = 15
command = /usr/sbin/iptables -D INPUT -s %IP% -p udp --dport 51820 -j ACCEPT
tcpflags = syn
启用服务:
# 修改配置启用knockd
sudo nano /etc/default/knockd
# 设置
START_KNOCKD=1
# 启动服务
sudo systemctl enable knockd
sudo systemctl start knockd
客户端使用:
# 发送敲门序列(开启)
knock server.example.com 7000 8000 9000
# 连接WireGuard
wg-quick up wg0
# 发送关闭序列(可选)
knock server.example.com 9000 8000 7000
33.2.2 端口跳跃
动态端口脚本:
#!/bin/bash
# port-hopping.sh
# 端口池
PORTS=(51820 41194 33891 28765 19283)
# 当前端口索引文件
INDEX_FILE="/var/run/wireguard-port-index"
# 读取当前索引
if [ -f "$INDEX_FILE" ]; then
CURRENT_INDEX=$(cat $INDEX_FILE)
else
CURRENT_INDEX=0
fi
# 计算下一个索引
NEXT_INDEX=$(( (CURRENT_INDEX + 1) % ${#PORTS[@]} ))
NEW_PORT=${PORTS[$NEXT_INDEX]}
echo "=== 端口跳跃 ==="
echo "当前端口: ${PORTS[$CURRENT_INDEX]}"
echo "新端口: $NEW_PORT"
# 1. 停止WireGuard
sudo wg-quick down wg0
# 2. 修改配置
sudo sed -i "s/ListenPort = .*/ListenPort = $NEW_PORT/" /etc/wireguard/wg0.conf
# 3. 更新防火墙
sudo ufw delete allow ${PORTS[$CURRENT_INDEX]}/udp
sudo ufw allow $NEW_PORT/udp
# 4. 启动WireGuard
sudo wg-quick up wg0
# 5. 保存新索引
echo $NEXT_INDEX > $INDEX_FILE
echo "✓ 端口已更换为: $NEW_PORT"
# 通知客户端(需要实现)
# send_notification_to_clients $NEW_PORT
定时端口跳跃:
# 每小时更换端口
0 * * * * /usr/local/bin/port-hopping.sh >> /var/log/port-hopping.log 2>&1
33.3 fail2ban集成
33.3.1 安装配置fail2ban
安装fail2ban:
sudo apt install -y fail2ban
创建WireGuard过滤器:
sudo nano /etc/fail2ban/filter.d/wireguard.conf
内容:
[Definition]
# 匹配WireGuard认证失败
failregex = ^.*WireGuard.*Invalid handshake.*from <HOST>.*$
^.*wireguard.*authentication failed.*<HOST>.*$
^.*wg0.*handshake.*failed.*<HOST>.*$
ignoreregex =
创建jail配置:
sudo nano /etc/fail2ban/jail.d/wireguard.conf
内容:
[wireguard]
enabled = true
port = 51820
protocol = udp
filter = wireguard
logpath = /var/log/syslog
/var/log/kern.log
maxretry = 3
findtime = 600
bantime = 3600
action = iptables-allports[name=wireguard, protocol=all]
重启fail2ban:
sudo systemctl restart fail2ban
33.3.2 监控和管理
查看fail2ban状态:
# 查看所有jail状态
sudo fail2ban-client status
# 查看WireGuard jail详情
sudo fail2ban-client status wireguard
# 查看被禁IP列表
sudo fail2ban-client get wireguard banip
手动操作:
# 手动封禁IP
sudo fail2ban-client set wireguard banip 203.0.113.100
# 解除封禁
sudo fail2ban-client set wireguard unbanip 203.0.113.100
# 查看日志
sudo tail -f /var/log/fail2ban.log
33.4 多因素认证
33.4.1 使用预共享密钥
生成预共享密钥:
# 生成PSK
wg genpsk > preshared.key
# 查看PSK
cat preshared.key
服务器配置:
[Interface]
PrivateKey = <服务器私钥>
Address = 10.8.0.1/24
ListenPort = 51820
[Peer]
PublicKey = <客户端公钥>
PresharedKey = <从preshared.key读取>
AllowedIPs = 10.8.0.2/32
客户端配置:
[Interface]
PrivateKey = <客户端私钥>
Address = 10.8.0.2/24
[Peer]
PublicKey = <服务器公钥>
PresharedKey = <相同的PSK>
Endpoint = 192.168.1.66:51820
AllowedIPs = 10.8.0.0/24
批量添加PSK脚本:
#!/bin/bash
# add-psk-to-all-peers.sh
CONFIG_FILE="/etc/wireguard/wg0.conf"
BACKUP_FILE="${CONFIG_FILE}.bak.$(date +%Y%m%d_%H%M%S)"
echo "=== 为所有Peer添加PSK ==="
# 备份配置
sudo cp $CONFIG_FILE $BACKUP_FILE
echo "✓ 配置已备份: $BACKUP_FILE"
# 为每个peer生成PSK
sudo grep -n "^\[Peer\]" $CONFIG_FILE | while read line; do
line_num=$(echo $line | cut -d: -f1)
# 生成PSK
psk=$(wg genpsk)
# 插入PSK
sudo sed -i "${line_num}a PresharedKey = $psk" $CONFIG_FILE
echo "✓ Peer at line $line_num: PSK added"
done
# 重新加载
sudo wg syncconf wg0 <(wg-quick strip wg0)
echo ""
echo "✓ 所有Peer已添加PSK"
echo "备份文件: $BACKUP_file"
33.4.2 结合TOTP(时间基准一次性密码)
概念设计:
#!/bin/bash
# wireguard-totp-wrapper.sh
# 这是一个概念脚本,展示如何集成TOTP
# 实际实现需要额外开发
USERNAME=$1
TOTP_CODE=$2
if [ -z "$USERNAME" ] || [ -z "$TOTP_CODE" ]; then
echo "用法: $0 <用户名> <TOTP代码>"
exit 1
fi
# 验证TOTP
if ! verify_totp "$USERNAME" "$TOTP_CODE"; then
echo "✗ TOTP验证失败"
# 记录失败尝试
logger "WireGuard TOTP failed for user: $USERNAME"
exit 1
fi
echo "✓ TOTP验证成功"
# 临时允许用户连接(5分钟)
USER_IP=$(get_user_ip "$USERNAME")
sudo iptables -I INPUT -s $USER_IP -p udp --dport 51820 -j ACCEPT
# 5分钟后自动删除规则
(sleep 300; sudo iptables -D INPUT -s $USER_IP -p udp --dport 51820 -j ACCEPT) &
echo "✓ 已授权连接(5分钟)"
34. 密钥管理
34.1 密钥生成最佳实践
34.1.1 安全的密钥生成
使用强随机源:
#!/bin/bash
# secure-key-generation.sh
echo "=== 安全密钥生成 ==="
# 1. 检查随机源
echo "[1] 检查随机源..."
if [ -c /dev/urandom ]; then
echo "✓ /dev/urandom 可用"
else
echo "✗ /dev/urandom 不可用"
exit 1
fi
# 2. 检查熵池
echo ""
echo "[2] 检查系统熵..."
ENTROPY=$(cat /proc/sys/kernel/random/entropy_avail)
echo "可用熵: $ENTROPY"
if [ $ENTROPY -lt 1000 ]; then
echo "⚠ 警告: 熵较低,建议安装rng-tools"
echo "sudo apt install rng-tools"
fi
# 3. 生成密钥
echo ""
echo "[3] 生成密钥对..."
# 设置umask确保文件权限
umask 077
# 生成私钥
PRIVATE_KEY=$(wg genkey)
PUBLIC_KEY=$(echo $PRIVATE_KEY | wg pubkey)
# 保存到安全位置
KEY_DIR="/etc/wireguard/keys"
sudo mkdir -p $KEY_DIR
sudo chmod 700 $KEY_DIR
echo $PRIVATE_KEY | sudo tee $KEY_DIR/private.key > /dev/null
echo $PUBLIC_KEY | sudo tee $KEY_DIR/public.key > /dev/null
# 设置权限
sudo chmod 600 $KEY_DIR/private.key
sudo chmod 644 $KEY_DIR/public.key
sudo chown root:root $KEY_DIR/*.key
echo "✓ 密钥已生成"
echo ""
echo "私钥: $KEY_DIR/private.key"
echo "公钥: $KEY_DIR/public.key"
# 4. 验证密钥
echo ""
echo "[4] 验证密钥..."
if [ ${#PRIVATE_KEY} -eq 44 ] && [ ${#PUBLIC_KEY} -eq 44 ]; then
echo "✓ 密钥格式正确"
else
echo "✗ 密钥格式错误"
exit 1
fi
# 5. 记录密钥指纹
echo ""
echo "[5] 记录密钥指纹..."
FINGERPRINT=$(echo $PUBLIC_KEY | sha256sum | awk '{print $1}')
echo "公钥指纹: $FINGERPRINT"
{
echo "密钥生成记录"
echo "时间: $(date)"
echo "公钥: $PUBLIC_KEY"
echo "指纹: $FINGERPRINT"
} | sudo tee $KEY_DIR/keyinfo.txt > /dev/null
echo ""
echo "=== 生成完成 ==="
34.1.2 密钥强度验证
密钥质量检查:
#!/bin/bash
# validate-key-strength.sh
PRIVATE_KEY=$1
if [ -z "$PRIVATE_KEY" ]; then
echo "用法: $0 <私钥>"
exit 1
fi
echo "=== 密钥强度验证 ==="
# 1. 长度检查
echo "[1] 长度检查..."
if [ ${#PRIVATE_KEY} -eq 44 ]; then
echo "✓ 长度正确 (44字符)"
else
echo "✗ 长度错误: ${#PRIVATE_KEY}"
exit 1
fi
# 2. Base64验证
echo ""
echo "[2] Base64格式验证..."
if echo "$PRIVATE_KEY" | base64 -d > /dev/null 2>&1; then
echo "✓ 有效的Base64编码"
else
echo "✗ 无效的Base64编码"
exit 1
fi
# 3. 解码长度
echo ""
echo "[3] 解码后长度检查..."
DECODED_LEN=$(echo "$PRIVATE_KEY" | base64 -d | wc -c)
if [ $DECODED_LEN -eq 32 ]; then
echo "✓ 解码后长度正确 (32字节)"
else
echo "✗ 解码后长度错误: $DECODED_LEN"
exit 1
fi
# 4. 生成公钥测试
echo ""
echo "[4] 公钥生成测试..."
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | wg pubkey)
if [ ${#PUBLIC_KEY} -eq 44 ]; then
echo "✓ 可以生成有效公钥"
echo "公钥: ${PUBLIC_KEY:0:20}..."
else
echo "✗ 无法生成有效公钥"
exit 1
fi
echo ""
echo "=== 验证通过 ==="
34.2 密钥轮换
34.2.1 服务器密钥轮换
服务器密钥轮换流程:
#!/bin/bash
# rotate-server-keys.sh
echo "=== 服务器密钥轮换 ==="
CONFIG_FILE="/etc/wireguard/wg0.conf"
KEYS_DIR="/etc/wireguard/keys"
BACKUP_DIR="/var/backups/wireguard/key-rotation"
# 创建备份目录
sudo mkdir -p $BACKUP_DIR
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 1. 备份当前配置和密钥
echo "[1] 备份当前配置..."
sudo cp $CONFIG_FILE $BACKUP_DIR/wg0.conf.$TIMESTAMP
sudo cp -r $KEYS_DIR $BACKUP_DIR/keys.$TIMESTAMP
echo "✓ 备份完成"
# 2. 获取当前密钥
echo ""
echo "[2] 当前密钥信息..."
OLD_PRIVATE=$(sudo grep PrivateKey $CONFIG_FILE | awk '{print $3}')
OLD_PUBLIC=$(echo $OLD_PRIVATE | wg pubkey)
echo "旧公钥: ${OLD_PUBLIC:0:20}..."
# 3. 生成新密钥
echo ""
echo "[3] 生成新密钥..."
NEW_PRIVATE=$(wg genkey)
NEW_PUBLIC=$(echo $NEW_PRIVATE | wg pubkey)
echo "新公钥: ${NEW_PUBLIC:0:20}..."
# 保存新密钥
echo $NEW_PRIVATE | sudo tee $KEYS_DIR/server_private.key.new > /dev/null
echo $NEW_PUBLIC | sudo tee $KEYS_DIR/server_public.key.new > /dev/null
# 4. 更新服务器配置
echo ""
echo "[4] 更新服务器配置..."
sudo sed -i "s|PrivateKey = $OLD_PRIVATE|PrivateKey = $NEW_PRIVATE|" $CONFIG_FILE
echo "✓ 配置已更新"
# 5. 生成新的客户端配置
echo ""
echo "[5] 生成新的客户端配置..."
CLIENT_CONFIG_DIR="/etc/wireguard/clients"
NEW_CLIENT_DIR="/etc/wireguard/clients-new-keys"
sudo mkdir -p $NEW_CLIENT_DIR
for conf in $CLIENT_CONFIG_DIR/*.conf; do
if [ -f "$conf" ]; then
filename=$(basename "$conf")
# 替换服务器公钥
sudo sed "s|PublicKey = $OLD_PUBLIC|PublicKey = $NEW_PUBLIC|" "$conf" \
> "$NEW_CLIENT_DIR/$filename"
echo " ✓ 更新: $filename"
fi
done
# 6. 重启WireGuard
echo ""
echo "[6] 重启WireGuard..."
sudo systemctl restart wg-quick@wg0
if systemctl is-active --quiet wg-quick@wg0; then
echo "✓ WireGuard重启成功"
else
echo "✗ WireGuard重启失败"
echo "恢复旧配置..."
sudo cp $BACKUP_DIR/wg0.conf.$TIMESTAMP $CONFIG_FILE
sudo systemctl restart wg-quick@wg0
exit 1
fi
# 7. 验证
echo ""
echo "[7] 验证新密钥..."
CURRENT_PUBLIC=$(sudo wg show wg0 public-key)
if [ "$CURRENT_PUBLIC" = "$NEW_PUBLIC" ]; then
echo "✓ 新密钥已生效"
else
echo "✗ 密钥验证失败"
exit 1
fi
# 8. 移动新密钥
sudo mv $KEYS_DIR/server_private.key.new $KEYS_DIR/server_private.key
sudo mv $KEYS_DIR/server_public.key.new $KEYS_DIR/server_public.key
echo ""
echo "=== 密钥轮换完成 ==="
echo ""
echo "重要提示:"
echo "1. 新客户端配置位于: $NEW_CLIENT_DIR"
echo "2. 必须将新配置分发给所有客户端"
echo "3. 客户端更新后才能重新连接"
echo "4. 备份文件位于: $BACKUP_DIR"
echo ""
echo "旧公钥: $OLD_PUBLIC"
echo "新公钥: $NEW_PUBLIC"
34.2.2 客户端密钥轮换
单个客户端密钥轮换:
#!/bin/bash
# rotate-client-key.sh
USERNAME=$1
if [ -z "$USERNAME" ]; then
echo "用法: $0 <用户名>"
exit 1
fi
echo "=== 客户端密钥轮换: $USERNAME ==="
KEYS_DIR="/etc/wireguard/clients"
CONFIG_FILE="/etc/wireguard/wg0.conf"
# 1. 获取旧公钥
echo "[1] 获取当前密钥..."
OLD_PUBLIC=$(cat $KEYS_DIR/${USERNAME}_public.key 2>/dev/null)
if [ -z "$OLD_PUBLIC" ]; then
echo "✗ 用户不存在"
exit 1
fi
echo "旧公钥: ${OLD_PUBLIC:0:20}..."
# 2. 生成新密钥
echo ""
echo "[2] 生成新密钥..."
NEW_PRIVATE=$(wg genkey)
NEW_PUBLIC=$(echo $NEW_PRIVATE | wg pubkey)
# 备份旧密钥
sudo mv $KEYS_DIR/${USERNAME}_private.key \
$KEYS_DIR/${USERNAME}_private.key.old
sudo mv $KEYS_DIR/${USERNAME}_public.key \
$KEYS_DIR/${USERNAME}_public.key.old
# 保存新密钥
echo $NEW_PRIVATE | sudo tee $KEYS_DIR/${USERNAME}_private.key > /dev/null
echo $NEW_PUBLIC | sudo tee $KEYS_DIR/${USERNAME}_public.key > /dev/null
sudo chmod 600 $KEYS_DIR/${USERNAME}_private.key
echo "新公钥: ${NEW_PUBLIC:0:20}..."
# 3. 更新服务器配置
echo ""
echo "[3] 更新服务器配置..."
sudo sed -i "s|PublicKey = $OLD_PUBLIC|PublicKey = $NEW_PUBLIC|" $CONFIG_FILE
echo "✓ 配置已更新"
# 4. 重新加载
echo ""
echo "[4] 重新加载配置..."
sudo wg syncconf wg0 <(wg-quick strip wg0)
echo "✓ 配置已重新加载"
# 5. 生成新的客户端配置
echo ""
echo "[5] 生成新客户端配置..."
# 获取客户端IP
CLIENT_IP=$(sudo grep -B 5 "$NEW_PUBLIC" $CONFIG_FILE | grep AllowedIPs | awk '{print $3}' | cut -d'/' -f1)
# 服务器信息
SERVER_PUBLIC=$(sudo wg show wg0 public-key)
SERVER_ENDPOINT="192.168.1.66:51820"
# 生成配置
NEW_CONFIG="$KEYS_DIR/${USERNAME}_new.conf"
cat << EOF | sudo tee $NEW_CONFIG > /dev/null
[Interface]
PrivateKey = $NEW_PRIVATE
Address = $CLIENT_IP/24
DNS = 223.5.5.5, 114.114.114.114
[Peer]
PublicKey = $SERVER_PUBLIC
Endpoint = $SERVER_ENDPOINT
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
EOF
sudo chmod 600 $NEW_CONFIG
echo "✓ 新配置已生成: $NEW_CONFIG"
# 6. 显示配置
echo ""
echo "新客户端配置:"
echo "----------------------------------------"
cat $NEW_CONFIG
echo "----------------------------------------"
echo ""
echo "=== 轮换完成 ==="
echo "请将新配置发送给用户: $USERNAME"
34.3 密钥存储
34.3.1 加密存储
使用GPG加密密钥:
#!/bin/bash
# encrypt-keys.sh
echo "=== 加密WireGuard密钥 ==="
KEYS_DIR="/etc/wireguard"
ENCRYPTED_DIR="/root/wireguard-keys-encrypted"
# 创建加密目录
sudo mkdir -p $ENCRYPTED_DIR
# GPG密钥ID(需要预先生成)
GPG_KEY_ID="[email protected]"
# 加密所有密钥文件
echo "加密密钥文件..."
for keyfile in $KEYS_DIR/*.key; do
if [ -f "$keyfile" ]; then
filename=$(basename "$keyfile")
# 加密
sudo gpg --encrypt \
--recipient $GPG_KEY_ID \
--output $ENCRYPTED_DIR/${filename}.gpg \
$keyfile
echo "✓ 已加密: $filename"
fi
done
# 加密配置文件
sudo gpg --encrypt \
--recipient $GPG_KEY_ID \
--output $ENCRYPTED_DIR/wg0.conf.gpg \
$KEYS_DIR/wg0.conf
echo "✓ 已加密: wg0.conf"
# 设置权限
sudo chmod 600 $ENCRYPTED_DIR/*.gpg
sudo chown root:root $ENCRYPTED_DIR/*.gpg
echo ""
echo "加密文件位于: $ENCRYPTED_DIR"
echo "解密命令: sudo gpg --decrypt <文件>.gpg"
解密恢复:
#!/bin/bash
# decrypt-keys.sh
ENCRYPTED_DIR="/root/wireguard-keys-encrypted"
RESTORE_DIR="/tmp/wireguard-restore"
echo "=== 解密WireGuard密钥 ==="
# 创建恢复目录
mkdir -p $RESTORE_DIR
# 解密所有文件
for encrypted in $ENCRYPTED_DIR/*.gpg; do
if [ -f "$encrypted" ]; then
filename=$(basename "$encrypted" .gpg)
# 解密
sudo gpg --decrypt \
--output $RESTORE_DIR/$filename \
$encrypted
echo "✓ 已解密: $filename"
fi
done
echo ""
echo "解密文件位于: $RESTORE_DIR"
echo "验证文件后,可以恢复到 /etc/wireguard/"
34.3.2 密钥保险库
使用Vault存储密钥(概念):
#!/bin/bash
# vault-integration.sh
# 这是一个概念脚本,展示如何与HashiCorp Vault集成
VAULT_ADDR="https://vault.example.com:8200"
VAULT_TOKEN="<your-vault-token>"
# 存储密钥到Vault
store_key_to_vault() {
local key_name=$1
local key_value=$2
curl -X POST \
-H "X-Vault-Token: $VAULT_TOKEN" \
-d "{\"data\": {\"key\": \"$key_value\"}}" \
$VAULT_ADDR/v1/secret/data/wireguard/$key_name
}
# 从Vault读取密钥
read_key_from_vault() {
local key_name=$1
curl -X GET \
-H "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/secret/data/wireguard/$key_name \
| jq -r '.data.data.key'
}
# 示例使用
# PRIVATE_KEY=$(read_key_from_vault "server_private")
34.4 密钥泄露响应
34.4.1 检测密钥泄露
检查密钥是否在公开位置:
#!/bin/bash
# check-key-exposure.sh
echo "=== 检查密钥泄露风险 ==="
KEYS_DIR="/etc/wireguard"
# 1. 检查文件权限
echo "[1] 检查文件权限..."
find $KEYS_DIR -name "*.key" -o -name "*.conf" | while read file; do
perms=$(stat -c %a "$file")
if [ "$perms" != "600" ] && [ "$perms" != "640" ]; then
echo "⚠ 警告: $file 权限过于开放 ($perms)"
fi
done
# 2. 检查备份文件
echo ""
echo "[2] 检查备份文件..."
if find $KEYS_DIR -name "*.bak" -o -name "*~" | grep -q .; then
echo "⚠ 警告: 发现备份文件"
find $KEYS_DIR -name "*.bak" -o -name "*~"
fi
# 3. 检查Git仓库
echo ""
echo "[3] 检查Git仓库..."
if [ -d "$KEYS_DIR/.git" ]; then
echo "⚠ 警告: WireGuard目录是Git仓库"
cd $KEYS_DIR
if git ls-files | grep -E '\.key$'; then
echo "✗ 密钥文件被Git跟踪"
fi
fi
# 4. 检查历史命令
echo ""
echo "[4] 检查历史命令..."
if grep -i "PrivateKey" ~/.bash_history 2>/dev/null; then
echo "⚠ 警告: bash历史中发现私钥相关命令"
fi
# 5. 检查日志文件
echo ""
echo "[5] 检查日志文件..."
if sudo grep -i "PrivateKey" /var/log/syslog 2>/dev/null | grep -v "hidden"; then
echo "⚠ 警告: 系统日志中可能包含私钥"
fi
# 6. 检查进程内存(需要root)
echo ""
echo "[6] 检查进程内存..."
# 这部分较复杂,仅提示
echo "ℹ 建议定期检查进程内存转储"
echo ""
echo "=== 检查完成 ==="
34.4.2 泄露响应流程
密钥泄露应急响应:
#!/bin/bash
# key-compromise-response.sh
echo "=== 密钥泄露应急响应 ==="
echo "⚠ 警告: 此操作将撤销所有现有密钥"
echo ""
read -p "确认执行应急响应? (输入 YES 继续) " -r
if [ "$REPLY" != "YES" ]; then
echo "操作已取消"
exit 0
fi
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
INCIDENT_DIR="/var/log/wireguard-incident-$TIMESTAMP"
# 1. 记录事件
echo ""
echo "[1] 记录安全事件..."
sudo mkdir -p $INCIDENT_DIR
{
echo "WireGuard密钥泄露事件"
echo "时间: $(date)"
echo "响应人员: $(whoami)"
echo ""
echo "当前配置快照:"
sudo wg show wg0
} | sudo tee $INCIDENT_DIR/incident-report.txt
# 2. 备份当前状态
echo ""
echo "[2] 备份当前状态..."
sudo tar czf $INCIDENT_DIR/pre-response-backup.tar.gz /etc/wireguard/
echo "✓ 备份完成"
# 3. 断开所有连接
echo ""
echo "[3] 断开所有连接..."
sudo wg-quick down wg0
echo "✓ WireGuard已停止"
# 4. 轮换服务器密钥
echo ""
echo "[4] 轮换服务器密钥..."
sudo bash /usr/local/bin/rotate-server-keys.sh
echo "✓ 服务器密钥已轮换"
# 5. 轮换所有客户端密钥
echo ""
echo "[5] 轮换所有客户端密钥..."
CLIENTS_DIR="/etc/wireguard/clients"
for pubkey_file in $CLIENTS_DIR/*_public.key; do
if [ -f "$pubkey_file" ]; then
username=$(basename "$pubkey_file" _public.key)
echo " 轮换: $username"
sudo bash /usr/local/bin/rotate-client-key.sh $username
fi
done
# 6. 启用增强安全
echo ""
echo "[6] 启用增强安全..."
# 启用IP白名单
echo " 启用IP白名单..."
# sudo bash /usr/local/bin/setup-ip-whitelist.sh
# 启用fail2ban
echo " 启用fail2ban..."
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# 7. 生成事件报告
echo ""
echo "[7] 生成事件报告..."
{
echo ""
echo "响应措施:"
echo "- 服务器密钥已轮换"
echo "- 所有客户端密钥已轮换"
echo "- 安全措施已加强"
echo ""
echo "后续行动:"
echo "1. 审计访问日志"
echo "2. 分发新的客户端配置"
echo "3. 监控异常活动"
echo "4. 更新密钥管理流程"
} | sudo tee -a $INCIDENT_DIR/incident-report.txt
echo ""
echo "=== 应急响应完成 ==="
echo "事件记录: $INCIDENT_DIR"
echo ""
echo "⚠ 重要提示:"
echo "1. 所有客户端必须更新配置才能重新连接"
echo "2. 新配置文件位于 /etc/wireguard/clients-new-keys/"
echo "3. 审查日志查找泄露源头"
echo "4. 考虑报告安全事件"
35. 审计和日志
35.1 审计日志配置
35.1.1 启用审计系统
安装和配置auditd:
# 安装auditd
sudo apt install -y auditd audispd-plugins
# 启动服务
sudo systemctl enable auditd
sudo systemctl start auditd
配置WireGuard审计规则:
#!/bin/bash
# setup-wireguard-audit.sh
echo "=== 配置WireGuard审计规则 ==="
# 审计规则文件
AUDIT_RULES="/etc/audit/rules.d/wireguard.rules"
# 创建审计规则
cat << 'EOF' | sudo tee $AUDIT_RULES
# WireGuard配置文件监控
-w /etc/wireguard/ -p wa -k wireguard_config
# WireGuard密钥文件监控
-w /etc/wireguard/wg0.conf -p wa -k wireguard_config_change
-w /etc/wireguard/server_private.key -p ra -k wireguard_key_access
-w /etc/wireguard/clients/ -p wa -k wireguard_client_keys
# WireGuard命令执行监控
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/wg -k wireguard_command
-a always,exit -F arch=b64 -S execve -F exe=/usr/bin/wg-quick -k wireguard_command
# 系统调用监控
-a always,exit -F arch=b64 -S socket -F a0=16 -k wireguard_socket
# 网络配置变更
-w /etc/sysctl.conf -p wa -k sysctl_changes
-w /etc/iptables/ -p wa -k iptables_changes
# systemd服务变更
-w /etc/systemd/system/[email protected] -p wa -k wireguard_service
EOF
echo "✓ 审计规则已创建: $AUDIT_RULES"
# 重新加载审计规则
sudo augenrules --load
echo "✓ 审计规则已加载"
# 查看当前规则
echo ""
echo "当前审计规则:"
sudo auditctl -l | grep wireguard
35.1.2 审计日志查询
查询审计事件:
#!/bin/bash
# query-audit-logs.sh
echo "=== WireGuard审计日志查询 ==="
# 1. 配置文件修改
echo ""
echo "[1] 配置文件修改记录:"
sudo ausearch -k wireguard_config -i | grep -A 5 "type=SYSCALL"
# 2. 密钥访问
echo ""
echo "[2] 密钥文件访问记录:"
sudo ausearch -k wireguard_key_access -i | grep -A 5 "type=PATH"
# 3. 命令执行
echo ""
echo "[3] WireGuard命令执行:"
sudo ausearch -k wireguard_command -i | grep -A 3 "comm="
# 4. 生成报告
echo ""
echo "[4] 生成审计报告..."
REPORT_FILE="/var/log/wireguard-audit-$(date +%Y%m%d).txt"
{
echo "WireGuard审计报告"
echo "生成时间: $(date)"
echo "========================================"
echo ""
echo "配置变更:"
sudo ausearch -k wireguard_config -i --start today | grep -c "type=SYSCALL"
echo ""
echo "密钥访问:"
sudo ausearch -k wireguard_key_access -i --start today | grep -c "type=PATH"
echo ""
echo "命令执行:"
sudo ausearch -k wireguard_command -i --start today | grep -c "comm="
echo ""
} > $REPORT_FILE
echo "✓ 报告已生成: $REPORT_FILE"
实时监控审计事件:
#!/bin/bash
# monitor-audit-realtime.sh
echo "=== WireGuard审计实时监控 ==="
echo "监控WireGuard相关的审计事件..."
echo "按Ctrl+C退出"
echo ""
# 使用ausearch实时监控
sudo ausearch -k wireguard_config -k wireguard_key_access -k wireguard_command -i -ts recent | \
while read -r line; do
echo "[$(date '+%H:%M:%S')] $line"
done
35.2 连接日志
35.2.1 记录连接事件
连接日志脚本:
#!/bin/bash
# log-connections.sh
LOG_FILE="/var/log/wireguard-connections.log"
echo "=== WireGuard连接日志记录 ==="
# 持续监控
while true; do
# 获取当前peer信息
sudo wg show wg0 dump | tail -n +2 | while IFS=$'\t' read -r pubkey psk endpoint allowed_ips handshake rx tx keepalive; do
# 查找用户名
username=$(grep -r "$pubkey" /etc/wireguard/clients/*.key 2>/dev/null | \
grep public | sed 's/.*\/\(.*\)_public.key.*/\1/')
if [ -z "$username" ]; then
username="unknown"
fi
# 提取IP
client_ip=$(echo $allowed_ips | cut -d'/' -f1)
# 计算握手时间
now=$(date +%s)
if [ "$handshake" != "0" ]; then
age=$((now - handshake))
# 如果是新连接(握手时间<10秒)
if [ $age -lt 10 ]; then
# 记录连接事件
{
echo "CONNECTION_ESTABLISHED"
echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
echo "User: $username"
echo "ClientIP: $client_ip"
echo "Endpoint: $endpoint"
echo "PublicKey: ${pubkey:0:20}..."
echo "---"
} >> $LOG_FILE
# 记录到syslog
logger -t wireguard "Connection established: $username from $endpoint"
fi
fi
done
sleep 10
done
配置为systemd服务:
sudo nano /etc/systemd/system/wireguard-connection-logger.service
内容:
[Unit]
Description=WireGuard Connection Logger
After[email protected]
Requires[email protected]
[Service]
Type=simple
ExecStart=/usr/local/bin/log-connections.sh
Restart=always
StandardOutput=null
StandardError=journal
[Install]
WantedBy=multi-user.target
启用:
sudo systemctl enable wireguard-connection-logger
sudo systemctl start wireguard-connection-logger
35.2.2 会话跟踪
跟踪用户会话:
#!/bin/bash
# track-sessions.sh
SESSION_DB="/var/lib/wireguard/sessions.db"
# 创建数据库(SQLite)
init_db() {
sqlite3 $SESSION_DB << EOF
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT,
client_ip TEXT,
endpoint TEXT,
connect_time INTEGER,
disconnect_time INTEGER,
rx_bytes INTEGER,
tx_bytes INTEGER,
duration INTEGER
);
EOF
}
# 记录新会话
log_session_start() {
local username=$1
local client_ip=$2
local endpoint=$3
local timestamp=$(date +%s)
sqlite3 $SESSION_DB << EOF
INSERT INTO sessions (username, client_ip, endpoint, connect_time)
VALUES ('$username', '$client_ip', '$endpoint', $timestamp);
EOF
echo "Session started for $username"
}
# 记录会话结束
log_session_end() {
local username=$1
local rx_bytes=$2
local tx_bytes=$3
local timestamp=$(date +%s)
# 计算会话时长
local start_time=$(sqlite3 $SESSION_DB "SELECT connect_time FROM sessions WHERE username='$username' AND disconnect_time IS NULL ORDER BY id DESC LIMIT 1;")
local duration=$((timestamp - start_time))
sqlite3 $SESSION_DB << EOF
UPDATE sessions
SET disconnect_time = $timestamp,
rx_bytes = $rx_bytes,
tx_bytes = $tx_bytes,
duration = $duration
WHERE username = '$username'
AND disconnect_time IS NULL;
EOF
echo "Session ended for $username (duration: ${duration}s)"
}
# 查询会话历史
query_sessions() {
local username=$1
echo "=== Session History for $username ==="
sqlite3 -header -column $SESSION_DB << EOF
SELECT
datetime(connect_time, 'unixepoch', 'localtime') as Connect,
datetime(disconnect_time, 'unixepoch', 'localtime') as Disconnect,
duration || 's' as Duration,
(rx_bytes / 1048576) || ' MB' as Downloaded,
(tx_bytes / 1048576) || ' MB' as Uploaded
FROM sessions
WHERE username = '$username'
ORDER BY connect_time DESC
LIMIT 10;
EOF
}
# 初始化数据库
init_db
# 示例使用
# log_session_start "alice" "10.8.0.2" "203.0.113.10:54321"
# query_sessions "alice"
35.3 安全事件监控
35.3.1 异常检测
异常行为检测脚本:
#!/bin/bash
# detect-anomalies.sh
echo "=== WireGuard异常检测 ==="
ALERT_FILE="/var/log/wireguard-alerts.log"
# 1. 检测异常连接频率
echo "[1] 检测异常连接频率..."
# 统计每个IP的连接次数(最近1小时)
sudo journalctl -u wg-quick@wg0 --since "1 hour ago" | \
grep -i "handshake" | \
awk '{print $NF}' | \
sort | uniq -c | \
while read count ip; do
if [ $count -gt 100 ]; then
{
echo "ALERT: High connection frequency"
echo "Time: $(date)"
echo "IP: $ip"
echo "Count: $count"
echo "---"
} | tee -a $ALERT_FILE
fi
done
# 2. 检测异常流量
echo ""
echo "[2] 检测异常流量..."
sudo wg show wg0 dump | tail -n +2 | while IFS=$'\t' read -r pubkey psk endpoint allowed_ips handshake rx tx keepalive; do
# 转换为GB
rx_gb=$((rx / 1073741824))
tx_gb=$((tx / 1073741824))
# 如果流量超过阈值(例如100GB)
if [ $rx_gb -gt 100 ] || [ $tx_gb -gt 100 ]; then
username=$(grep -r "$pubkey" /etc/wireguard/clients/*.key 2>/dev/null | \
grep public | sed 's/.*\/\(.*\)_public.key.*/\1/')
{
echo "ALERT: High traffic usage"
echo "Time: $(date)"
echo "User: $username"
echo "Download: ${rx_gb}GB"
echo "Upload: ${tx_gb}GB"
echo "---"
} | tee -a $ALERT_FILE
fi
done
# 3. 检测多地登录
echo ""
echo "[3] 检测多地登录..."
# 检测同一用户从多个地理位置连接
# (需要geoip数据库)
# 4. 检测端口扫描
echo ""
echo "[4] 检测端口扫描..."
# 检查是否有大量连接失败
failed_count=$(sudo journalctl -u wg-quick@wg0 --since "1 hour ago" | \
grep -ic "failed\|invalid\|denied")
if [ $failed_count -gt 50 ]; then
{
echo "ALERT: Possible port scanning"
echo "Time: $(date)"
echo "Failed attempts: $failed_count"
echo "---"
} | tee -a $ALERT_FILE
fi
# 5. 检测配置篡改
echo ""
echo "[5] 检测配置篡改..."
CONFIG_FILE="/etc/wireguard/wg0.conf"
HASH_FILE="/var/lib/wireguard/config.sha256"
# 计算当前哈希
current_hash=$(sha256sum $CONFIG_FILE | awk '{print $1}')
# 检查是否有记录的哈希
if [ -f "$HASH_FILE" ]; then
saved_hash=$(cat $HASH_FILE)
if [ "$current_hash" != "$saved_hash" ]; then
{
echo "ALERT: Configuration file modified"
echo "Time: $(date)"
echo "File: $CONFIG_FILE"
echo "Old hash: $saved_hash"
echo "New hash: $current_hash"
echo "---"
} | tee -a $ALERT_FILE
# 更新哈希
echo $current_hash > $HASH_FILE
fi
else
# 首次运行,保存哈希
echo $current_hash > $HASH_FILE
fi
echo ""
echo "=== 检测完成 ==="
echo "告警记录: $ALERT_FILE"
定时执行异常检测:
# 每10分钟检测一次
*/10 * * * * /usr/local/bin/detect-anomalies.sh
35.3.2 入侵检测集成
与OSSEC集成:
#!/bin/bash
# setup-ossec-wireguard.sh
echo "=== 配置OSSEC监控WireGuard ==="
# OSSEC规则文件
OSSEC_RULES="/var/ossec/rules/wireguard_rules.xml"
# 创建WireGuard规则
cat << 'EOF' | sudo tee $OSSEC_RULES
<group name="wireguard,">
<!-- WireGuard连接失败 -->
<rule id="100001" level="5">
<decoded_as>wireguard</decoded_as>
<match>handshake.*failed</match>
<description>WireGuard handshake failed</description>
</rule>
<!-- 多次连接失败 -->
<rule id="100002" level="10" frequency="5" timeframe="300">
<if_matched_sid>100001</if_matched_sid>
<description>Multiple WireGuard connection failures</description>
</rule>
<!-- 配置文件修改 -->
<rule id="100003" level="7">
<decoded_as>syscheck</decoded_as>
<match>/etc/wireguard/</match>
<description>WireGuard configuration modified</description>
</rule>
<!-- 密钥文件访问 -->
<rule id="100004" level="8">
<decoded_as>auditd</decoded_as>
<match>wireguard_key_access</match>
<description>WireGuard private key accessed</description>
</rule>
<!-- 异常流量 -->
<rule id="100005" level="6">
<match>High traffic usage</match>
<description>WireGuard high traffic detected</description>
</rule>
</group>
EOF
# 配置syscheck监控
OSSEC_CONF="/var/ossec/etc/ossec.conf"
# 添加WireGuard目录监控
sudo sed -i '/<syscheck>/a \
<directories check_all="yes" realtime="yes">/etc/wireguard</directories>' \
$OSSEC_CONF
# 重启OSSEC
sudo systemctl restart ossec
echo "✓ OSSEC配置完成"
35.4 合规性报告
35.4.1 生成合规报告
合规性检查脚本:
#!/bin/bash
# compliance-report.sh
REPORT_FILE="/var/reports/wireguard-compliance-$(date +%Y%m%d).html"
echo "=== 生成WireGuard合规性报告 ==="
# 创建HTML报告
cat << 'EOF' > $REPORT_FILE
<!DOCTYPE html>
<html>
<head>
<title>WireGuard Compliance Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #333; }
h2 { color: #666; border-bottom: 2px solid #ddd; }
table { border-collapse: collapse; width: 100%; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #4CAF50; color: white; }
.pass { color: green; font-weight: bold; }
.fail { color: red; font-weight: bold; }
.warning { color: orange; font-weight: bold; }
</style>
</head>
<body>
<h1>WireGuard VPN Compliance Report</h1>
<p>Generated: $(date)</p>
<p>Server: $(hostname)</p>
EOF
# 1. 密钥安全检查
cat << EOF >> $REPORT_FILE
<h2>1. Key Security</h2>
<table>
<tr>
<th>Check</th>
<th>Status</th>
<th>Details</th>
</tr>
EOF
# 检查密钥权限
for keyfile in /etc/wireguard/*.key; do
if [ -f "$keyfile" ]; then
perms=$(stat -c %a "$keyfile")
if [ "$perms" = "600" ]; then
status="<span class='pass'>PASS</span>"
else
status="<span class='fail'>FAIL</span>"
fi
echo " <tr><td>$(basename $keyfile) permissions</td><td>$status</td><td>$perms</td></tr>" >> $REPORT_FILE
fi
done
# 2. 配置安全检查
cat << EOF >> $REPORT_FILE
</table>
<h2>2. Configuration Security</h2>
<table>
<tr>
<th>Check</th>
<th>Status</th>
<th>Details</th>
</tr>
EOF
# IP转发
ip_forward=$(sysctl -n net.ipv4.ip_forward)
if [ "$ip_forward" = "1" ]; then
status="<span class='pass'>PASS</span>"
else
status="<span class='fail'>FAIL</span>"
fi
echo " <tr><td>IP Forwarding</td><td>$status</td><td>$ip_forward</td></tr>" >> $REPORT_FILE
# 防火墙规则
if sudo iptables -L FORWARD -n | grep -q wg0; then
status="<span class='pass'>PASS</span>"
details="Enabled"
else
status="<span class='fail'>FAIL</span>"
details="Missing"
fi
echo " <tr><td>Firewall Rules</td><td>$status</td><td>$details</td></tr>" >> $REPORT_FILE
# 3. 用户访问审计
cat << EOF >> $REPORT_FILE
</table>
<h2>3. User Access Audit</h2>
<table>
<tr>
<th>Username</th>
<th>Last Connection</th>
<th>Total Data</th>
<th>Status</th>
</tr>
EOF
# 统计用户信息
sudo wg show wg0 dump | tail -n +2 | while IFS=$'\t' read -r pubkey psk endpoint allowed_ips handshake rx tx keepalive; do
username=$(grep -r "$pubkey" /etc/wireguard/clients/*.key 2>/dev/null | \
grep public | sed 's/.*\/\(.*\)_public.key.*/\1/')
if [ -z "$username" ]; then
username="unknown"
fi
# 最后连接时间
if [ "$handshake" != "0" ]; then
last_seen=$(date -d @$handshake '+%Y-%m-%d %H:%M:%S')
# 检查是否活跃(最近7天)
now=$(date +%s)
age=$((now - handshake))
if [ $age -lt 604800 ]; then
status="<span class='pass'>Active</span>"
else
status="<span class='warning'>Inactive</span>"
fi
else
last_seen="Never"
status="<span class='warning'>Never Connected</span>"
fi
# 总流量
total_bytes=$((rx + tx))
total_gb=$((total_bytes / 1073741824))
echo " <tr><td>$username</td><td>$last_seen</td><td>${total_gb}GB</td><td>$status</td></tr>" >> $REPORT_FILE
done
# 4. 安全事件
cat << EOF >> $REPORT_FILE
</table>
<h2>4. Security Events (Last 30 Days)</h2>
<table>
<tr>
<th>Event Type</th>
<th>Count</th>
</tr>
EOF
# 统计安全事件
failed_auth=$(sudo journalctl -u wg-quick@wg0 --since "30 days ago" | grep -ic "failed\|invalid")
config_changes=$(sudo ausearch -k wireguard_config --start $(date -d '30 days ago' +%Y-%m-%d) 2>/dev/null | grep -c "type=SYSCALL" || echo "0")
key_access=$(sudo ausearch -k wireguard_key_access --start $(date -d '30 days ago' +%Y-%m-%d) 2>/dev/null | grep -c "type=PATH" || echo "0")
echo " <tr><td>Failed Authentication</td><td>$failed_auth</td></tr>" >> $REPORT_FILE
echo " <tr><td>Configuration Changes</td><td>$config_changes</td></tr>" >> $REPORT_FILE
echo " <tr><td>Key Access Events</td><td>$key_access</td></tr>" >> $REPORT_FILE
# 结束HTML
cat << 'EOF' >> $REPORT_FILE
</table>
<h2>5. Recommendations</h2>
<ul>
EOF
# 生成建议
recommendations=()
# 检查不活跃用户
inactive_users=$(sudo wg show wg0 latest-handshakes | awk -v now=$(date +%s) '$2 < now - 2592000' | wc -l)
if [ $inactive_users -gt 0 ]; then
recommendations+=("<li>Review and remove $inactive_users inactive users (no connection in 30 days)</li>")
fi
# 检查密钥年龄
key_age=$((($(date +%s) - $(stat -c %Y /etc/wireguard/server_private.key)) / 86400))
if [ $key_age -gt 365 ]; then
recommendations+=("<li>Server key is $key_age days old - consider key rotation</li>")
fi
# 输出建议
if [ ${#recommendations[@]} -eq 0 ]; then
echo " <li>No recommendations at this time</li>" >> $REPORT_FILE
else
for rec in "${recommendations[@]}"; do
echo " $rec" >> $REPORT_FILE
done
fi
cat << 'EOF' >> $REPORT_FILE
</ul>
<hr>
<p><small>This is an automated compliance report. Please review all findings and take appropriate action.</small></p>
</body>
</html>
EOF
echo "✓ 报告已生成: $REPORT_FILE"
# 发送邮件(可选)
# mail -s "WireGuard Compliance Report" -a $REPORT_FILE [email protected] < /dev/null
35.4.2 定期审计
月度审计脚本:
#!/bin/bash
# monthly-audit.sh
AUDIT_DIR="/var/audits/wireguard"
MONTH=$(date +%Y-%m)
AUDIT_FILE="$AUDIT_DIR/audit-$MONTH.txt"
mkdir -p $AUDIT_DIR
echo "=== WireGuard月度审计:$MONTH ===" | tee $AUDIT_FILE
# 1. 用户活动审计
{
echo ""
echo "========================================="
echo "1. 用户活动审计"
echo "========================================="
echo ""
echo "活跃用户:"
sudo wg show wg0 latest-handshakes | \
awk -v now=$(date +%s) '$2 > now - 2592000' | \
wc -l
echo ""
echo "不活跃用户(30天未连接):"
sudo wg show wg0 latest-handshakes | \
awk -v now=$(date +%s) '$2 < now - 2592000 && $2 != 0'
echo ""
echo "从未连接:"
sudo wg show wg0 latest-handshakes | \
awk '$2 == 0'
} | tee -a $AUDIT_FILE
# 2. 流量统计
{
echo ""
echo "========================================="
echo "2. 流量统计"
echo "========================================="
echo ""
echo "总流量统计:"
sudo wg show wg0 transfer | \
awk '{rx+=$2; tx+=$3} END {
printf "接收: %.2f GB\n", rx/1073741824;
printf "发送: %.2f GB\n", tx/1073741824;
printf "总计: %.2f GB\n", (rx+tx)/1073741824
}'
} | tee -a $AUDIT_FILE
# 3. 安全事件统计
{
echo ""
echo "========================================="
echo "3. 安全事件"
echo "========================================="
echo ""
echo "配置修改次数:"
sudo ausearch -k wireguard_config --start $(date -d 'last month' +%Y-%m-01) 2>/dev/null | \
grep -c "type=SYSCALL" || echo "0"
echo ""
echo "认证失败次数:"
sudo journalctl -u wg-quick@wg0 --since "$(date -d 'last month' +%Y-%m-01)" | \
grep -ic "failed\|invalid" || echo "0"
echo ""
echo "密钥访问次数:"
sudo ausearch -k wireguard_key_access --start $(date -d 'last month' +%Y-%m-01) 2>/dev/null | \
grep -c "type=PATH" || echo "0"
} | tee -a $AUDIT_FILE
# 4. 系统健康
{
echo ""
echo "========================================="
echo "4. 系统健康"
echo "========================================="
echo ""
echo "服务运行时间:"
systemctl show wg-quick@wg0 --property=ActiveEnterTimestamp
echo ""
echo "系统负载:"
uptime
echo ""
echo "磁盘使用:"
df -h / | tail -1
echo ""
echo "内存使用:"
free -h | grep Mem
} | tee -a $AUDIT_FILE
# 5. 合规性检查
{
echo ""
echo "========================================="
echo "5. 合规性状态"
echo "========================================="
echo ""
# 密钥权限
echo "密钥文件权限检查:"
find /etc/wireguard -name "*.key" -exec ls -l {} \; | \
awk '{print $1, $9}'
echo ""
echo "配置文件完整性:"
sha256sum /etc/wireguard/wg0.conf
echo ""
echo "审计系统状态:"
systemctl is-active auditd
echo ""
echo "fail2ban状态:"
systemctl is-active fail2ban
} | tee -a $AUDIT_FILE
# 6. 建议
{
echo ""
echo "========================================="
echo "6. 审计建议"
echo "========================================="
echo ""
# 检查需要密钥轮换的用户
echo "密钥年龄检查:"
for keyfile in /etc/wireguard/clients/*_private.key; do
if [ -f "$keyfile" ]; then
age=$((($(date +%s) - $(stat -c %Y "$keyfile")) / 86400))
if [ $age -gt 180 ]; then
echo " $(basename $keyfile): $age 天(建议轮换)"
fi
fi
done
echo ""
echo "不活跃用户清理建议:"
# 列出60天未活跃用户
sudo wg show wg0 latest-handshake | \
awk -v now=$(date +%s) '$2 < now - 5184000 && $2 != 0 {print " " $1}'
} | tee -a $AUDIT_FILE
# 生成摘要
{
echo ""
echo "========================================="
echo "审计完成"
echo "========================================="
echo "审计日期: $(date)"
echo "报告文件: $AUDIT_FILE"
} | tee -a $AUDIT_FILE
echo ""
echo "✓ 月度审计完成"
echo "报告保存在: $AUDIT_FILE"
定时执行:
# 每月1号生成审计报告
0 2 1 * * /usr/local/bin/monthly-audit.sh