SSH连接正常但SCP传输失败的原因分析与解决方案
在日常的Linux系统管理工作中,我们经常会遇到这样的问题:可以通过SSH正常连接到服务器,但使用SCP传输文件时却失败了。这种情况往往让人困惑,因为SSH和SCP都是基于SSH协议的,为什么一个能工作,另一个却不行呢?
问题现象分析
让我们先看一下用户提供的终端会话:
0 ✓ 11:06:23 root@rocky9.6-12,10.0.0.52:~ # scp .vimrc root@10.0.0.36:/root
root@10.0.0.36's password:
Connection closed
255 ✗ 11:07:05 root@rocky9.6-12,10.0.0.52:~ # ssh root@10.0.0.36
root@10.0.0.36's password:
Welcome to openKylin 2.0 SP2 (GNU/Linux 6.6.0-17-generic x86_64)
* Support: `https://openkylin.top`
Web console: `https://openkylin36:9090/` or `https://10.0.0.36:9090/`
You do not have any new mail.
Last login: Sat Dec 20 09:53:25 2025 from 10.0.0.1
0 ✓ 11:07:20 root@openkylin36,10.0.0.36:~ # exit
注销
Connection to 10.0.0.36 closed.
0 ✓ 11:07:25 root@rocky9.6-12,10.0.0.52:~ #
从会话中可以看到:
- SCP命令尝试传输
.vimrc文件到10.0.0.36服务器的/root目录 - 输入密码后,连接被关闭,返回错误码255
- 紧接着的SSH连接尝试却成功了,可以正常登录到服务器
这种现象表明:
- 网络连接是正常的
- SSH服务是运行的
- 认证机制是正常的
- 但SCP协议的某个环节出现了问题
可能的原因及解决方案
1. SCP命令语法错误
现象:命令格式不正确,导致SCP无法正确解析目标路径
解决方案: 确保SCP命令格式正确:
# 正确格式:scp 源文件 目标用户@目标服务器:目标路径
scp .vimrc root@10.0.0.36:/root/
# 也可以指定目标文件名
scp .vimrc root@10.0.0.36:/root/.vimrc
2. SSH配置文件限制
现象:服务器端SSH配置文件中限制了SCP命令的使用
解决方案: 检查服务器端/etc/ssh/sshd_config文件,确保以下配置没有限制SCP:
# 确保没有设置ForceCommand限制为特定命令
# ForceCommand internal-sftp # 这会禁用SCP
# 确保Subsystem配置正确
Subsystem sftp /usr/lib/openssh/sftp-server
# 如果使用了Match块,确保没有针对特定用户或组禁用SCP
# Match User root
# ForceCommand internal-sftp
如果修改了配置文件,需要重启SSH服务:
systemctl restart sshd
3. 目标目录权限问题
现象:虽然是root用户,但目标目录可能存在特殊权限设置或文件系统问题
解决方案: 检查目标目录权限:
# 登录到目标服务器后执行
ls -ld /root
确保目标目录存在且可写:
# 如果目录不存在,创建它
mkdir -p /root
# 确保权限正确
chmod 700 /root
4. 文件系统问题
现象:目标文件系统已满或只读
解决方案: 检查目标服务器的文件系统状态:
# 检查磁盘空间
df -h
# 检查文件系统挂载状态
mount | grep /root
如果文件系统只读,尝试重新挂载:
mount -o remount,rw /
5. SELinux或防火墙限制
现象:SELinux或防火墙规则限制了SCP操作
解决方案:
检查SELinux状态
# 查看SELinux状态
getenforce
# 如果是Enforcing,检查审计日志
audit2why < /var/log/audit/audit.log
# 临时关闭SELinux测试(不推荐生产环境)
setenforce 0
检查防火墙规则
# 使用iptables检查
iptables -L -n
# 使用firewalld检查
firewall-cmd --list-all
确保防火墙没有阻止SSH或相关端口。
6. 服务器端SCP服务问题
现象:SCP服务未安装或配置错误
解决方案:
# 检查openssh-clients是否安装(客户端和服务器端都需要)
# CentOS/RHEL
rpm -qa | grep openssh-clients
# Ubuntu/Debian
dpkg -l | grep openssh-client
# 安装SCP组件
yum install -y openssh-clients # CentOS/RHEL
apt install -y openssh-client # Ubuntu/Debian
7. 客户端配置问题
现象:客户端SSH配置影响了SCP操作
解决方案: 检查客户端~/.ssh/config文件,确保没有针对目标服务器的特殊配置影响SCP:
cat ~/.ssh/config
8. 网络设备限制
现象:中间网络设备(如防火墙、路由器)限制了SCP流量
解决方案:
- 检查网络设备的日志
- 尝试使用不同的网络路径
- 检查MTU设置
# 检查MTU设置
ifconfig | grep mtu
# 尝试调整MTU
ifconfig eth0 mtu 1400
根本原因:OpenKylin的OSTree架构导致的”显示与实际不一致”
通过用户提供的系统日志和进一步诊断,我们发现了SCP失败的根本原因,这是一个与OpenKylin系统架构相关的特殊问题:
sshd[3558]: Accepted password for root from 10.0.0.52 port 48292 ssh2
sshd[3558]: pam_unix(sshd:session): session opened for user root(uid=0) by (uid=0)
sshd[3571]: subsystem request for sftp by user root
sshd[3571]: error: subsystem: cannot stat /usr/lib/openssh/sftp-server: No such file or directory
sshd[3571]: subsystem request for sftp failed, subsystem not found
sshd[3558]: pam_unix(sshd:session): session closed for user root
矛盾的事实
我们遇到了三个看似矛盾但同时成立的事实:
- 包信息显示文件存在:
dpkg -L openssh-sftp-server # /usr/lib/openssh/sftp-server # /usr/lib/sftp-server - 实际文件系统中找不到:
ls -l /usr/lib/openssh/ # 没有 sftp-server ls -l /usr/lib/sftp-server # No such file - 包确实是已安装状态:
dpkg -l | grep openssh-sftp-server # ii openssh-sftp-server 1:9.6p1-ok6 amd64 secure shell (SSH) sftp server module
架构原因:OSTree + Overlay
这个矛盾现象是OpenKylin系统架构的正常表现:
- OSTree系统:OpenKylin使用OSTree进行系统管理,它维护一个不可变的系统树
- Overlay文件系统:运行时使用overlay文件系统在不可变基础上创建可写层
- dpkg与OSTree的差异:
dpkg -L显示的是包的逻辑内容- 实际文件系统中看到的是当前overlay视图
- 某些包文件可能不会暴露在运行时文件系统中
问题机制
当执行SCP命令时:
- SSH连接和认证成功
- SCP尝试使用SFTP子系统(现代OpenSSH默认行为)
- SSHD尝试执行
/usr/lib/openssh/sftp-server - 但该文件在当前overlay视图中不可见
- 导致exec失败,连接关闭
终极解决方案:使用internal-sftp
OpenSSH官方提供了内置的SFTP实现internal-sftp,这是解决此问题的最佳方案:
什么是internal-sftp?
- 是OpenSSH内置的SFTP服务器实现
- 不需要任何外部二进制文件
- 直接由sshd进程提供服务
- 在OSTree/容器/精简系统中100%稳定
配置步骤
- 修改sshd_config:
vim /etc/ssh/sshd_config删除或注释掉所有现有的Subsystem配置,只保留:
# 唯一的Subsystem配置 Subsystem sftp internal-sftp⚠️ 关键点:
- 不要有第二条Subsystem配置
internal-sftp是关键字,不是文件路径- 不要指定任何文件路径
- 验证配置并重启服务:
# 验证配置语法 sshd -t # 重启SSH服务 systemctl restart ssh
立即验证
在客户端(10.0.0.52)上测试:
# 测试SCP
scp .vimrc root@10.0.0.36:/root/.vimrc
# 测试SFTP
sftp root@10.0.0.36
✅ 不会再有Connection closed ✅ 不依赖/usr/lib是否可见 ✅ 不怕系统升级/overlay切换
为什么推荐internal-sftp?
| 方案 | 稳定性 | 依赖 | 适用场景 |
|---|---|---|---|
| 外部sftp-server | ❌ 不稳定 | 依赖文件系统中的二进制文件 | 传统非OSTree系统 |
| internal-sftp | ✅ 100%稳定 | 无外部依赖 | OSTree/容器/Kubernetes/精简系统 |
企业级应用
internal-sftp已经成为众多企业级系统的默认选择:
- Ubuntu Server
- Debian hardened系统
- Kubernetes节点
- OSTree系统
深入理解:为什么SSH可以工作但SCP失败?
这个问题的核心在于:
- SSH登录:只需要基本的SSH协议功能,不需要额外的子系统
- SCP传输:现代OpenSSH默认使用SFTP子系统实现文件传输,而不是传统SCP协议
当SFTP子系统请求失败时,整个SCP操作就会失败,即使基础SSH连接是正常的。
总结
在OpenKylin 2.0 SP2系统上,SCP失败的根本原因是OSTree架构导致的文件系统视图不一致。虽然openssh-sftp-server包已安装且dpkg显示包含所需文件,但这些文件在实际运行时的overlay视图中不可见。
解决这个问题的最佳方案是使用OpenSSH内置的internal-sftp,它不依赖任何外部文件,在OSTree系统中100%稳定可靠。
一句话终极总结
OpenKylin上SCP秒断,不要修路径,直接用
Subsystem sftp internal-sftp
这个问题展示了国产Linux发行版在采用现代系统架构时可能遇到的特殊挑战,理解OSTree+overlay的工作原理对于解决此类问题至关重要。
文档信息
- 本文作者:soveran zhong
- 本文链接:https://blog.clockwingsoar.cyou/2025/12/20/ssh-works-but-scp-fails/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)