尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

甲骨文云VPS开启SSH密码登录:从密钥认证到密码认证的完整配置指南

甲骨文云VPS开启SSH密码登录:从密钥认证到密码认证的完整配置指南 上周帮一位刚抢到甲骨文免费ARM实例的朋友开荒他拿着控制台给的公网IP和私钥文件问我现在IP有了、用户名也有了可是密码在哪为什么我用密码登录一直报错这个问题其实不是个例。很多第一次接触甲骨文云Oracle Cloud VM实例的人都会卡在同一个地方新开的VPS默认只允许密钥登录密码登录是关闭状态而登录密码根本不存在。你要么用密钥文件进系统要么自己动手把密码登录打开没有第三条路。这篇文章我打算把这套配置链路完整讲一遍。从默认密钥登录的原理到sshd_config里几个参数怎么改再到手工操作和脚本自动化最后把连接不上时的排查思路也一并整理出来。内容适用于甲骨文云Oracle Cloud VM实例也适用于绝大多数刚重装完、默认只开密钥认证的Linux VPS。无论你是刚入手第一台云服务器的萌新还是需要批量开新机器做初始化的老手看完都能直接照着做。1. 新开的VPS默认访问方式到底是什么样的1.1 拿到新实例时你手里通常只有三样东西以甲骨文云为例创建实例时你可以选择上传自己的SSH公钥也可以让系统帮你生成密钥对。不管哪条路最终你手里的登录凭据都是这两样一个是公网IP地址一个是私钥文件后缀是.pem或者.key。用户名则取决于你选的系统镜像Oracle Linux和CentOS镜像默认是opcUbuntu镜像默认是ubuntu只有部分自定义镜像才会直接用root。也就是说首次登录这个新实例标准动作不是输密码而是用私钥去敲门。在电脑终端里执行chmod 600 /path/to/your-key.pem ssh -i /path/to/your-key.pem ubuntu你的公网IP其中chmod 600这一步很多人会漏掉私钥文件权限太宽松SSH客户端会直接拒绝使用它。进了系统之后你可能会发现一件事这个VPS压根没有配置登录密码。哪怕你在控制台重置了实例密码那只影响Oracle Cloud控制台的访问跟系统里的SSH登录密码是两码事。想在SSH环节使用密码认证唯一的办法是自己进系统设置密码然后在sshd配置里把密码认证开关打开。1.2 厂商为什么默认关掉密码登录这背后是安全策略的选择不是甲骨文云故意给用户添堵。密码登录有一个让人头疼的问题暴力破解成本太低。只要你的VPS暴露在公网上马上就会有扫描机器人用常见用户名加常见密码的组合不间断地尝试登录。默认开22端口的VPS短短几小时内收到几千次失败的认证尝试日志根本不算新鲜事。密钥登录走的是非对称加密。你手里的私钥相当于一把专属钥匙服务器上存的公钥则是这把钥匙对应的锁芯。没有私钥的人拿猜密码那套方法是完全使不上劲的。正是因为这一点主流云厂商不只是甲骨文云在新实例上都把密钥认证设为默认密码认证则默认关闭。还有一层原因在于镜像模板的统一性。云厂商的镜像希望开出来即安全、可自动化管理而不是开出来就暴露在暴力破解的火力下。开局先让你拿密钥进去用户自己想开密码登录再按需开启这比反过来默认密码登录、让用户自己去关要安全得多。1.3 什么场景下值得手动打开密码登录听到这里可能有人会想密钥登录这么安全那我不开密码登录不就行了说实话你完全有权不开。我自己有一部分服务器至今仍然只保留密钥认证。但下面这些场景里密码登录确实有它不可替代的便利临时在外面的电脑上登录服务器手上没有私钥文件又不想把私钥传到别人机器上。帮朋友或同事排查问题对方只需要知道IP和密码不需要提前交换公钥。使用某些控制面板、监控脚本、SSH隧道工具时它们只认密码认证。个人自用追求省事不希望每次登录都要指定私钥路径。所以这事的本质不是密码登录好还是密钥登录好而是你知道两种方式的差异并且能按需切换。下面就开始讲具体怎么改。2. 动手之前先吃透sshd_config里的这几个核心参数2.1 主配置文件、Include目录、cloud-init下发的配置谁说了算SSH服务端的配置文件通常位于/etc/ssh/sshd_config。早年改配置只需要盯这一个文件现在不行了。以Ubuntu 22.04及更高版本为例sshd_config文件开头会有这么一行Include /etc/ssh/sshd_config.d/*.conf这句话的意思是主配置文件会额外加载/etc/ssh/sshd_config.d/目录下所有以.conf结尾的文件。OpenSSH读取参数时有一个规则谁排在后面谁说了算。如果某个参数在Include进来的文件里被重新定义那么Include进来的值会覆盖主配置文件里的旧值。这就是很多人改完/etc/ssh/sshd_config后重启服务发现设置根本不生效的根本原因。特别是云镜像里会有一个/etc/ssh/sshd_config.d/50-cloud-init.conf这个文件由cloud-init在实例初始化时生成里面可能写入了PasswordAuthentication之类的参数直接覆盖了主配置。所以你在动手前最好先看一下当前生效的配置到底是什么。不但要看主配置文件还要把Include目录下的文件都过一遍grep -r ^PasswordAuthentication\|^PermitRootLogin\|^PubkeyAuthentication /etc/ssh/sshd_config /etc/ssh/sshd_config.d/看清楚现状再改能少走很多弯路。2.2 三个关键参数的取值组合sshd_config里和密码登录相关的参数主要有三个我列一下它们各自控制什么参数可选值作用PasswordAuthenticationyes / no是否允许使用密码登录PermitRootLoginyes / no / prohibit-password是否允许root登录prohibit-password表示允许root用密钥登录但禁止密码PubkeyAuthenticationyes / no是否允许密钥登录建议始终保留yes三个参数配合起来可以组合出多种策略只开密钥登录PasswordAuthentication no这也是很多云实例的默认状态。只开密码登录PubkeyAuthentication no密钥完全不用一般不建议。两种都开PasswordAuthentication yes且PubkeyAuthentication yes这是最灵活、对新手最友好的组合。登录时可以选密码也可以指定私钥总有一条路能进系统。如果你希望root用户也能用密码登录还需要把PermitRootLogin改成yes。如果保持prohibit-password那么就算你给root设置了密码SSH也会拒绝root的密码登录请求。另外较新版本的OpenSSH还涉及KbdInteractiveAuthentication旧版本叫ChallengeResponseAuthentication。在启用PAM的系统上密码认证有时候也会走这个通道。我在实际配置中通常会把它一并放开避免出现明明开了密码认证却提示密码错误的诡异情况PasswordAuthentication yes KbdInteractiveAuthentication yes2.3 改完配置验证语法再重启这一步别省修改任何系统服务的配置文件我都建议先用服务自带的语法检查命令确认一遍不要一股脑重启。SSH服务的语法检查命令是sshd -tsudo sshd -t没有任何输出说明配置语法没问题。如果有报错会直接告诉你第几行参数不对。确认无误后再重启服务sudo systemctl restart sshd这里有个发行版差异要注意在Debian/Ubuntu系上SSH服务名可能是ssh而不是sshd。执行systemctl restart ssh和systemctl restart sshd在这类系统上通常效果一样因为两者指向同一个服务单元但稳妥起见还是先确认一下sudo systemctl status sshd如果提示找不到服务就改用ssh。我见过有人改完配置忘了重启服务然后一直试密码登录怎么试都失败以为配置写错了。其实配置没写错只是服务还在用旧配置。这类问题在排查时最容易让人怀疑人生所以重启这一步务必记牢。3. 手工配置实操从密钥进站到密码验证成功的完整流程3.1 先用私钥把门敲开这一步没什么捷径新实例第一次登录必须靠密钥。在本地终端执行chmod 600 /path/to/your-key.pem ssh -i /path/to/your-key.pem ubuntu你的公网IP如果一切正常你会进入服务器的命令行界面。我建议登录后的第一件事是先看一眼当前用户身份和系统版本确认自己身在何处whoami cat /etc/os-release这能帮你确认两件事当前用户是谁、该用哪个系统的包管理器。后面设置密码、装软件都要依赖这些信息。3.2 给当前用户设置密码新实例的当前用户默认没有密码。你要用passwd命令给当前用户设置一个登录密码passwd执行后会要求输入两次新密码。注意输入密码时终端不会有任何回显这是正常现象不要以为自己键盘坏了。如果你还希望root用户也能用密码登录那就再给root设置一个密码。Ubuntu等系统上root默认没有密码需要先用sudo提权sudo passwd root这里需要小心在Debian/Ubuntu系上使用sudo passwd root设置密码后root用户就有了密码。如果你设置的root密码比较弱又开启了root密码登录等于给公网上的扫描器留了一扇方便门。所以安全起见我建议普通用户能完成日常操作就不用动root密码。确实需要root密码登录的至少把密码设得足够长、足够随机。3.3 修改sshd_config 放开密码认证现在到了关键一步。用编辑器打开/etc/ssh/sshd_configsudo nano /etc/ssh/sshd_config如果你更习惯vim换成sudo vim即可。打开文件后找到或新增以下三行PasswordAuthentication yes KbdInteractiveAuthentication yes PermitRootLogin yes关于PermitRootLogin我给个针对不同需求的取值建议只想让普通用户用密码登录root保持密钥登录保持prohibit-password即可甚至不用改。希望root也能用密码登录改成yes并且先按前面的步骤给root设好密码。最保守的做法改成no任何情况下都不允许root直接SSH登录。改完保存退出。如果你发现主配置文件里的参数没生效回到2.1节去检查/etc/ssh/sshd_config.d/目录下的文件。必要时直接把那些覆盖参数的.conf文件里的相关行也改掉或者在主配置文件的末尾强制重新定义一遍——因为Include加载顺序的原因放在主配置末尾的参数仍然可能被Include文件覆盖最保险的做法还是直接修改Include目录里的那个文件。然后用sshd -t做语法检查通过后重启服务sudo sshd -t sudo systemctl restart sshd3.4 重启sshd并用密码登录验证重启完服务不要急着关掉当前这个SSH会话。我强烈建议你先保持现有连接不断开再新开一个终端窗口去测试密码登录。这样做的好处是万一配置有误导致SSH服务无法启动或登录被拒绝你还有旧会话可以救场不至于把自己锁在服务器外面。新开终端窗口直接执行ssh ubuntu你的公网IP这次不要加-i参数SSH会提示你输入密码。输入刚设置的密码如果能顺利登录说明密码认证已经生效了。验证完毕之后再回头把之前的密钥登录也测一次确保两种方式都没问题ssh -i /path/to/your-key.pem ubuntu你的公网IP这一步我觉得很多人会偷懒跳过但强烈建议做一下。你开启密码认证的同时理想状态下密钥认证应该继续保留。如果因为改配置不小心把PubkeyAuthentication设成了no那密钥登录就会被关掉。这种事我踩过一次当时光顾着开密码认证没注意把密钥认证关了后来丢失本地私钥重装系统时才意识到问题的严重性。4. 一键初始化脚本适合多个新实例快速落地的场景如果你手里只有一两台VPS手工敲命令完全够用。但如果你跟我一样隔三差五就要抢救一台新开出来的机器尤其是费了老大劲才抢到的甲骨文ARM实例那么把上面的步骤固化成脚本会省很多时间。4.1 脚本长什么样下面这段脚本是我平时初始化新VPS时用的精简版去掉了交互直接完成设置当前用户密码、修改SSH配置、重启服务这三件事#!/bin/bash if [ $(id -u) ! 0 ]; then echo 请用root或者sudo执行此脚本 exit 1 fi # 设置root密码防止忘记私钥时无法救急 echo 请输入root的新密码 passwd root # 设置当前登录用户密码这里取sudo环境变量里的SUDO_USER if [ -n $SUDO_USER ]; then echo 请输入普通用户 $SUDO_USER 的新密码 passwd $SUDO_USER fi # 备份原始配置 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date %Y%m%d%H%M%S) # 用sed修改关键参数 sed -i s/^#\?PasswordAuthentication.*/PasswordAuthentication yes/ /etc/ssh/sshd_config sed -i s/^#\?KbdInteractiveAuthentication.*/KbdInteractiveAuthentication yes/ /etc/ssh/sshd_config sed -i s/^#\?PermitRootLogin.*/PermitRootLogin yes/ /etc/ssh/sshd_config sed -i s/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/ /etc/ssh/sshd_config # 语法检查通过后重启服务 if sshd -t; then systemctl restart sshd echo SSH配置已生效 else echo sshd -t 检查失败请手工检查配置 exit 1 fi把这段内容保存为init_ssh.sh然后在服务器上执行chmod x init_ssh.sh sudo ./init_ssh.sh4.2 脚本做了什么脚本的核心思路是把前面手工操作的步骤全部串起来减少遗漏。第1步判断当前是否是root权限普通用户直接拒绝执行避免权限不足导致半途失败。第2步分别设置root和当前登录用户的密码采用交互式输入而不是把密码明文写死在脚本里——这样日志和shell历史里不会残留密码。第3步备份原始sshd_config改出问题可以快速回滚。第4步用sed替换参数。这里^#\?表示行首可能有一个可选的注释符号#这样不管是注释状态还是未注释状态都能正确修改。第5步先跑sshd -t做语法检查通过才重启服务。任何一步出问题脚本都会停下来并提示手工检查。4.3 使用脚本前的检查和上线后的验证脚本虽然方便但它面向的是通用场景。在使用前有几个点需要你自己确认你的系统里是否存在/etc/ssh/sshd_config.d/目录下的覆盖文件如果存在脚本修改主配置文件可能被覆盖。遇到这种情况把脚本里的sed替换逻辑套用到那个具体文件即可。PermitRootLogin yes是不是你想要的如果只想让普通用户密码登录就把这行sed去掉。云平台的安全组、防火墙是否放行了22端口这一步在控制台做光改系统配置是不够的。脚本执行完再用新开的终端窗口分别测试密码登录和密钥登录。这两项测试过了整个初始化才算真正完成。我在实际使用中还会在脚本末尾追加一行打印当前生效的SSH配置方便一眼确认sshd -T | grep -E passwordauthentication|permitrootlogin|pubkeyauthenticationsshd -T是查看SSH服务实际生效配置的命令比直接看文件更靠谱因为它会把所有Include进来的配置合并后的最终结果展示给你。排查配置不生效的问题时这个命令是神器。5. 连接不上的排查链路从ssh -vvv到安全组和防火墙配置密码登录本身不难难的是改完之后连不上了。这个章节我把实战中最高频的几类故障和排查链路完整梳理一遍。5.1 ssh -vvv的输出能告诉我们什么当SSH连接出现问题不要干瞪眼。用调试模式跑一遍让SSH客户端把详细过程打印出来ssh -vvv ubuntu你的公网IP-vvv会把连接过程拆解成三个阶段建立TCP连接、密钥协商与认证、会话建立。输出里几个关键信息要会看Connection to 你的公网IP port 22: Connection refused说明服务器的22端口根本没有响应。要么SSH服务没启动要么防火墙在拦截。Connection timed out说明数据包发出去没回来。大概率是云平台安全组没放行22端口或者本地网络到服务器的路由有问题。Permission denied (publickey,password)说明TCP连接和SSH服务都正常只是认证阶段被拒绝了。这时候要检查用户名、密码、密钥是否正确以及sshd_config里的认证开关是否允许当前使用的认证方式。no matching key exchange method found说明本地SSH客户端和服务器支持的加密算法没有交集多见于新客户端连接很老版本的OpenSSH服务端。解决方向是升级服务端或者临时指定算法。5.2 服务没起来、防火墙拦截、安全组没放行三层排查我习惯按从内到外的顺序排查先看本机服务再看本机防火墙最后看云平台安全组。第一层确认SSH服务在跑sudo systemctl status sshd sudo ss -tlnp | grep :22第一条看服务状态第二条看22端口是否在监听。如果端口没监听大概率是服务没起来。重启服务sudo systemctl restart sshd如果重启报错跑一遍sshd -t看配置哪里写错了。第二层检查本机防火墙Ubuntu上常用ufwCentOS/Oracle Linux常用firewalld。分别看状态# Ubuntu sudo ufw status # CentOS/Oracle Linux sudo firewall-cmd --list-all如果防火墙开启确认22端口是放行的。用ufw放行sudo ufw allow 22/tcp用firewalld放行sudo firewall-cmd --permanent --add-port22/tcp sudo firewall-cmd --reload还有一部分系统用的是纯iptables没有ufw或firewalld这类前端工具那就直接查iptables规则sudo iptables -L -n | grep :22第三层检查云平台安全组甲骨文云的控制台里有两个概念容易混淆一个是网络的安全列表Security List另一个是网络安全组NSG。如果实例绑定的是NSG那么规则配在NSG里如果用的是默认安全列表规则配在VCN的安全列表里。两者都检查一下确认有一条放行入站TCP 22端口的规则源地址建议限制为你自己的固定IP或者0.0.0.0/0如果实在需要全网访问。这一层是云服务器特有的也是最容易被忽略的。很多人在系统层面折腾了半天最后发现问题是安全组压根没放行22端口。另外如果改端口为自定义端口记得安全组也要同步放行新端口。5.3 常见报错速查表报错或现象大概率原因解决办法Connection refusedSSH服务没启动或22端口被本机防火墙拦截检查sshd服务状态检查ufw/firewalld/iptablesConnection timed out云平台安全组未放行22端口或本地网络不通控制台检查安全列表/NSGping测试网络连通性Permission denied (publickey,password)认证失败密码错误或该认证方式被禁止确认密码、确认sshd_config里对应参数为yesPasswordAuthentication参数改了却不生效被Include目录下的conf文件覆盖检查/etc/ssh/sshd_config.d/用sshd -T确认密码登录成功但密钥登录失败本地私钥权限太宽松chmod 600 私钥文件修改配置后所有登录都失败sshd服务没起来或配置有语法错误通过VNC/控制台连接救场恢复备份配置还有一个我特别想提醒的坑刚设置完密码立刻测试密码登录却提示密码错误。这种情况十有八九是你密码里有特殊字符但没有在SSH客户端里正确处理。密码中含有$、!、等特殊符号时直接在命令行里传给ssh可能会被shell解释掉。建议先在简单终端里用ssh交互式输入密码来测试或者用支持安全输入的客户端工具。如果实在搞不定重置一个只包含字母和数字的密码也是一条务实路径。6. 密码登录打开之后安全底线一定不能丢6.1 改端口、禁root、限制来源IP三件套先做开启密码登录等于给服务器开了一道用密码就能撬开的大门所以安全措施必须跟上。我的建议是开完密码认证后紧接着做这三件事改掉默认的22端口。改成高位端口可以减少大量无差别扫描。修改sshd_configPort 22222改完重启sshd后云平台安全组也要同步放行新端口。以后登录就用ssh -p 22222 ubuntu你的公网IP关闭root密码登录。除非你有强需求否则root用户禁止直接用密码登录。把PermitRootLogin从yes改成prohibit-password或者干脆no。日常操作通过普通用户加sudo完成。限制来源IP。如果你的公网IP是固定的在安全组里把22端口或自定义端口的源地址限定为你自己的IP。这样哪怕密码泄露别人也无法从其他IP登录。我个人的习惯是三件事都做尤其是源IP限制这条在甲骨文云上配置非常简单效果却立竿见影。6.2 fail2ban配置与经验值只做上面三件事还不够因为密码登录开启后暴力破解的风险会真实存在。fail2ban是Linux上最常用的暴力破解防护工具它会监控日志发现多次登录失败的IP就临时封禁。安装fail2ban# Ubuntu/Debian sudo apt install fail2ban -y # CentOS/Oracle Linux sudo yum install fail2ban -y配置/etc/fail2ban/jail.local加入下面这段[sshd] enabled true port 22222 filter sshd logpath /var/log/auth.log maxretry 3 bantime 3600参数含义很直观maxretry表示允许尝试3次bantime表示封禁3600秒findtime默认600秒表示10分钟内的失败计数。用sshd服务配合filter sshdfail2ban会自动解析SSH认证失败的日志。启动并查看状态sudo systemctl enable fail2ban sudo systemctl start fail2ban sudo fail2ban-client status sshd注意日志路径在不同系统上有差异。Ubuntu、Debian是/var/log/auth.logCentOS、Oracle Linux是/var/log/secure。填错日志路径fail2ban会一直看不见失败记录等于白装了。另一个经验值是maxretry别设太低。设成1或者2你自己密码输错一次就被封IP后面手动排查问题会很难受。我一般设置3到5次既能拦住扫描器也不影响自己操作。6.3 日常巡检日志、用户列表和密钥授权最后说一个很多人忽略的环节日常巡检。开启密码登录后养成定期看服务器登录日志的习惯能帮你及时发现异常。查看最近成功的登录记录sudo grep Accepted /var/log/auth.log | tail -20查看失败的登录尝试sudo grep Failed password /var/log/auth.log | wc -l除了日志还要定期检查系统里有哪些用户可以登录。列出所有带shell的用户sudo awk -F: $7 ~ /(bash|sh|zsh)$/ {print $1} /etc/passwd另外/home/用户名/.ssh/authorized_keys这个文件里的公钥也要定期检查。这个文件是密钥登录的钥匙库里面每一行都代表着某人拥有这台服务器的登录权限。如果发现不认识的公钥立即删掉那一行并排查服务器是否已经被入侵。开启密码登录之后用户维护这块就变得更关键了。还有一件事我实际操作中也在坚持做把密码和私钥分开管理。密码用于日常交互登录私钥用于脚本和自动化操作。两者分开既避免了密码在脚本里明文存储的风险也避免了一旦私钥泄露全部资产裸奔的局面。严格一点的话给私钥本身再加一个口令passphrase这样就算私钥文件被别人拿走没有口令也使用不了。密码登录是一把双刃剑用好了它是救急的备用通道用不好它就是服务器最显眼的突破口。我的建议始终是新开的VPS先用密钥登录完成初始配置再按需打开密码登录同时把端口、root权限、fail2ban、源IP限制这些配套措施全部跟上。这套组合下来既保留了密码登录的便利又不至于把服务器直接暴露在公网扫描的火力下。
返回列表