maxstartups限制未完成认证的半开连接数以防御dos,其10:30:100默认值实现延迟+丢弃策略;persourcemaxstartups和persourcenetblocksize需配合usepam yes生效,且仅适用于sshv2。

MaxStartups 是什么,为什么它能防 DoSMaxStartups 不是限制“已登录用户数”,而是控制**尚未完成认证的连接请求数**——也就是攻击者在暴力破解或泛洪时卡在密码输入前、密钥交换中、甚至只发个 SYN 就不继续的“半开连接”。这些连接会占用内存和文件描述符,堆积多了直接让 sshd 拒绝新请求,连合法用户都登不上。
OpenSSH 默认值通常是 10:30:100(不同版本略有差异),含义是:
- 最多允许 100 个未认证连接
- 前 10 个连接立即处理(无延迟)
- 第 11–30 个连接会被随机延迟(throttling)
- 超过 30 个后,新连接直接被丢弃
这个设计很关键:它不一刀切拒绝所有新连接,而是用“延迟+丢弃”组合,既防住扫段/爆破脚本的密集请求,又保留对真实用户的友好性。
PerSourceMaxStartups 和 PerSourceNetBlockSize 怎么配才有效
单靠 MaxStartups 不够。攻击者可以换 IP 或用代理池发起大量连接,这时就得靠客户端粒度的限制:
-
PerSourceMaxStartups 1:每个源 IP 最多只能有 1 个未认证连接。适合管理严格、IP 稳定的场景(比如只从办公网段登录)。但别乱开在公网服务器上——NAT 环境下多个用户共用一个出口 IP,会互相锁死。
-
PerSourceNetBlockSize 32:128:限制每个 IP 的“网络数据块”缓存上限。32 表示初始缓冲区大小(KB),128 是硬上限(KB)。它防的是恶意客户端发超长、畸形或重复的 SSH 数据包,消耗服务端内存。这个参数在 OpenSSH 9.0+ 才支持,旧版本无效。
PerSourceMaxStartups 1:每个源 IP 最多只能有 1 个未认证连接。适合管理严格、IP 稳定的场景(比如只从办公网段登录)。但别乱开在公网服务器上——NAT 环境下多个用户共用一个出口 IP,会互相锁死。PerSourceNetBlockSize 32:128:限制每个 IP 的“网络数据块”缓存上限。32 表示初始缓冲区大小(KB),128 是硬上限(KB)。它防的是恶意客户端发超长、畸形或重复的 SSH 数据包,消耗服务端内存。这个参数在 OpenSSH 9.0+ 才支持,旧版本无效。注意:PerSourceMaxStartups 和 PerSourceNetBlockSize 必须配合 UsePAM yes 才生效(因为依赖 PAM 的连接追踪机制)。如果你关了 PAM,这两个配置就形同虚设。
改完配置后怎么验证没写错、真起作用
改完 /etc/ssh/sshd_config 别急着重启,先做两件事:
- 语法检查:
sudo sshd -t。输出为空 = 配置无语法错误;如果有报错,会明确指出哪一行、什么参数错(比如拼成 MaxSturtups)。
- 检查实际加载值:
sudo sshd -T | grep -E '^(maxstartups|persourcemaxstartups|persourcenetblocksize)'。这会输出运行时真正生效的值,确认不是被 include 或默认值覆盖了。
sudo sshd -t。输出为空 = 配置无语法错误;如果有报错,会明确指出哪一行、什么参数错(比如拼成 MaxSturtups)。sudo sshd -T | grep -E '^(maxstartups|persourcemaxstartups|persourcenetblocksize)'。这会输出运行时真正生效的值,确认不是被 include 或默认值覆盖了。别跳过这两步。线上服务器一旦 systemctl restart sshd 后配置崩了,可能直接失联——尤其当你还改了 Port 却忘了开防火墙时。
LoginGraceTime 和 ClientAliveInterval 这两个超时要一起调LoginGraceTime 控制“从 TCP 连接到完成认证”的宽限期,默认 120 秒。攻击者常建连后空挂着不动,耗尽连接池。建议压到 30 或 45。
ClientAliveInterval 和 ClientAliveCountMax 控制“已登录但空闲”的会话清理:
-
ClientAliveInterval 60:每 60 秒发一次加密心跳 -
ClientAliveCountMax 3:连续 3 次没回应就断开 → 实际超时约 3 分钟
这两个参数和 MaxStartups 是互补关系:前者管“还没登进来”的连接,后者管“登进来但睡着了”的连接。漏掉任何一个,DoS 防御都有缺口。
真正容易被忽略的是:这些参数对协议版本有要求。PerSource<em></em> 类参数只在 SSHv2 下有效;而 ClientAlive 完全不适用于 SSHv1(早该禁用了)。确认你的 sshd_config 里有 Protocol 2,且没留 Protocol 2,1 这种危险回退。










