统计尝试SSH连接的IP地址脚本
ssh-login-stat.sh
#!/bin/bash
# 文件名: ssh-login-stat.sh
# 作者: wanghongwei
# 日期: 2026年8月20日
# 版本: 1.0
# 描述: 统计尝试 SSH 连接的 IP 地址:成功、无效用户、失败、其他探测、关闭、总计(按连接去重)
# 使用方式: ./ssh-login-stat.sh [日志文件,默认/var/log/secure]
logfile="${1:-/var/log/secure}"
if [[ ! -f "$logfile" ]]; then
echo "错误:日志文件 '$logfile' 不存在" >&2
exit 1
fi
# 单元格内容宽度定义
IP_W=20
SUC_W=10
INV_W=12
FAIL_W=10
OTHER_W=10
CLOSE_W=10
TOTAL_W=10
# 打印分隔线
print_sep() {
printf "+"
printf "%0.s-" $(seq 1 $((IP_W + 2))); printf "+"
printf "%0.s-" $(seq 1 $((SUC_W + 2))); printf "+"
printf "%0.s-" $(seq 1 $((INV_W + 2))); printf "+"
printf "%0.s-" $(seq 1 $((FAIL_W + 2))); printf "+"
printf "%0.s-" $(seq 1 $((OTHER_W + 2))); printf "+"
printf "%0.s-" $(seq 1 $((CLOSE_W + 2))); printf "+"
printf "%0.s-" $(seq 1 $((TOTAL_W + 2))); printf "+\n"
}
# 打印表头
print_sep
printf "| %-*s | %-*s | %-*s | %-*s | %-*s | %-*s | %-*s |\n" \
$IP_W "IP Address" $SUC_W "Success" $INV_W "Invalid User" $FAIL_W "Failure" $OTHER_W "Other" $CLOSE_W "Close" $TOTAL_W "Total"
print_sep
# 使用 gawk 统计,按 sshd 进程号(PID)识别连接,状态优先级 1>2>3>4>5
gawk '
{
# 跳过 sshd 服务状态日志
if ($0 ~ /Server listening/) {
next
}
# 提取 sshd 进程号,无 PID 则跳过
if (!match($0, /sshd(-session)?\[([0-9]+)\]/, arr_pid)) {
next
}
pid = arr_pid[2]
# 提取 IP 地址,无 IP 则跳过
if (!match($0, /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)) {
next
}
ip = substr($0, RSTART, RLENGTH)
key = pid
conn_ip[key] = ip
# 状态优先级:成功(1) > 无效用户(2) > 失败(3) > 关闭(4) > 其他(5)
if ($0 ~ /Accepted publickey|Accepted password/) {
if (status[key] == 0 || 1 < status[key]) status[key] = 1
} else if ($0 ~ /Invalid user|Connection closed by invalid user/) {
if (status[key] == 0 || 2 < status[key]) status[key] = 2
} else if ($0 ~ /Failed password|Connection closed by authenticating user|drop connection.*MaxStartups|Connection reset by/) {
if (status[key] == 0 || 3 < status[key]) status[key] = 3
} else if ($0 ~ /Connection closed by/) {
if (status[key] == 0 || 4 < status[key]) status[key] = 4
} else {
if (status[key] == 0) status[key] = 5
}
}
END {
# 按连接状态汇总到每个 IP
for (key in status) {
ip = conn_ip[key]
if (status[key] == 1) succ[ip]++
else if (status[key] == 2) inv[ip]++
else if (status[key] == 3) fail[ip]++
else if (status[key] == 4) closed[ip]++
else if (status[key] == 5) other[ip]++
}
# 收集所有出现过的 IP
for (ip in succ) all_ip[ip] = 1
for (ip in inv) all_ip[ip] = 1
for (ip in fail) all_ip[ip] = 1
for (ip in closed) all_ip[ip] = 1
for (ip in other) all_ip[ip] = 1
# 输出结果(列顺序:IP, Success, Invalid User, Failure, Other, Close, Total)
for (ip in all_ip) {
s = succ[ip] + 0
i = inv[ip] + 0
f = fail[ip] + 0
o = other[ip] + 0
c = closed[ip] + 0
t = s + i + f + o + c
print ip, s, i, f, o, c, t
}
}' "$logfile" | sort -nr -k7 | while read -r ip s i f o c t; do
printf "| %-*s | %-*d | %-*d | %-*d | %-*d | %-*d | %-*d |\n" \
$IP_W "$ip" $SUC_W "$s" $INV_W "$i" $FAIL_W "$f" $OTHER_W "$o" $CLOSE_W "$c" $TOTAL_W "$t"
done
print_sep
作者:wanghongwei
版权声明:本作品遵循<CC BY-NC-ND 4.0>版权协议,商业转载请联系作者获得授权,非商业转载请附上原文出处链接及本声明。

浙公网安备 33010602011771号