Skip to content

运维脚本示例:安全、告警与系统初始化

侧重思路说明与可运行示例;生产环境务必替换路径、账号与策略。


一、访问频率异常与自动封禁 IP(iptables)

思路:从 Nginx 访问日志中截取最近一段时间内的请求,统计同一 IP 出现次数超过阈值则认为是异常,若 iptables 中尚未丢弃该 IP,则添加 DROP 并记录日志。

shell
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
LOG_FILE=/usr/local/nginx/logs/demo2.access.log
ABNORMAL_IP=$(tail -n5000 $LOG_FILE |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
    if [ "$(iptables -vnL | grep -c -- "$IP")" -eq 0 ]; then
        iptables -I INPUT -s "$IP" -j DROP
        echo "$(date +'%F_%T') $IP" >> /tmp/drop_ip.log
    fi
done

补充说明

  • DATE 与日志里的时间格式必须一致,否则 grep 筛不出数据。
  • 阈值 10tail 5000 仅为示例,误封真实用户的风险始终存在;更稳妥的做法是结合业务告警、人工复核或使用 fail2ban 等成熟方案。
  • 云主机往往还有安全组;本机 iptables 与云端策略需一致考虑。
  • IPv6、CDN、反向代理场景下「第一层看到的 IP」可能是代理 IP,需配合 X-Forwarded-For 与可信代理列表(脚本未涵盖)。

二、邮件告警(mailx)

示例通过配置 mailx 使用 SMTP 发信。以下为示意配置,切勿把真实密码写入仓库。

shell
# yum install mailx
# vi /etc/mail.rc
set from=alert@example.com smtp=smtp.example.com
set smtp-auth-user=alert@example.com smtp-auth-password=YOUR_SMTP_AUTH_CODE
set smtp-auth=login

补充

  • 多数邮箱要求 客户端专用密码授权码,不是网页登录密码。
  • 更安全的做法:用环境变量或独立权限只有 root 可读的配置文件注入密码,并限制文件权限。
  • 其他告警通道:企业微信/钉钉 Webhook、PagerDuty、自建 Prometheus Alertmanager 等,Shell 往往只负责调用 curl POST JSON。

三、新装机初始化(时区、安全、内核与工具)

下列脚本摘自教程示例,面向 RHEL/CentOS 系(yum/etc/redhat-release)。在其他发行版上需改包管理器与路径。

shell
#!/bin/bash
# 设置时区(优先 timedatectl;失败时再回退到软链)
timedatectl set-timezone Asia/Shanghai 2>/dev/null || {
  rm -f /etc/localtime
  ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
}
# 时间同步:示例仍用 ntpdate;新系统请优先 chrony(systemctl enable --now chronyd)
if ! crontab -l 2>/dev/null | grep -q ntpdate; then
    (echo "* 1 * * * ntpdate time.windows.com >/dev/null 2>&1"; crontab -l 2>/dev/null) | crontab -
fi

# 禁用 SELinux(重启后完全生效;请按当前值核对,勿盲目执行)
sed -i.bak 's/^SELINUX=enforcing/SELINUX=disabled/; s/^SELINUX=permissive/SELINUX=disabled/' /etc/selinux/config

# 关闭防火墙
if egrep "7.[0-9]" /etc/redhat-release &>/dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
elif egrep "6.[0-9]" /etc/redhat-release &>/dev/null; then
    service iptables stop
    chkconfig iptables off
fi

# 历史命令显示操作时间
if ! grep -q HISTTIMEFORMAT /etc/bashrc; then
    echo 'export HISTTIMEFORMAT="%F %T `whoami` "' >> /etc/bashrc
fi

# SSH超时时间
if ! grep "TMOUT=600" /etc/profile &>/dev/null; then
    echo "export TMOUT=600" >> /etc/profile
fi

# 禁止root远程登录
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

# 禁止定时任务向发送邮件
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab 

# 设置最大打开文件数
if ! grep -Fq "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
    cat >> /etc/security/limits.conf << EOF
    * soft nofile 65535
    * hard nofile 65535
    EOF
fi

# 系统内核优化
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp_max_syn_backlog = 20480
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_fin_timeout = 20  
EOF

# 减少SWAP使用
echo "0" > /proc/sys/vm/swappiness

# 安装系统性能分析工具及其他
yum install -y gcc make autoconf vim sysstat net-tools iostat iftop iotop lrzsz

补充说明

  • 版号判断脚本里用 egrep "7.[0-9]" / 6.[0-9]" 仅为示例;AlmaLinux / Rocky 8、9 等不会命中,需改为 VERSION_ID/etc/os-release)或 systemctl 判断 firewalld 是否存在。
  • PermitRootLogin:若 sshd_config 已是 prohibit-password 等,需人工核对,勿依赖单行 sed 万能替换。
  • SELinux 改为 disabled 需重启才完全生效;也可先 permissive 排查。
  • 禁止 root SSH:请先确认已有 sudo 用户可登录,避免把自己锁在外面。
  • ntpdate 已逐渐被 chronychronyd)取代,新项目建议调研发行版默认时间同步方案。
  • 正文中包名已写为 iotop;若仓库无某包,删除对应名称即可。
  • grep "* soft nofile":已改为 grep -F 匹配字面量 *;若仍失败请直接人工检查 limits.conf

四、与本系列其他文档的关系

  • 批量 SSH、数据库备份、Nginx 日志等见同目录下后续章节。
  • Shell 语言基础见上级目录 0106 合并文档。