SSH连接正常但SCP传输失败的原因分析与解决方案

2025/12/20 Linux SSH SCP 网络问题 共 4530 字,约 13 分钟

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:~ #

从会话中可以看到:

  1. SCP命令尝试传输.vimrc文件到10.0.0.36服务器的/root目录
  2. 输入密码后,连接被关闭,返回错误码255
  3. 紧接着的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

矛盾的事实

我们遇到了三个看似矛盾但同时成立的事实:

  1. 包信息显示文件存在
    dpkg -L openssh-sftp-server
    # /usr/lib/openssh/sftp-server
    # /usr/lib/sftp-server
    
  2. 实际文件系统中找不到
    ls -l /usr/lib/openssh/  # 没有 sftp-server
    ls -l /usr/lib/sftp-server  # No such file
    
  3. 包确实是已安装状态
    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命令时:

  1. SSH连接和认证成功
  2. SCP尝试使用SFTP子系统(现代OpenSSH默认行为)
  3. SSHD尝试执行/usr/lib/openssh/sftp-server
  4. 但该文件在当前overlay视图中不可见
  5. 导致exec失败,连接关闭

终极解决方案:使用internal-sftp

OpenSSH官方提供了内置的SFTP实现internal-sftp,这是解决此问题的最佳方案:

什么是internal-sftp?

  • 是OpenSSH内置的SFTP服务器实现
  • 不需要任何外部二进制文件
  • 直接由sshd进程提供服务
  • 在OSTree/容器/精简系统中100%稳定

配置步骤

  1. 修改sshd_config
    vim /etc/ssh/sshd_config
    

    删除或注释掉所有现有的Subsystem配置,只保留:

    # 唯一的Subsystem配置
    Subsystem sftp internal-sftp
    

    ⚠️ 关键点:

    • 不要有第二条Subsystem配置
    • internal-sftp是关键字,不是文件路径
    • 不要指定任何文件路径
  2. 验证配置并重启服务
    # 验证配置语法
    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失败?

这个问题的核心在于:

  1. SSH登录:只需要基本的SSH协议功能,不需要额外的子系统
  2. 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的工作原理对于解决此类问题至关重要。

文档信息

Search

    Table of Contents