最可靠的方式是使用sshd_config的allowusers指令限制用户+ip组合,因其原生支持、优先级最高且语义清晰;/etc/hosts.allow在现代系统中基本失效,firewalld/iptables仅作第二道防线,denyusers仅适合临时封禁。

最直接、最可靠的方式是改 /etc/ssh/sshd_config 里的 AllowUsers,而不是依赖已废弃的 /etc/hosts.allow。 现代 OpenSSH(8.0+)默认不编译 libwrap 支持,hosts.allow 和 hosts.deny 在 CentOS/RHEL 8+、Ubuntu 20.04+ 等系统上基本失效,强行配置可能完全不生效,还掩盖真实问题。
用 AllowUsers 限制用户 + IP 组合登录
这是 OpenSSH 原生支持、无需额外依赖、优先级最高且语义清晰的方案。它在认证前就做匹配,比防火墙更早拦截,也比 TCP Wrappers 更可控。
-
AllowUsers是白名单机制:未明确列出的用户或 IP,一律拒绝,哪怕密码正确 - 格式严格:
username@ip_address或username@cidr_net,中间不能有空格;多个条目用空格分隔 - 支持 CIDR,但不支持通配符(如
192.168.1.*是无效的,必须写成192.168.1.0/24) - 若只限制 IP 不限制用户,可写成
AllowUsers *@192.168.1.0/24;但生产环境强烈建议同时限定用户
示例配置:
AllowUsers admin@192.168.10.5 root@203.0.113.12 admin@2001:db8::1/64
改完后必须执行 sudo systemctl restart sshd,否则不生效。注意:重启会断开当前 SSH 连接,务必确保你有控制台访问权限(如云平台 VNC)或留一个未关闭的会话备用。
为什么 /etc/hosts.allow 很可能没用
OpenSSH 自 6.7 版起默认禁用 TCP Wrappers(即 libwrap),8.0+ 彻底移除编译选项。即使你在 /etc/hosts.allow 里写了 sshd: 192.168.1.100,运行 ldd /usr/sbin/sshd | grep wrap 返回空,就说明根本不链接 libwrap.so,规则纯属摆设。
- RHEL/CentOS 8+、Fedora 33+、Debian 11+、Ubuntu 20.04+ 默认不支持
- 部分旧系统(如 CentOS 7)虽保留,但行为不稳定:比如仅对 IPv4 生效、不处理 IPv6、与
AllowUsers冲突时逻辑难预测 - 错误现象:配置完
hosts.allow后仍能从禁止 IP 登录,或反过来——放行 IP 却被拒,debug 时容易误判为 SSH 配置问题
用 firewalld 或 iptables 做第二道防线
防火墙层限制适合“只放行某几个管理 IP”,尤其当你无法修改 SSH 配置(如托管环境),或需要快速临时封禁某个暴力扫描 IP 时。但它不区分用户,只看源 IP + 目标端口。
-
firewalld(推荐用于 RHEL/CentOS 8+、Fedora):sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.12" port port="22" protocol="tcp" accept' sudo firewall-cmd --permanent --remove-service=ssh sudo firewall-cmd --reload
-
iptables(适用于无 firewalld 的系统):sudo iptables -A INPUT -p tcp -s 203.0.113.12 --dport 22 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 22 -j DROP
注意:这两条必须成对使用,且DROP规则要放在ACCEPT之后;否则所有 SSH 请求都会被第一条DROP拦截 - 防火墙规则不会影响本地登录(如 console、tty),而
sshd_config的AllowUsers会影响所有 SSH 连接方式(包括密钥、密码、代理转发)
DenyUsers 和 DenyGroups 仅作补充,别当主力
黑名单机制天生有维护成本:新用户、新 IP 要持续追加,漏一条就可能被利用。它适合临时封禁某个已知恶意账号(如 DenyUsers hacker1 hacker2),不适合构建长期访问控制策略。
-
DenyUsers不支持 IP 限定,只能写用户名(如DenyUsers guest test) - 若同时配置了
AllowUsers和DenyUsers,AllowUsers优先匹配,DenyUsers只对已通过AllowUsers的用户起作用 - 常见误操作:只写
DenyUsers *想禁止所有人——这会导致所有用户都无法登录,因为*是字面量,不是通配符
真正关键的细节是:所有基于 sshd_config 的限制都发生在 SSH 协议认证阶段之前,而防火墙规则作用在网络层。如果你看到连接被重置(Connection reset by peer),大概率是防火墙 DROP 了包;如果提示 Permission denied 且没弹密码框,才是 AllowUsers 生效了。别靠猜,用 journalctl -u sshd -f 实时看日志最准。











