Linux SSH安全配置:禁止Root远程登录与密钥认证

发布时间:2026/10/8 8:48:48
Linux SSH安全配置:禁止Root远程登录与密钥认证 简介一份面向Linux运维初学者与系统管理员的SSH安全配置入门文档重点解决远程管理中最常见的Root直接登录风险和密码认证安全隐患。文档从重启SSH服务讲起围绕/etc/ssh/sshd_config文件展开涵盖修改默认端口、禁止Root远程登录、禁止空密码用户登录并完整演示基于RSA密钥对的公钥认证配置流程包括ssh-keygen生成密钥、authorized_keys部署以及Windows下使用PuTTY进行密钥登录的细节同时说明StrictModes等关键选项的权限约束。资源为单份PDF电子文档体积仅288KB内容紧凑、步骤指令清晰适合遇到server refused our key等登录问题或准备加固服务器SSH配置的读者直接参考。目前已有156人学习下载对于需要快速掌握SSH安全基线配置的操作人员而言是一份即查即用的精简手册。1. Linux SSH配置与禁止Root远程登陆先保住入口再谈安全我拆过不少Linux服务器的SSH配置文档最典型的一次翻车是晚上十点改完sshd_config顺手systemctl restart sshd结果新开的终端窗口全部连接失败旧会话还挂着不敢动。那台机器还没配密钥登录Root密码是唯一入口——等于把自己锁在门外。后来我把「改SSH配置」这件事拆成了一套固定流程先理解每个参数的作用边界再改配置最后用sshd -t校验、开新会话验证、最后才reload。这份《Linux SSH配置和禁止Root远程登陆设置文档.pdf》讲的就是这套东西从sshd_config的常用参数到禁止Root远程登录的安全基线都有涉及。适合刚接手服务器的新手也适合被暴力破解折腾过的老运维——看完能直接照着改改完知道怎么验证踩坑了知道去哪查。2. sshd_config 逐项拆解先搞清楚每个开关再动手2.1 SSH登录链路与配置加载顺序SSH不是装好就能用的。Linux发行版里openssh-server装完sshd进程读取/etc/ssh/sshd_config然后监听22端口。客户端连过来时sshd按配置文件里的参数决定三件事端口对不对、允许谁登录、用哪种方式认证。这条链路上任何一个环节卡住结果都是Connection refused或者Permission denied。我一般会先确认服务状态再谈配置。常见的检查命令是systemctl status sshd ss -tlnp | grep :22第一行看sshd服务是否active第二行看22端口有没有被监听。如果端口没起来先查sshd进程有没有报错用journalctl -u sshd看最近日志。这个习惯能省掉后面一半的排查时间。配置文件的加载顺序也容易被忽略。sshd_config是主配置但OpenSSH 7.0以上版本还支持/etc/ssh/sshd_config.d/目录下的drop-in片段主配置末尾通常有一行Include /etc/ssh/sshd_config.d/*.conf。这就带来一个坑你改的主配置参数可能被目录里的片段覆盖。查实际生效值的时候别只看主文件要连drop-in目录一起看。我遇到过有人在sshd_config里写了PermitRootLogin no结果目录里另一个conf文件写了yes最后Root照常能登——排查了半小时才发现是Include顺序问题。2.2 核心参数速查与推荐基线sshd_config里参数很多但日常运维真正需要动的没几个。我把高频参数整理成了一份基线表改配置的时候对着这个表过一遍就行参数推荐值作用备注Port2222自定义修改监听端口改完要同步防火墙和SELinuxPermitRootLoginno禁止Root直接登录配合普通用户sudo使用PubkeyAuthenticationyes允许密钥认证建议开启PasswordAuthenticationno关闭密码认证确认密钥可用后再关AllowUsers普通用户名用户白名单不在列表里的用户直接拒绝MaxAuthTries3最大认证尝试次数防暴力破解LoginGraceTime30登录超时秒数防DDoS占连接ClientAliveInterval300服务端心跳间隔配合下面参数断死链ClientAliveCountMax2心跳失败次数上限超过则断开连接这套参数组合起来的效果是监听非默认端口、禁止Root、只允许密钥认证、限定用户白名单。每一条都有明确目的改端口是降低被扫描概率禁Root是缩小攻击面密钥认证是防止密码被爆破白名单是限制登录入口。2.3 首次配置实操最小可运行配置第一次上手不要一上来就全部参数堆上去先改一个最小集合确认能跑通再逐步收紧。我建议的首次配置顺序是先改端口再配密钥最后才动PasswordAuthentication和PermitRootLogin。顺序反了容易把自己锁在门外。# 编辑sshd主配置 sudo vim /etc/ssh/sshd_config # 修改后的核心内容 Port 2222 PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication no AllowUsers devops # 语法校验 sudo sshd -tsshd -t只校验语法不检查参数逻辑。比如PermitRootLogin no和PasswordAuthentication no同时开没问题但如果AllowUsers里写的用户名不存在sshd -t不会报错连接时才失败。所以校验之后一定要做连接测试。改完配置后建议先不重启用sshd -t确认语法正确然后开一个新的SSH会话用-cipher或者直接连一次确认新配置能正常登录最后再reload。这个「先验证、后reload」的顺序是我吃过亏之后才养成的习惯。参数修改后有两种生效方式systemctl reload sshd平滑重载和systemctl restart sshd完全重启。reload不会断开现有连接restart会。生产环境优先用reload但有些参数比如ListenAddress修改后必须restart才能生效。判断标准是看sshd -T输出的实际生效值是否和配置文件一致不一致就restart。3. 禁止Root远程登陆三步改完并验证3.1 为什么不能只改 PermitRootLogin no网上很多教程说禁止Root远程登录就是改一行PermitRootLogin no但实际上改完这行只是把「直接以Root身份登录」关掉了攻击面并没有缩到最小。原因是Root不能直接登录后攻击者还可以尝试其他用户名如果这些用户名密码弱照样能进来再提权。更关键的是如果你同时开着PasswordAuthentication yes攻击者依然可以用普通用户弱密码撞库。所以禁止Root登录必须搭配两件事一是确认有一个普通用户能通过sudo切换到Root二是要么用密钥认证要么强密码策略把普通账号的密码强度拉上来。还有一层容易忽略PermitRootLogin参数不只接受yes和no。OpenSSH还支持prohibit-password和forced-commands-only两个中间值。prohibit-password表示禁止密码登录但允许密钥登录forced-commands-only只允许通过authorized_keys里指定的命令执行。如果你只想关密码登录、保留密钥用prohibit-password而不是no。直接写no会把密钥登录也一起关掉。这个区别在文档里写得很清楚但实操中我见过不少人把no当成唯一选项。3.2 普通用户白名单的完整配置完整的禁止Root远程登录方案分为四步创建普通用户、加入sudo组、改PermitRootLogin、配置AllowUsers白名单。每一步都有对应命令# 1. 创建普通用户 sudo useradd -m -s /bin/bash devops sudo passwd devops # 2. 加入sudo组Ubuntu为sudoCentOS为wheel sudo usermod -aG sudo devops # 3. 修改sshd_config sudo sed -i s/^#PermitRootLogin.*/PermitRootLogin no/ /etc/ssh/sshd_config sudo sed -i s/^PermitRootLogin.*/PermitRootLogin no/ /etc/ssh/sshd_config # 4. 追加AllowUsers白名单 echo AllowUsers devops | sudo tee -a /etc/ssh/sshd_config # 5. 校验并重载 sudo sshd -t sudo systemctl reload sshduseradd创建用户后必须设密码不然登录直接失败。usermod -aG里的-a参数是append的意思不加会把你之前加过的附属组全部覆盖我已经在脚本里踩过这个坑所以现在写命令都会带-a。sed替换那两行分别处理带注释和不带注释的情况第一次跑可能其中一行没匹配到这很正常关键是最终sshdd -t能通过。AllowUsers写在sshd_config末尾好处是优先级高不会被Include目录里的片段覆盖。但要注意AllowUsers和AllowGroups不要同时用两个参数同时存在时会取交集配置不好会出现用户明明在白名单里却登录不了的情况。3.3 修改后的验证清单改完配置不是测试一次就算完事我建议按这份清单逐项验证# 1. 语法校验 sudo sshd -t # 2. 查看实际生效配置 sudo sshd -T | grep -E permitrootlogin|allowusers|passwordauthentication # 3. 测试Root登录预期被拒绝 ssh -p 2222 root服务器IP # 4. 测试普通用户登录预期成功 ssh -p 2222 devops服务器IP # 5. 测试sudo切换 sudo whoamisshd -T输出的是sshd实际加载的参数值和配置文件可能有差异每一步修改后都要以sshd -T的输出为准。测试Root登录时你会发现连接直接返回Permission denied或Connection closed这就对了。如果还能登录说明配置没生效——检查Include目录里有没有覆盖项。普通用户登录成功后sudo whoami要输出root说明提权路径正常。这套验证跑完禁止Root登录才算真正落地。日志层面也要盯一下。禁止Root后攻击者的Root登录尝试会记录在/var/log/auth.logDebian/Ubuntu或/var/log/secureCentOS/RHEL里。我一般配置一个cron任务定期grep关键字重点看Failed password和Connection closed by preauth的行数变化行数异常增长说明有人在扫描。4. 用密钥认证把安全拉满生成、分发与权限4.1 密钥对生成与参数选择禁止Root登录之后剩下的普通用户不能继续裸奔用密码。生产环境的标配是密钥认证客户端生成一对密钥私钥自己留着公钥放到服务器的authorized_keys文件里。登录的时候服务端用公钥验证客户端的私钥省掉密码输入的同时把暴力破解的可能性降到零。密钥生成命令如下# 生成Ed25519密钥对推荐 ssh-keygen -t ed25519 -C devopsworkstation -f ~/.ssh/id_ed25519 # 或兼容性更好的RSA 4096 ssh-keygen -t rsa -b 4096 -C devopsworkstation -f ~/.ssh/id_rsa # 查看公钥内容 cat ~/.ssh/id_ed25519.pub-t指定算法ed25519是目前推荐选项速度快、密钥短、安全性高。老一些的系统可能不支持ed25519这时候用rsa -b 4096兜底。f参数指定私钥保存路径默认在~/.ssh/id_ed25519。生成过程中会提示输入passphrase我建议一定要设——万一私钥泄露了没有passphrase对方也拿不到私钥内容。代价是每次登录要输一遍passphrase可以用ssh-agent记住。这里有个常见的选型纠结到底用RSA还是Ed25519。我的做法是看服务端版本OpenSSH 6.5以下不支持Ed25519但那种老系统基本都该升级了。新部署的机器一律Ed25519只有对接老设备时才退到RSA。文档里如果提到密钥类型选择通常也会给这个参考标准。4.2 批量分发与authorized_keys权限陷阱公钥要放到服务器上才能生效。最常见的分发方式是ssh-copy-id也可以手动追加但手动追加踩权限坑的概率大得多# 方式一ssh-copy-id推荐 ssh-copy-id -p 2222 devops服务器IP # 方式二手动追加适合ssh-copy-id不可用时 cat ~/.ssh/id_ed25519.pub | ssh -p 2222 devops服务器IP mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keysssh-copy-id会自动处理目录和文件权限手动追加必须自己确保三个权限点~/.ssh目录是700、authorized_keys文件是600、~/.ssh和authorized_keys的所有者必须是当前用户。权限太宽松时sshd会出于安全考虑直接忽略密钥认证——它认为文件可能被篡改过。这就是很多人密钥配好了但登录还是要输密码的根本原因查日志能看到Authentication refused: bad ownership or modes。批量管理多台服务器时我不建议一台台去手动分发写个循环脚本更靠谱#!/bin/bash # 批量分发公钥到多台服务器 SERVERS10.0.0.11 10.0.0.12 10.0.0.13 DEFAULT_PORT2222 USERdevops for HOST in $SERVERS; do echo 正在处理 $HOST ... ssh-copy-id -p $DEFAULT_PORT $USER$HOST if [ $? -eq 0 ]; then echo $HOST 密钥分发成功 else echo $HOST 密钥分发失败请手动检查 fi done脚本会逐台连接并要求输入一次密码之后这台机器就只认密钥了。循环里的$?判断上一条命令是否执行成功0表示成功非0表示失败。生产环境跑这个脚本前我建议先在一台测试机上跑通确认目标服务器的sshd_config已经开启PubkeyAuthentication yes不然分发过去也登录不了。密钥认证生效后再把PasswordAuthentication改成no。此时普通用户和Root都只能走密钥登录配合之前的PermitRootLogin no整个SSH入口就只剩一条可控的密钥通道了。最后别忘了在sshd_config里把PasswordAuthentication改成no前先开着第二个终端连接测试确认密钥能用再改不然就是自断后路。5. 避坑排查SSH配置翻车的六个高频现场5.1 服务重启后新连接全断现象修改sshd_config后执行systemctl restart sshd当前SSH窗口没断但新开的连接全部超时或拒绝。原因大概率是配置文件里某个参数写错了但sshd进程重启时没检测出来。最常见的是Port参数被改成防火墙未放行的端口或者ListenAddress绑定了错误的IP地址。sshd restart时如果配置有语法错误进程会拒绝启动但很多参数是运行时才报错的。解决立刻从云控制台VNC或物理控制台登录先把配置改回来再重启。关键处理路径# 用sshd -t检查语法 sudo sshd -t # 查看详细的debug输出 sudo sshd -d -p 2222 # 查看sshd运行状态 sudo systemctl status sshd # 查看日志定位错误 sudo tail -50 /var/log/auth.logsshd -t只查语法层面错误查不出逻辑问题。sshd -d会在前台运行并输出debug日志能看到实际监听的地址和处理流程。遇到配置改完连不上的情况我现在的处理顺序是先确认sshd进程还活着再确认端口在监听最后确认防火墙状态三步走完基本能定位到问题层。如果sshd直接挂了连端口都看不见那就要检查配置里有没有不存在的用户或无效参数。5.2 常见高频坑逐条排查下面是几条出现频率高到值得单列的坑每条按现象到解决写清楚坑一PermitRootLogin no之后密钥也登不进 现象改成no之后即使Root的公钥已经放进authorized_keys登录依然被拒。 原因PermitRootLogin no会禁止所有方式登录Root包括密钥。如果还想让Root走密钥登录应该用prohibit-password。 解决把PermitRootLogin改成prohibit-passwordreload后测试。文档里如果没提这个参数大概率是只讲no的用法所以才会有这么多人踩这个坑。坑二authorized_keys权限过大导致密钥无效 现象密钥已分发sshd_config里PubkeyAuthentication也开了但登录时还是提示要输密码。 原因~/.ssh目录或authorized_keys文件的权限太宽松sshd拒绝信任。常见的是chmod 755 ~/.ssh或者authorized_keys被设成666。 解决严格按照chmod 700 ~/.ssh和chmod 600 ~/.ssh/authorized_keys执行注意不能是root所有必须是登录用户的。日志里出现Authentication refused: bad ownership or modes就是这个问题。坑三Ubuntu默认没装openssh-server 现象刚装好的Ubuntu服务器ssh命令连不上本机IPnetstat看不到22端口。 原因Ubuntu桌面版默认不安装openssh-server只装了客户端。 解决apt install openssh-server装完自动启动。CentOS/RHEL相反默认装了openssh-server但Kali又是另一个情况——Kali默认装了但服务没启动需要systemctl enable ssh --now。不同发行版行为差异很大排查时先确认服务存在与否再谈配置。坑四麒麟系统能往外连不能被别人连 现象麒麟系统上SSH客户端能正常连接其他服务器但其他机器连接它直接失败。 原因麒麟系统默认可能没有安装openssh-server或sshd服务未启动防火墙和SELinux也可能拦截了22端口。国产系统很多默认策略偏严安全组件会主动放行出站连接但拦截入站。 解决先检查系统服务里有没有sshd没有就安装openssh-server然后systemctl enable sshd --now再放行防火墙端口。SELinux的状态也要查getenforce如果是Enforcing可能需要设置sebool或添加端口规则。坑五改端口后防火墙没同步 现象Port改成2222后本机连接成功但外网连不上。 原因改了sshd监听端口但firewalld或iptables规则还只放行22。 解决把新端口加入防火墙放行列表。firewalld环境下执行firewall-cmd --permanent --add-port2222/tcp firewall-cmd --reload。很多文档只讲改sshd_config不讲防火墙联动所以这个坑出现频率极高。还有SELinuxCentOS上如果开着SELinux自定义端口需要semodule或semanage port添加。坑六配置改了但没生效 现象文件里明明写了PermitRootLogin no用sshd -T查出来还是yes。 原因配置文件末尾的Include指令把sshd_config.d目录下的文件加载进来目录里的文件参数优先级更高。 解决确认drop-in文件里有没有冲突配置或者干脆在sshd_config末尾启用Include的优先级写法。用grep -r PermitRootLogin /etc/ssh/查所有相关文件一目了然。5.3 改配置前的后悔药快照与备份运维改配置最怕的就是改坏了回不去。我现在的习惯是每次动sshd_config之前先备份这个习惯救过我两次。命令很简单# 备份配置 sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date %Y%m%d%H%M) # 需要恢复时 sudo cp /etc/ssh/sshd_config.bak.202501101530 /etc/ssh/sshd_config sudo systemctl reload sshd备份文件名带时间戳是为了区分多次修改后悔药不能只有一颗。云服务器的话改之前顺手打一个快照更保险。格式化一点说改配置的黄金法则是「永远留一条后路」——当前终端别关、备份文件留着、防火墙规则确认放行。三条占不住一条就动手改早晚翻车。6. 验证配置的习惯sshd -T 和 reload 之间差了一条命配置校验有两条命令很多人混着用但它们干的事不一样。sshd -t只检查语法是否合法sshd -T输出当前生效的配置参数。语法合法不代表逻辑正确比如Port写成非数字类型sshd -t可能报错但PermitRootLogin和PasswordAuthentication这两个参数如果用错了值sshd -t照样通过sshd -T才能看出实际加载的是哪个值。我把这套验证流程固化成了一条固定命令组合每次改完配置都执行一遍# 语法检查 sudo sshd -t # 实际生效参数检查 sudo sshd -T | grep -E permitrootlogin|passwordauthentication|port|allowusers # 平滑重载 sudo systemctl reload sshd # 确认服务正常 sudo systemctl status sshd # 新开终端测试连接 ssh -p 2222 devops服务器IPreload和restart的选择也是一条命的事。reload不中断现有连接只是让sshd重新读取配置文件restart会终止所有连接再启动。生产环境优先reload的基本盘是如果你改错了老的连接还活着你还有机会用老连接把配置改回来。如果你用的是restart改错就是当场断线而且起不来的sshd不会给你留任何回旋余地。我之前踩过的坑就是restart之后sshd直接挂掉VNC进控制台才救回来。从那以后我强制自己改SSH配置时永远先开一个新终端窗口保持连接再执行reload确认新连接能进来才关老窗口。如果reload后新连接失败老窗口还在可以立刻把配置改回去再reload——这就是reload比restart多出来的那条命。还有一个容易被忽略的验证维度改完配置后要看一眼日志。ssh -p 2222连接一次然后立刻tail /var/log/auth.log能看到Accepted publickey for devops加上登录IP。这行日志确认密钥认证真的走通了而不是你以为走通了。日志里如果出现Failed password说明密码认证还没关干净回头检查PasswordAuthentication。最后说个我在文档基础上补充的习惯把这份PDF里的配置项整理成一个速查卡放在服务器上下次改配置前先对照速查卡过一遍参数边界改完后用上面这条命令组合做一轮验证。这套流程看着麻烦但每次都能在五分钟内完成而且再也没出过把自己锁在门外的事。希望帮到你。本文还有配套的精品资源点击获取