Linux SSH:验证主机、配置密钥并用 scp/sftp 传文件

安全外壳协议(SSH,Secure Shell)通过加密连接提供远程登录和命令执行,OpenSSH 的 scp 与 sftp 工具还可用于文件传输。首次连接应先核对服务器主机密钥的指纹;在确认密钥认证实际成功之前,保留原有登录方式和恢复路径。

私钥文件权限可结合Linux 文件权限与 sudo检查,超时或名称解析失败可参考网络分层排障。本课以常规 Ubuntu 26.04 LTS 或 Rocky Linux 9 系列虚拟机为参考,容器、WSL 和其他版本的服务与软件包配置可能不同。先按虚拟机环境准备(英语)核对版本,并准备控制台恢复方式。

区分客户端与服务器并安装工具

输入远程连接命令的计算机是客户端,要登录的 Linux 是服务器。服务器需要可达地址、真实用户账号、SSH 服务以及允许实际端口的网络规则。客户端须有 ssh、scp、sftp 等工具,可先用 ssh -V 查看版本。下面两组安装命令在服务器执行,只选符合发行版的一组。

Ubuntu 中,apt update 刷新包信息,apt install 才安装服务器包:

sudo apt update
sudo apt install openssh-server
sudo systemctl enable --now ssh

Rocky Linux 的对应示例:

sudo dnf install openssh-server
sudo systemctl enable --now sshd

Ubuntu 常用服务名为 ssh,Rocky Linux 常用 sshd,仍应检查实际安装结果。Ubuntu 还可能采用套接字激活:用 systemctl status ssh.service ssh.socket 同时观察服务和套接字,不能要求二者始终都处于活动状态。上面的 enable --now ssh 针对服务,不应据此忽略已启用的 ssh.socket 或为统一状态而盲目切换激活方式。

主机防火墙、云安全规则和 NAT 端口转发是独立环节。修改端口或限制认证前,保持现有会话打开并准备控制台;修改服务器配置后先用 sudo sshd -t 检查语法,再按实际服务/套接字配置安排生效操作。

首次连接先验证服务器身份

从已经信任的服务器控制台或管理渠道获得主机公钥指纹。下面第一条在服务器执行,第二条在客户端执行,不是在同一终端顺序粘贴。把 user、server.example 换成真实账号和地址;若没有 Ed25519 主机密钥,或密码策略不允许该类型,应由管理员确认实际使用的主机密钥。

sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
ssh user@server.example

比较客户端提示的 SHA256 指纹与可信渠道获得的指纹,一致后再接受。服务器主机密钥用于验证服务器身份,后面的用户密钥用于证明登录用户身份,两者不要混淆。已有服务器出现主机密钥变化警告时,先确认是否重装或合法轮换,也要考虑中间人拦截的可能。

不要为消除警告删除整个 known_hosts,也不要关闭主机密钥验证。只有确认服务器确实合法更换后,才更新对应主机和端口的那一项记录;使用非默认端口时也要核对该端口对应的记录。

生成用户密钥,只注册公钥

在客户端操作。先确认自己的 ~/.ssh 目录存在且属于本人;缺少时可用 mkdir -p ~/.ssh 创建,并按 Linux 权限要求设置为 700。确认 linux-course-key 与同名 .pub 文件尚不存在,再运行:

ssh-keygen -t ed25519 -f ~/.ssh/linux-course-key
ssh-copy-id -i ~/.ssh/linux-course-key.pub user@server.example
ssh -i ~/.ssh/linux-course-key user@server.example

若出现覆盖现有文件的询问,应中止并换一个新名称。为私钥设置口令短语,将私钥留在客户端;只把 .pub 公钥注册到服务器。ssh-copy-id 需要已有的获准登录方式。客户端没有该命令时,可按管理流程把公钥完整一行追加到目标账号的 ~/.ssh/authorized_keys,保留已有条目。

服务器端常用权限为 .ssh 目录 700、authorized_keys 文件 600,还要核对所有者及上级目录权限。不要为排障直接放宽所有权限。FIPS 或其他密码策略环境,应选择政策批准且双方支持的算法。

在新终端中验证登录。指定私钥路径并不证明最终一定使用了该密钥,也可能由代理中的其他密钥或密码后备方式完成认证。必要时查看 ssh -v -o IdentitiesOnly=yes -i ... 的实际成功认证方式;其中省略号须替换成完整密钥路径,并补上目标账号和主机。IdentitiesOnly 限制身份选择,不等于自动禁止密码后备。

用 scp 发送并取回一个文件

在客户端的独立实验目录执行,使用实验账号。先确认本地 transfer-test.txt、transfer-returned.txt 和远程同名文件不会覆盖现有资料;第一条重定向及 scp 下载都可能覆盖文件。

printf "SSH transfer test\n" > transfer-test.txt
scp -i ~/.ssh/linux-course-key transfer-test.txt user@server.example:~/transfer-test.txt
scp -i ~/.ssh/linux-course-key user@server.example:~/transfer-test.txt ./transfer-returned.txt
cmp transfer-test.txt transfer-returned.txt

前三条创建测试内容、上传到远程主目录,再下载为另一个本地文件。最后的 cmp 若无输出且退出状态为 0,表示内容相同;应紧接着用 echo $? 查看状态。先确认上传和下载成功,再判断比较结果。

当前 OpenSSH 的 scp 默认通过 SFTP 传输。旧服务端未实现 SFTP 或不支持部分路径扩展时,行为可能不同,应核对两端版本和手册,不要把所有 scp 都当成旧 SCP 协议。scp -p 用于保留时间及模式等属性,指定端口则是大写 -P。

使用交互式 sftp 与自定义端口

sftp -i ~/.ssh/linux-course-key user@server.example

建立连接后,下面的命令在 sftp 提示符中输入,不是在普通 Shell 中执行。pwd、ls 查看远程位置,lpwd、lls 查看本地位置。先确认本地测试文件存在,以及远程当前目录和下载目标不会覆盖重要文件,再上传和下载。

pwd
lpwd
ls
put transfer-test.txt
get transfer-test.txt transfer-sftp.txt
bye

put 上传本地文件,get 下载远程文件,bye 退出。退出后可在普通 Shell 中用 cmp transfer-test.txt transfer-sftp.txt 核对下载内容。若服务器端口为 2222,ssh 使用 -p 2222,scp 和 sftp 使用 -P 2222,选项放在目标主机之前。

连接被拒绝时先检查实际端口、服务和网络策略;认证失败时检查账号、密钥、所有者和权限。ssh -v 不会直接打印私钥内容,但会包含账号、路径和地址,分享前应遮盖。实验结束后只清理本次创建的文件和不再需要的公钥注册条目,保留其他用户或原有的登录资料。

官方参考

主机验证与客户端选项见 OpenSSH ssh 手册;文件传输与端口选项见 scp 手册和 sftp 手册,指纹与密钥操作见 ssh-keygen 手册。服务器配置见 Ubuntu OpenSSH 官方文档,激活方式见 Ubuntu 团队的套接字激活说明。