SSH 这个词凡是用过 Linux 的人都不会陌生。前段时间有朋友问我连着服务器总得输密码不仅麻烦日志里还隔三差五冒出陌生 IP 的尝试到底怎么配置才既安全又省事这其实就是很经典的 linux配置ssh 场景。这篇内容不堆理论按真实动手顺序把服务端配置、客户端配置、密钥认证、安全加固、故障排查这几块一次说透。看完你至少能完成三件事让日常登录从密码变成密钥、给 sshd 做一遍基本加固、以后碰到“连不上”知道从哪里入手。无论是刚摸 Linux 的新手还是要维护生产机的运维这套思路都适用。1. 内容整体设计与思路拆解1.1 SSH 到底在解决什么问题SSH 本质上是“远程安全登录通道”。你可以把它理解成大门的门禁系统不是谁都能进进出记录留痕对话内容全程加密。它同时负责三件事身份认证证明你是谁、传输加密中间人截了包也看不懂、通道复用一条连接里可以跑命令、传文件、转发端口。大多数 Linux 发行版默认都装了 OpenSSH但“装了”和“配好了”是两回事。默认状态一般是密码登录开着、端口 22、root 可以远程登录。这套配置在小范围开发环境勉强能用一旦机器暴露在公网日志里很快就会看到大量扫描尝试。所以 linux配置ssh 的重点从来不是“怎么装上”而是“怎么把登录方式、端口、权限控制调整到适合你的场景”。想清楚这一点后面所有操作都不会跑偏。1.2 动手前先想清楚三件事第一件密码登录还是密钥登录。我基本建议一律切到密钥。密钥相当于一把和锁配对好的钥匙私钥留在本机公钥放到服务器。它的优势是长度和随机性远强于人类记忆的密码而且你能随时单独吊销某台服务器的访问权不用改所有人的账号密码。初期可以让密码和密钥同时开着确认密钥能登录后再关掉密码验证避免把自己锁在门外。第二件端口改不改。总有人说改端口只是“安全通过隐藏实现”但我的实测体验是把 22 改成高位端口后日志里的暴力扫描尝试会肉眼可见地减少。这不能解决所有问题但能显著降低噪音。关键是别选 2222、22222 这种常见替代容易进扫描字典。我习惯选 20000 以上的非常规端口同时记得防火墙和安全组要同步放行。第三件你的使用场景是什么。自己一台开发机、几台内网服务器、还是公网生产环境配置策略完全不同。开发机可以宽松一些生产机建议限制来源 IP、关闭密码登录、甚至只允许指定用户登录。别想一套配置走天下SSH 真正麻烦的恰恰是场景的差异化配置这也是很多人配完不好用的根因。1.3 配置的完整骨架一套标准的 SSH 配置由三部分组成服务端的 sshd_config控制谁可以进来、用什么方式进来、客户端的 ~/.ssh/config让自己连多台机器更顺手、密钥对身份凭证。很多人只盯着服务端改参数结果日常操作反而别扭、多台机器管理混乱。真正好用的配置是这三个部分配合起来服务端决定权限边界客户端降低日常操作成本密钥承担认证职责。后面所有内容都是围绕这三块展开的。2. 核心细节解析与实操要点2.1 服务端 sshd_config 的关键参数先说明路径绝大多数 Linux 发行版的服务端配置文件都在 /etc/ssh/sshd_config。改之前先备份然后看几个核心参数。参数建议值作用与理由Port22022 或自定义高位端口减少被扫描命中的概率必须同步改防火墙和安全组PermitRootLoginprohibit-password允许密钥登录但禁止密码登录 root生产机可设为 noPubkeyAuthenticationyes开启公钥认证这是密钥登录的前提PasswordAuthentication先用 yes确认密钥可用后改 no避免密钥没配对就关掉密码把自己锁在门外MaxAuthTries3限制单次连接尝试次数降低暴力破解效率LoginGraceTime30限制认证超时时间防止连接长期占用ClientAliveInterval / ClientAliveCountMax300 / 2定期探测空闲连接防止假死连接堆积拿 PermitRootLogin 举例prohibit-password 的意思是 root 可以用密钥登录但不能用密码登录no 则是完全不允许 root 直接 SSH。生产环境建议用 no平时用普通用户登录再 sudo既安全又能在审计日志里看到具体是谁执行了什么命令这个差别非常重要。改完配置后一定要做两件事先执行 sshd -t 检查语法再 systemctl reload sshd 让配置生效。reload 不会踢掉现有连接所以生产机上敢于随手改动但前提是语法检查通过。我见过有人改错一个参数reload 后新连接全挂幸好旧连接没断才救了场。MaxAuthTries 不建议设成 1因为有时密钥类型判断会额外消耗一次尝试机会设太严格反而误伤正常登录。3 次是实操里比较合适的值既能挡脚本又不影响正常使用。2.2 客户端 config 文件的高级用法很多人不知道客户端也有配置文件路径是 ~/.ssh/config。它的作用说穿了就是给 ssh 指令做别名预设大大减少日常敲键盘的时间。看一个典型片段Host prod HostName 203.0.113.10 Port 22022 User deploy IdentityFile ~/.ssh/id_ed25519_prod配置完之后直接 ssh prod 就能登录不需要每次记 IP、端口、用户名。这个文件的价值体现在三个场景第一多台服务器按 Host 分块管理所有连接参数一目了然。第二多密钥并存时IdentityFile 精确指定哪个私钥去认证避免出现“带了 A 机器的钥匙要去开 B 机器的锁”这种错配。第三支持 ProxyJump用于跳板机场景非常舒服比如Host jump HostName 203.0.113.20 User admin Port 22022 Host internal-1 HostName 10.0.0.5 User dev ProxyJump jump之后 ssh internal-1命令会自动先连跳板机再跳向内网目标全程不需要手动在跳板机上再敲一次 ssh。这个模式比 ssh -A 转发 agent 更简洁清晰也更容易排查问题。还有个小细节命令行参数永远比配置文件里的优先级高所以临时想换个端口或用户直接在命令行覆盖即可不必改文件。2.3 密钥权限最容易踩坑的地方密钥认证对文件权限极度敏感。sshd 出于安全考虑会拒绝使用“权限过宽”的密钥文件。常见权限要求如下~/.ssh 目录700~/.ssh/authorized_keys600私钥600 或 400公钥644 没有问题很多人配完密钥仍然发现要输密码用 ssh -vvv 一看是 “bad permissions”就是 chmod 没弄对。另外要留意用 root 身份生成的密钥放到非 root 用户目录归属不对也会被拒。我排查过很多次最后发现只是权限 777 导致的失败这类问题占误配案例的比例相当高。如果发行版开了 SELinux还可能涉及上下文问题执行 restorecon -Rv ~/.ssh 可以恢复默认上下文。 Windows 10/11 自带 OpenSSH 客户端在 PowerShell 里同样能跑 ssh-keygen 和 ssh-copy-id但 Windows 的文件 ACL 权限模型跟 Linux 不完全一样同步代码或配置文件时一旦把权限放宽过头SSH 也会拒绝使用这个坑值得提前了解。3. 实操过程与核心环节实现3.1 服务端从零配置到能连第一步确认服务端已安装。多数发行版自带 openssh-server没有的话用包管理器装Debian 系执行 apt install openssh-serverRedHat 系执行 dnf install openssh-server。装完后启动并设置开机自启服务名在不同发行版可能是 sshd 或 ssh用 systemctl enable --now sshd 即可。第二步处理防火墙与安全组。如果用的云服务器安全组要放行对应 TCP 端口本机防火墙是 ufw 的话执行 ufw allow 22022/tcp。这一步最容易漏漏了就会出现“配置全对但连不上”的诡异现象。实际现象是telnet 测试端口不通ssh 客户端一直卡在 connecting其实就是请求被防火墙静默丢弃了。第三步编辑 /etc/ssh/sshd_config。按上一节建议改端口、关掉 root 密码登录但先保留普通用户的密码登录以防万一。保存后先 sshd -t 检查语法再 systemctl reload sshd。第四步新开终端测试连接。这里有个顺序很重要不要在旧连接断掉之前重启或关掉 sshd否则配置写错又断了旧连接后果很严重。正确流程是改配置 → 语法检查 → reload → 新连接验证 → 再把临时允许的密码登录关掉。我实际操作机器时习惯把每次改动的参数和日期用注释放进配置文件里批处理多台机器时才不会搞混哪台改了什么。3.2 密钥认证的完整落地流程第一步生成本机密钥。优先选 ed25519 算法现代系统都支持速度快、密钥短安全性也足够。担心极老设备的兼容性可以用 RSA 4096。命令如下ssh-keygen -t ed25519 -C work-laptop -f ~/.ssh/id_ed25519-t 指定算法-C 是备注-f 指定文件名。系统会提示设置 passphrase我建议务必设置。这样可以保证私钥即使被别人拷走也还需要口令才能使用。唯一的小麻烦是每次连接都要输一次口令但可以配合 ssh-agent 做会话缓存输入一次后面不再重复输入。第二步把公钥放到服务器。最方便的方式是 ssh-copy-idssh-copy-id -p 22022 userserver这个命令会提示输入服务器密码然后自动把你的公钥追加到服务器的 ~/.ssh/authorized_keys。如果没有这个命令手动方式也很简单把 id_ed25519.pub 的内容追加到服务器的 authorized_keys 文件一行一个公钥。第三步验证密钥登录再关密码。新开连接执行 ssh -p 22022 userserver如果不再要密码说明密钥认证成功。确认能用之后再回到 sshd_config 把 PasswordAuthentication 改为 noreload 生效。这里有个值得特别注意的细节authorized_keys 是追加而不是覆盖。我见过有人把原文件内容清空再粘贴新公钥结果所有人的访问全断只能跑去机房或控制台恢复。手动操作时严格用 追加不要用 。3.3 多机与跳板场景的免密配置如果你维护多台服务器不要每台机器产一套密钥那样私钥管理会失控。正确的做法是本机生成一两对长期使用的密钥对分别用于不同信任级别的机器把对应的公钥一次性追加到各台服务器的 authorized_keys。后续要收回某台机器的权限只需要从那台机器的 authorized_keys 里删掉对应那一行非常灵活。批量分发公钥时如果目标机器多可以写一个简单循环来跑 ssh-copy-id。但要注意不要为了图省事在命令行参数里直接暴露密码历史记录和进程列表都可能泄露。更稳妥的做法是先用 ssh-copy-id 分发给少数第一批机器再通过第一批机器作为跳板去分发给其余机器过程中保持交互式输密码而不是把密码写进脚本。跳板机场景前面已经给了 config 示例实际用下来ProxyJump 的体验比传统的多级 ssh 手动跳转要顺畅很多尤其是配合 ControlMaster 复用连接时连续操作内网多台机器的效率提升非常明显。思路就是一级跳板负责过公网二级内网机负责干活密钥只放在本机和跳板上内网机器则信任来自本机的转发请求。4. 安全加固与日常维护4.1 常用安全手段的组合拳安全从来不是靠单一参数。我自己的组合拳是非默认端口降低被扫描概率。关闭密码登录消灭暴力破解面。禁止 root 直连一律通过普通用户 sudo。用 AllowUsers 设置登录白名单只允许指定用户 SSH。有条件时限制来源 IP比如只允许固定办公出口 IP 访问。部署 fail2ban 做动态封禁把连续失败的 IP 临时拉黑。AllowUsers 的写法很简单AllowUsers alice bob意味着只有这两个用户能 SSH。想再叠加 IP 限制可以写 AllowUsers alice192.0.2.0/24表示只有来自该网段的 alice 才能登录灵活度很高。fail2ban 是很常用的防护组件它监控认证日志连续失败多次的 IP 会被临时封禁。部署时记得先把当前出口 IP 加进白名单不然自己误操作几次被断连那种感觉实在不好受。替代方案是用 sshd 自身的 MaxAuthTries 配合防火墙手动封禁适合机器少、不想再维护一个常驻进程的场景。4.2 日常维护备份、审计与恢复配置文件和密钥目录都属于“静态资产”平时不觉得重要关键时刻丢了、改错了就非常被动。我的习惯是把 /etc/ssh/sshd_config 的每一次修改用注释写上日期和原因定期整体备份 /etc/ssh/ 目录把 ~/.ssh/config 纳入个人备份清单每季度检查一遍各台机器的 authorized_keys删掉不认识的公钥。审计登录记录主要关注两类信息认证失败的密集模式说明有人在扫某个成功登录发生在非预期时间说明可能存在泄露。排查时用 journalctl -u ssh 或者直接看 /var/log/auth.log日志保留时间不要太短有按月轮转的策略最好。有些发行版默认只保留最近几周遇到半个多月前的异常登录行为日志已经滚没了那才真是无从下手。还有一个容易忽略的点系统升级或迁移服务后记得检查 sshd 是否还是默认配置。有些云厂商镜像或自动化初始化脚本会重置配置如果回滚后不经确认之前做的加固可能一夜回到解放前。我遇到过升级完系统后发现 22 端口又开了密码登录复盘下来就是镜像自动把 sshd_config 覆盖回了默认值。4.3 连接排查的思维顺序遇到“连不上”我按“网络 → 端口 → 服务 → 认证”四层顺序排查这个顺序几乎覆盖所有场景。网络层目标机器能不能 ping 通通则进入下一层不同则看安全组、路由、物理链路。端口层本机执行 nc -vz server_ip 22022看端口是否通。不通就是防火墙或安全组没放行。服务层到目标机器上执行 ss -tlnp | grep 22022看 sshd 是否在监听。没监听说明服务没起来或者配置里有语法错误导致启动失败。认证层执行 ssh -vvv server_ip观察完整交互过程是权限问题、密钥不匹配还是密码验证被禁绝大部分问题在这一层就能定位。这套顺序我用了很多年基本没有遇到超出这个框架的卡点。很多时候大家一上来就怀疑密钥错了其实链路层都没通白折腾半天。5. 常见问题与排查技巧实录5.1 高频报错逐个拆Permission denied (publickey)服务端拒绝了密钥认证。常见原因公钥不在 authorized_keys 里、私钥没被使用、文件权限不对、登录用户不匹配。先用 ssh -vvv 看客户端是否提交了正确的私钥再检查服务器端 authorized_keys。Connection refused服务没启动或端口没在监听也可能是防火墙直接返回拒绝而不是丢弃。用 systemctl status sshd 确认服务状态再用 ss -tlnp 看监听情况。Connection timed out请求被静默丢弃大概率是防火墙或安全组没放行目标端口。这个和 Connection refused 的区别在于refused 说明有人明确拒绝timed out 说明没人响应。no supported authentication methods服务器没有可用的认证方式。通常就是 PasswordAuthentication 已经关掉但密钥又没有配对成功两边都不满足。这种情况先用临时方法确认密钥有没有生效再决定是否重新开启密码认证。WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED目标主机的 host key 变了可能是系统重装也可能有人做中间人。确认系统确实重装后手动清除 known_hosts 里的旧条目即可不用过度恐慌但也不要下意识忽略。5.2 一次真实排查实录有一次同事反馈某台服务器突然连不上了。我没有直接去查密钥而是按固定顺序排查先从本机 ping 目标通再 nc 测端口居然也通。网络层没问题说明方向是对的。接着从另一台同网段机器登录上去看 sshd 状态服务在跑但日志里出现 “Bad protocol version identification”。回头看配置发现有人改了 sshd_config 里的 ListenAddress指定到了错误网卡导致连接请求落在未监听的地址上。改回正确地址reload 后立刻恢复正常。这个案例有两点值得记录一是别上来就怀疑密码或密钥先确认链路和监听二是改配置文件必须留历史记录否则出问题时根本不知道谁改了什么。后来我养成了习惯任何 sshd_config 改动都配一行注释写明日期和原因这个习惯救了我很多次。5.3 问题速查表症状常见原因处理办法连接超时防火墙或安全组未放行端口检查 ufw、iptables、云安全组规则连接被拒sshd 未启动或端口未监听检查服务状态与监听地址Permission denied (publickey)公钥未配对、权限不对、用户不匹配用 ssh -vvv 定位检查 authorized_keys 与权限始终要求输密码密钥未生效密码认证仍然开着确认密钥分发正确后再关闭 PasswordAuthentication登录加载特别慢DNS 反向解析或 GSSAPI 认证拖慢客户端加 -o GSSAPIAuthenticationno服务端视情况 UseDNS noHost key 变化告警系统重装或 host key 被修改核实系统状态后清除 known_hosts 旧条目最后再分享一个个人体会。我配了这么些年 SSH最大的感受是别在一开始就钻参数细节先想清楚“这台机器允许谁、用什么方式、从哪些地址登录”。把这个边界想明白了配置方向基本不会跑偏。还有两个习惯能帮你躲开绝大多数事故改配置前备份、改完用 sshd -t 先检查再 reload。这套流程虽然朴素但确实让我在生产环境里少踩了很多坑。
阅读完成 · 觉得有帮助?