很多刚装完 Ubuntu 的朋友都会遇到同一个尴尬场景:安装向导里明明设置了用户名和密码,但登录系统后想切换到 root 身份,输入自己设的密码却怎么都不对;想用另一台电脑远程 SSH 连过来,又被 Permission denied 挡在外面。这两个问题放在一起,几乎成了新装 Ubuntu 用户的第一道坎,有人甚至为此直接重装系统。
今天这篇就把“新装 Ubuntu 之后如何配置 root 密码、如何开启 SSH 远程登录”这条线完整走一遍。我会把每一步背后的原理、实际踩过的坑、以及排查思路都讲清楚,不管你是刚接触 Ubuntu 的新手,还是从 CentOS 切过来的运维,应该都能少走不少弯路。
1. 整体思路与 Ubuntu 权限模型的底层逻辑
1.1 sudo 机制与 root 密码到底是什么关系
很多人卡在 root 密码这一步,根源在于没弄懂 Ubuntu 的权限模型。CentOS 这类系统在安装时可以直接设置 root 密码,但 Ubuntu 默认不让 root 账户直接登录,安装向导里创建的那个用户其实是管理员组(sudo 组)成员,你设置的是这个普通管理员的密码,不是 root 的密码。
那 root 密码存在吗?存在,但默认是锁定的、随机且无人知晓。你可以用 sudo 临时提权执行管理员命令,因为 sudo 验证的是“当前用户自己的密码”,而 su - root 或者直接登录 root 需要的是 root 账户的密码。两者本质上不是一回事,这也是新手最容易混淆的地方。
打个比方:sudo 相当于保安队长手里的一张临时门禁卡,刷卡就能办管理员的事,但刷的是自己的卡、记的是自己的名;root 则是万能总钥匙,拿到它所有门都能开。Ubuntu 默认不给这把总钥匙,是为了减少误操作和审计盲区——用 sudo 执行任何高权限命令都会留下日志,而全程用 root 操作什么都查不到。
理解了这一点,接下来的操作就有方向了:我们要做的不是“找回 root 密码”,而是“为 root 账户设置一个新密码”。
1.2 为什么新装系统默认无法用 root 远程登录
SSH 连不上 root 的情况同样有原因。首先,Ubuntu 桌面版默认根本没有安装 SSH 服务端,只有客户端 openssh-client,所以你 systemctl status ssh 会直接报错;服务器版安装时可以勾选 OpenSSH server,但如果没勾选,同样没服务。
其次,就算装了 openssh-server,Ubuntu 的 /etc/ssh/sshd_config 里对于 root 登录的默认策略也不是“放开”的。在新版本 Ubuntu 中,PermitRootLogin 的默认值是 prohibit-password,意思是允许 root 通过密钥方式登录,但禁止用密码登录。所以即使你给 root 设了密码,直接用 ssh root@ip 加密码去连,依然会被拒绝。
再叠加一个更隐蔽的点:如果你的系统里有防火墙,比如 ufw 或者云平台安全组没有放行 22 端口,那连密码验证的机会都没有,直接 connection timed out。新装 Ubuntu 的用户往往同时踩中这几个坑,导致问题看起来特别棘手。
所以正确的操作顺序应当是:先给 root 设置密码,再确认/安装 SSH 服务端,然后调整 sshd_config 参数,最后放行防火墙。下面我按这个顺序逐个拆解。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 配置前的准备与环境确认
2.1 确定系统版本和基本网络环境
无论你的 Ubuntu 是装在物理机、虚拟机还是云服务器上,第一步永远是确认系统版本和当前网络状态。很多教程直接让用户改配置,忽视基础环境,最后用户照着操作却失败,因为版本不同、默认配置不一样。
bash复制lsb_release -a
cat /etc/os-release
uname -m
至少要看清楚三个信息:系统版本(比如 Ubuntu 22.04 LTS / 24.04 LTS)、CPU 架构(x86_64 还是 aarch64)、以及是否有图形界面。不同版本在 sshd_config 的默认值上确实有差异,比如 Ubuntu 24.04 对密码算法和密钥类型的限制就更严格一些。
接着确认网络。ip addr 查看本机 IP,ping -c4 8.8.8.8 测试外网连通性。如果是在虚拟机里新装的系统,很多人会碰上网络没起来的问题,表现为 ping 不同外网、apt update 也无法完成。这时候先查 /etc/netplan/*.yaml 的配置,确认网卡是否正确启用,不要一上来就怪 SSH。
还需要做一件看着多余、实则必要的事:更新软件源和系统包。新装的系统软件源里可能存在过期索引,直接安装 openssh-server 有概率出现依赖解析问题。
bash复制sudo apt update && sudo apt upgrade -y
等待升级完成,再进入下一步。这个过程耗时取决于网络,但值得等。
2.2 给 root 设置密码的正确姿势
前面已经解释过,root 密码默认是未设置的,所以我们要用当前管理员用户来设置 root 密码。打开终端执行:
bash复制sudo passwd root
系统会先要求输入当前用户的密码(也就是你登录 Ubuntu 时用的密码),验证通过后才提示 New password: 和 Retype new password:。两次输入一致且足够复杂,root 密码就设置成功了。
这里有一个很容易被忽略的点:sudo passwd root 和 sudo passwd 有什么区别?前者给 root 账户设置密码,后者是修改当前用户自己的密码。如果你只是想改自己那个管理员账户的密码,执行 passwd 就够了;但目标是 root,必须带上用户名。
设置完成后,可以用 su - 验证一下。su - 会切换到 root 并加载 root 的完整环境变量,而 su 不带横杠只切换用户身份,环境变量还是原来的。很多人喜欢用 sudo -i,效果和 su - 类似,都是拿到一个 root shell。
我强烈建议新用户用 sudo -i 而不是直接 su -,因为如果哪一天 root 密码忘了,只要当前用户在 sudo 组里就还能通过 sudo -i 恢复控制。也正是这个原因,Ubuntu 默认锁定 root 密码其实是一种保护机制——防止你忘掉密码后连系统都进不去。
另外提醒一句:给 root 设置密码后,别再随意用 root 执行日常命令。我见过有人全程 root 操作,一不小心把 /etc 权限改错导致系统起不来,排查起来非常痛苦。
3. 启用 SSH 远程登录:从安装到修改配置
3.1 安装 openssh-server 并启动服务
检查 SSH 服务端是否已安装:
bash复制dpkg -l | grep openssh-server
如果没有任何输出,说明没装。直接装:
bash复制sudo apt install -y openssh-server
安装完成后,SSH 服务一般会自动启动。验证一下:
bash复制systemctl status ssh
如果状态不是 active (running),手动启动并设置开机自启:
bash复制sudo systemctl start ssh
sudo systemctl enable ssh
注意这里服务名是 ssh 而不是 sshd,Ubuntu 的服务脚本沿用了传统命名,早期很多人执行 systemctl start sshd 会报错找不到单元,这是个经典坑。
由于桌面版自带的 openssh-client 中也有一个 ssh 命令,为了区分,装完之后建议用 ps -ef | grep sshd 确认服务端进程确实存在。看到 /usr/sbin/sshd 在跑,才算安装成功。
3.2 修改 sshd_config 核心参数
SSH 服务端的配置集中在 /etc/ssh/sshd_config,修改前先备份是一个好习惯,毕竟配错了可能导致所有人都连不上:
bash复制sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo vim /etc/ssh/sshd_config
跟我前面说的一致,新装系统默认是禁用 root 密码远程登录的,所以重点看这几个参数:
| 参数 | 建议值 | 含义 |
|---|---|---|
PermitRootLogin |
prohibit-password 或 yes |
是否允许 root 登录;yes 允许密码和密钥,prohibit-password 仅允许密钥 |
PasswordAuthentication |
yes(临时) |
是否允许密码认证;测试阶段可开,安全加固后建议关 |
PubkeyAuthentication |
yes |
是否允许公钥认证,一般默认就是 yes |
Port |
22(可改) |
SSH 监听端口,默认 22,可改成别的端口 |
如果你现在只是想快速连上去,可以临时把配置改成:
text复制PermitRootLogin yes
PasswordAuthentication yes
保存后重启 SSH 服务:
bash复制sudo systemctl restart ssh
这样再用 root 加密码登录应该就能成功了。但我要提醒你,PermitRootLogin yes 在公网环境下是一个风险比较大的配置,业务服务器上强烈不建议这样用,正确的做法是后面配合密钥登录再改回 prohibit-password,这个问题我放在第 4 部分专门讲。
3.3 防火墙放行与监听端口检查
改完配置连不上,十有八九是防火墙或者安全组的问题。Ubuntu 默认可能没有启用 ufw,但很多云镜像会预装并启用防火墙,所以必须检查:
bash复制sudo ufw status
如果是 inactive,说明本机防火墙没有拦截,问题可能出在网络或云安全组。如果 active,就要放行 SSH:
bash复制sudo ufw allow ssh
# 或者指定端口
sudo ufw allow 22/tcp
刚才如果修改了 SSH 端口,记得放行对应新端口。云服务器的话,还需要去云控制台的安全组/防火墙规则里,把相应端口加进放行列表,否则本机策略改得再对也没用。
另外可以检查 SSH 是否真的在监听:
bash复制sudo ss -tlnp | grep sshd
正常会看到类似 0.0.0.0:22 或 [::]:22 的监听记录。如果你看到的是 127.0.0.1:22,说明 sshd 只监听回环地址,外部永远连不上。这时候去 sshd_config 里检查 ListenAddress 配置,正常情况下别主动设置它,或者显式写成 0.0.0.0。
4. 从客户端连接 root:密码登录与 SSH 密钥配置
4.1 密码方式连接 root 的常规操作
服务端配置好了,客户端连接就简单了。Linux / macOS 自带的终端直接敲:
bash复制ssh root@192.168.x.x
第一次连接会提示确认主机指纹,输入 yes 回车。接着输入第 2 步设置的 root 密码,就能登入系统。
Windows 用户更省事,新系统自带的 Windows Terminal / PowerShell 里直接就能运行 ssh 命令,不需要额外装工具。如果你喜欢图形界面的多标签管理,也可以用 MobaXterm、FinalShell 这一类工具,填主机 IP、用户名 root、端口 22,密码一输就连上了。工具只是外壳,底层走的都是 OpenSSH 协议,配置思路完全一样。
如果此时依然提示 Permission denied (publickey,password),基本可以肯定是两种原因:第一,sshd_config 里 PermitRootLogin 不是 yes 且禁用了密码认证;第二,密码输错了。回去按 3.2 的内容重新检查。
4.2 SSH 密钥登录配置与常见权限问题
虽然密码登录省事,但长期使用还是建议切到密钥认证。密钥认证的核心原理是:客户端持有一对密钥,把公钥放到服务器的 ~/.ssh/authorized_keys 文件里,登录时客户端用私钥签名,服务端用公钥验证。这样即使密码泄露,没有私钥也进不来。
在客户端生成密钥对:
bash复制ssh-keygen -t ed25519 -C "your-comment"
一路回车就行。默认会在 ~/.ssh/ 下生成 id_ed25519(私钥)和 id_ed25519.pub(公钥)。然后把公钥复制到服务器上:
bash复制ssh-copy-id root@192.168.x.x
ssh-copy-id 会询问 root 密码,然后把公钥追加到服务器的 authorized_keys 中。如果你没有 ssh-copy-id,手动操作也很快。把公钥内容追加进 ~/.ssh/authorized_keys,然后设置权限:
bash复制chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
权限这个点极其重要。OpenSSH 对密钥文件的权限非常敏感,如果 authorized_keys 或 .ssh 目录权限过宽,服务端会直接忽略这个文件,表现为“密钥认证被拒绝,又回退到密码认证”。
Windows 客户端同样存在权限敏感问题,最典型的一个报错就是:
text复制Bad owner or permissions on C:\Users\thinkpad\.ssh\config
这是因为 config 文件继承的权限包含了普通用户可写,SSH 客户端为了安全直接拒绝加载。解决办法是右键文件属性,在安全选项卡里取消继承,只保留当前用户的读取权限,或者用命令行修复:
powershell复制icacls "C:\Users\thinkpad\.ssh\config" /inheritance:r /grant:r "%USERNAME%:(R)"
同样地,私钥文件 id_ed25519 也要保证当前用户独有读写权限。
4.3 安全加固建议:别让你的 SSH 裸奔
一旦能通过密钥登录,就应该立刻把之前临时打开的密码认证关掉,并限制 root 只能使用密钥。我推荐的一套基础加固组合:
text复制Port 2222
PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers root yourname
改动顺序也要讲究:先确保密钥登录已经验证通过,再去修改配置重启服务,不然把自己锁在外面真的会抓狂。特别提醒,如果你修改了端口,云安全组和本机防火墙都要同步放行新端口,否则重启服务的一瞬间你的会话就断了。
还可以安装 fail2ban 来防止暴力破解:
bash复制sudo apt install -y fail2ban
sudo systemctl enable fail2ban
它会自动监控系统日志,同一 IP 多次认证失败就临时封禁,十分推荐给直接暴露在公网的服务器。注意,公司内网或家庭虚拟机场景可以适当放宽,毕竟安全策略要和风险等级匹配,没必要为了炫技搞出额外复杂度。
5. 常见问题排查与避坑记录
5.1 连接失败场景速查表
以下是我这些年折腾 SSH 经常遇到的情况整理成的一张表,适合“连不上时对着查”:
| 报错或现象 | 大概率原因 | 处理方法 |
|---|---|---|
Connection refused |
sshd 未启动 | systemctl start ssh,确认监听端口 |
Connection timed out |
防火墙拦截、IP/端口不对 | 检查 ufw 与云安全组,ping 测试连通 |
Connection reset by peer |
SSH 配置异常、SSH 协议版本不匹配 | 查看 journalctl -u ssh -f 日志 |
Permission denied (publickey,password) |
密码错误或密钥验证没通过 | 重试密码,检查 authorized_keys 权限 |
Host key verification failed |
服务器系统重装,指纹变化 | 客户端删除旧的 known_hosts 中对应条目 |
Unable to negotiate 算法不匹配 |
客户端和服务端加密算法版本差异大 | 升级客户端,或调整 sshd_config 中 KexAlgorithms |
如果一台机器刚重装过系统,原来 known_hosts 里还留着旧指纹,会出现 Host key verification failed。在确认服务器本身没有问题的情况下,删掉本机 ~/.ssh/known_hosts 里对应的旧记录,重新连接即可。个人经验是,查问题优先看服务端日志,比瞎猜强多了:
bash复制sudo journalctl -u ssh -f
日志里会直接写出“Invalid user admin from 1.2.3.4”“Connection closed by authenticating user root”这类关键线索。
5.2 密钥登录失败的隐藏细节
密钥登录配好了,第二天突然连不上,这种情况多半不是系统配置变了,而是文件权限或目录属性出了问题。比如 /root 目录本身权限被改成 777,或者 .ssh 目录的所有者变成了别的用户,sshd 为了安全都会拒绝使用这个公钥。
新系统上最容易出现的问题是把 authorized_keys 文件放到了错误的目录。注意,服务端校验的是“目标用户的家目录下的 .ssh/authorized_keys”,root 用户就是 /root/.ssh/authorized_keys,而不是 /home/root。如果你之前手动创建了 /home/root,很容易搞混。
还有一个小细节:authorized_keys 文件不能有除了注释和密钥之外的多余内容,复制公钥时不要手滑多复制一个换行或文件标识符进去,否则密钥校验虽不报错但也会失败。排查时用 cat -A /root/.ssh/authorized_keys 看看有没有异常字符。
5.3 VSCode 远程开发连接 SSH 的配置思路
现在很多人喜欢用 VSCode 远程写代码,做法是装好 Remote - SSH 扩展,然后在连接配置里填上服务器信息。这本质上和我们上面配置的 SSH 是一样的,只是多了一层客户端封装。
首次连接时,VSCode 需要在服务器上安装一个服务端组件(~/.vscode-server),如果 root 目录空间不足或者目录权限不对,就会报错。我的经验是,先把 zsh/bash 的初始化脚本临时屏蔽掉,因为 ~/.bashrc 里有异常的输出可能会干扰 VSCode 的初始化流程。
另外,如果你在 ~/.ssh/config 里配置了多个主机,VSCode 连接时偶尔会因为 config 文件权限不对而加载失败,这个问题在 Windows 上尤其常见。修好权限之后再试,基本就能连上。
5.4 与 root 密码相关的其他坑
最后说几个和 root 密码看似相关、实则需要区分开的问题。很多人安装 MySQL / MariaDB 后尝试给数据库 root 用户设置密码,报错 ERROR 1045 (28000): Access denied for user 'root'@'localhost',或者 ERROR 1396 ... Operation ALTER USER failed,第一反应是“系统 root 密码出问题”,其实完全无关。数据库的 root 是数据库内部的超级用户,和 Ubuntu 系统 root 是两个独立体系,处理时要分开排查。
还有一个高频坑是环境变量。用 su - 和 sudo -i 切换到 root 后,当前 shell 的 PATH 和普通用户完全不同。有时候 root 下执行 apt、docker 提示命令找不到,不要怀疑命令不存在,先 echo $PATH 看一眼,再用 /usr/bin/apt 这类绝对路径去执行。出现这种问题的深层原因是 root 的环境变量没有继承普通用户的自定义配置,这也是为什么我建议尽量用 sudo -i 而不是在普通用户 shell 里混用 su。
另外一个容易被忽略的点是,如果你修改了 /etc/environment 或 /etc/profile 想给 root 配环境变量,配完一定要重新登录 root 会话,因为环境变量只在 shell 启动时加载一次,当前会话不会自动刷新。
我在实际维护 Ubuntu 服务器的过程中,最顺手的组合是:系统装好后先 sudo apt update && sudo apt upgrade,然后 sudo passwd root,安装 openssh-server,生成 ed25519 密钥,修改默认端口并禁止密码登录。整套流程跑熟之后,远程管理基本不会再为权限问题焦头烂额。希望这篇分享能把你刚踩进去的坑提前填平。
