AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 709613
Accepted
zpangwin
zpangwin
Asked: 2022-07-13 12:04:27 +0800 CST2022-07-13 12:04:27 +0800 CST 2022-07-13 12:04:27 +0800 CST

ssh 在所有设备上工作,但来自某些设备的 scp 给出“连接已关闭”错误

  • 772

快速版本:

ssh在我的台式机和scp笔记本电脑上工作。从我的 android 手机上的 termuxssh可以工作,但scp不能。在这种情况下,我收到有关“连接已关闭”的错误。


扩展版

最初,当我问这个问题时,我在连接到我的 Fedora Linux 机器时,在我的 android 手机上从 termux 运行 scp 时遇到了这个问题。而且我一直很困惑,ssh所以我提供了很多调试信息。因为后来我了解到这个问题与 termux 完全无关,而与 OpenSSH 版本有关,所以我试图清理很多无关的信息转储并使其更易于访问,同时仍然保留相关的错误消息以更好地进行 seo 匹配.

设备:

  • 设备 A(计算机):运行 openssh.x86_64 8.7p1-3.fc35 的 Fedora 35
  • 设备 B(计算机):运行 openssh.x86_64 8.7p1-3.fc35 的 Fedora 35
  • device C (phone): android上的termux (我原来抓不到openssh版本,估计是v8.8或更高版本)

计算机 A 和 B 具有基本相同sshd_config的文件,所有 3 个基本相同的~/.ssh/config文件内容。

问题:

A->B、B->A、C->A 和 C->B 之间的 ssh 连接都工作正常。我对从任何一台计算机连接到我的手机都不感兴趣,并且从未在其上配置过 sshd,因此没有测试这种情况。

但是,对于通过 ssh 运行的 scp,我遇到了以下问题: A->B 和 B->A 工作,而 C->A 和 C->B 失败,出现以下错误:

$ scp -rp "[email protected]:/home/desktop-user/Pictures/test.jpg" .
scp: Connection closed
 

调试:

  • 大量验证 ssh 文件权限和所有权、~/.ssh/config设置等。没有明显问题。
  • 我(暂时)在 A 和 B 上禁用了 SELinux 和 firewalld,但仍然遇到同样的问题。
  • 根据这篇文章,我将自定义的 id_rsa(和 id_rsa.pub)文件名重命名为使用默认名称,并编辑了相应的~/.ssh/config定义。没变。
  • 我没有尝试(从 C 中)尝试从远程接收/拉取文件,而是尝试将文件推送/发送到远程。没变。
  • 从 C 开始,我确保所有软件包都是最新的。没变。
  • 从 C 中,我运行scp带有标志的命令-v以提供详细的调试信息。在编辑哈希等之后,我添加到pastebin。我看到的主要内容是密钥似乎已被接受,但最后一行表明“debug1:退出状态 127”。在线结果似乎表明scp主机上不存在......但就我而言,它是。所以还是没有变化。

主机的 sshd 配置

同样,A 和 B 具有基本相同的配置

# grep -Pv '^\s*(#|$)' /etc/ssh/sshd_config
Include /etc/ssh/sshd_config.d/*.conf
Port 22
Ciphers [email protected],aes256-ctr
LoginGraceTime 1m
PermitRootLogin no
MaxAuthTries 4
MaxSessions 6
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
UseDNS yes
AcceptEnv LANG LC_*
Subsystem   sftp    /usr/lib/openssh/sftp-server
Protocol 2
DenyUsers root docker-user
MACs [email protected],hmac-sha2-512,[email protected],hmac-sha2-256
KexAlgorithms diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
ssh scp
  • 1 1 个回答
  • 514 Views

1 个回答

  • Voted
  1. Best Answer
    zpangwin
    2022-07-13T20:27:32+08:002022-07-13T20:27:32+08:00

    快速版本 (TL;DR)

    更新:对于那些只想要快速而肮脏且阅读最少的人。

    知道:

    1. 这实际上与 Termux 无关——它影响任何使用 OpenSSH 8.8+ 的 Linux。我还在使用 OpenSSH 8.7p1 的 Fedora 35 上遇到过它
    2. 虽然sftp会在紧要关头工作,但它处理符号链接的复制方式与此不同,scp因此不要只是将其放入脚本中作为替代。更好用rsync。

    递归地将目录从远程复制到本地:

    # deprecated / insecure (see CVE link below) but works
    scp -O -rp -P <port> "<user>@<host_ip>:<SRC_PATH>" "<DST_PATH>"
     
    # secure / recommended by openssh - also works
    rsync -saLPz --port <port> -e ssh "<user>@<host_ip>:<SRC_PATH>" "<DST_PATH>"
    

    递归地将目录从本地复制到远程:

    # deprecated / insecure (see CVE link below) but works
    scp -O -rp -P <port> "<SRC_PATH>" "<user>@<host_ip>:<DST_PATH>"
     
    # secure / recommended by openssh - also works
    rsync -saLPz --port <port> -e ssh "<SRC_PATH>" "<user>@<host_ip>:<DST_PATH>"
    

    这也适用于多条路径,例如

    # copy multiple paths
    rsync -saLPz --port <port> -e ssh "<SRC_PATH_1>" "<SRC_PATH_2>" "<SRC_PATH_3>" "<user>@<host_ip>:<DST_PATH>"
     
    # copy multiple paths from array
    arrPaths=("<SRC_PATH_1>" "<SRC_PATH_2>" "<SRC_PATH_3>");
    rsync -saLPz -e ssh "${arrPaths[@]}" "<user>@<host_ip>:<DST_PATH>"
    

    根本原因

    经过大量的在线搜索,我终于在这里找到了答案——感谢 manjaro 论坛用户 zbe 和 canyue980 找到了最初的修复程序并让我了解了实际情况。

    引用canyue980:

    感谢所有提供帮助的人!我刚刚在上面的链接中找到了解决方案:

    注意:从 OpenSSH 8.8 开始,scp 实用程序默认使用 SFTP 协议。-O 选项必须用于使用旧版 SCP 协议。

    通过使用 -O 选项,它可以工作!

    scp -O 文件名目标目录

    当然,您也可以在~/.zshrc 中为其添加别名,如下所示:

    别名 scp="scp -O"

    确实,将我的命令从:

    scp -rp -P 1234 "[email protected]:/home/desktop-user/Pictures/test.jpg" .
    

    至:

    scp -rpO -P 1234 "[email protected]:/home/desktop-user/Pictures/test.jpg" .
    

    它就像一个冠军。会留下这个,希望它可以帮助别人。


    -O 的安全含义

    使用的安全含义-O(在 OLD 中是“哦” - 不是零):根据 openssh 8.8 的发行说明,听起来主要风险是:

    旧版 scp/rcp 通过远程 shell 执行远程文件名的通配符扩展(例如“scp host:* .”)。这样做的副作用是需要在 scp(1) 命令行中包含的文件名中对 shell 元字符进行双引号,否则它们可能会被解释为远程端的 shell 命令。

    对于习惯了旧命令并手动运行或通过家庭计算机上受信任的脚本运行的人来说,我个人认为这不会是一个很大的风险。但是您的风险评估/用例可能会有所不同——尤其是对于使用未经验证/不受信任的脚本的业务系统或设置。这似乎是某些情况,因为RHEL 9 正在弃用 scp 协议,理由是:

    我们做出这一改变是因为 SCP 协议已有数十年的历史,并且存在多种安全风险和问题,没有直接的解决方案。经常报告新问题(CVE-2020-15778是撰写本文时最新的问题,但我们不能确定它是否会是最后一个)并且很难正确修复它们,因为该协议本质上是值得信赖的经过身份验证的会话。

    从上面的发行说明和链接,以及arch wiki 上的说明来看,似乎其意图是完全弃用SCP(例如协议),转而支持sftp和rsync(见下文)之类的替代方案。我不清楚该scp 命令的预期未来是什么,尤其是在短期内,但它似乎是合理的,甚至可能在未来也会被弃用。


    推荐的替代品

    要在脚本中使用sftp和rsync作为插入式替换,可能rsync是更容易的插入式替换,因为它不需要对主机进行任何更改,而至少在 Fedora 35sftp中是这样。

    sftp只要您可以sftp <user>@<host_ip>像连接一样连接,下面的命令应该可以正常工作ssh(以这种方式连接会将您置于sftp“shell”中。要退出,请使用exit)。否则,您可能必须在主机上启用它。对于 Fedora 35,该过程如下:

    1. sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +'%F_%T').bak
    2. sudo sed -Ei 's~^(Subsystem[ \t]+sftp[ \t]+)(/usr/lib/openssh/sftp-server)~#\1\2\n\1internal-sftp~g' /etc/ssh/sshd_config
    3. sudo systemctl restart sshd

    完成后,您应该会看到类似这样的内容(例如,应该注释掉 sftp 服务器行,并添加一个带有 internal-sftp 的新行来代替它):

    sudo grep Subsystem /etc/ssh/sshd_config
    #Subsystem  sftp    /usr/lib/openssh/sftp-server
    Subsystem   sftp    internal-sftp
    

    如果您需要提高安全性,还可以使用组和 chroot 来限制这一点,如此处和此处所示。

    注意:scp默认情况下,复制符号链接的内容而不是将它们作为符号链接。-lRsync 允许您通过使用复制为符号链接或-L复制符号链接引用的内容来控制此行为。(-a存档)选项将默认为-l,除非-L还指定。会将符号链接复制为链接(例如,不sftp复制指向的内容)并且在撰写本文时不提供用于控制此行为的选项。您可以通过分别查看和下的选项的文档来验证这一点。-rman scpman sftp

    以下是一些大致等效命令的示例,它们都应该通过 SSH 并获取您的~/.ssh/config设置和身份:

    递归地将目录从远程复制到本地:

    scp -O -rp -P <port> "<user>@<host_ip>:<SRC_PATH>" "<DST_PATH>"
     
    rsync -saLPz --port <port> -e ssh "<user>@<host_ip>:<SRC_PATH>" "<DST_PATH>"
    

    递归地将目录从本地复制到远程:

    scp -O -rp -P <port> "<SRC_PATH>" "<user>@<host_ip>:<DST_PATH>"
     
    rsync -saLPz --port <port> -e ssh "<SRC_PATH>" "<user>@<host_ip>:<DST_PATH>"
    

    更正 sftp 语法

    编辑:2022 年 9 月 13 日:今天在重新测试时注意到我的命令sftp出现错误,因此我将它们从上面移出并添加一些免责声明。由于我上面提到的在涉及符号链接时它们如何处理复制方面存在差异,我个人并不推荐sftp作为替代品。scp

    我对使用它作为脚本中的替代品特别感兴趣。如果您只需要交互模式,请不要介意为 制作“批处理”指令文件sftp,或者已经rsync安装在您将使用的所有机器上,那么您可能不需要走这么远。我下面的笔记部分基于这个答案,我做了一些额外的测试。

    我在这里最大的抱怨(除了sftp使用不同的语法进行上传和下载)是非常糟糕的文档。看一下man sftp,语法根本没有记录(这意味着虽然该工具可以以非交互方式使用,但它只记录在批处理和交互模式下使用,并且在支持时跳出这些用例,但没有记录)。手册页没有像许多 GNU 工具那样提供常见用法的示例,甚至没有提供更详细文档的网站。并sftp -h提供少于手册页。从字面上看,如果不是这样的搜索引擎和网站,我会完全放弃sftp作为一种选择。

    1.本地拉取(例如从本地终端,从远程下载文件到本地)

    这主要是直截了当的,scp除了上面提到的差异(例如符号链接)和稍微不同的语法之外,它的工作方式有些相似。并且其中一种变体将产生交互式提示。

    # Download a single file with same name to current dir
    sftp -pC -P <port> "<user>@<host_ip>:<SRC_PATH>"
    # or
    sftp -pC -P <port> "<user>@<host_ip>:<SRC_PATH>" .
     
    # Download a single file to name and path in "<DST_PATH>"
    sftp -pC -P <port> "<user>@<host_ip>:<SRC_PATH>" "<DST_PATH>"
     
    # Download a folder and all of its contents,
    # keep the same name as the remote and save to current dir
    # note that any symlinks will copy only the symlink itself
    # and NOT the data the link references
    sftp -rpC -P <port> "<user>@<host_ip>:<SRC_PATH>" .
     
    # Now if you omit "<DST_PATH>" entirely like you can with
    # the single-file version (first command in this code-block)
    # you instead drop to an interactive prompt and have to type
    # type 'exit' to get back to your bash prompt
    # e.g. AVOID THIS IN NON-INTERACTIVE SCRIPTS!!!
    sftp -rpC -P <port> "<user>@<host_ip>:<SRC_PATH>"
    Connected to <host_ip>.
    Changing to: <SRC_PATH>
    sftp> 
    sftp> exit
      
    # Download a folder and all of its contents,
    # to name and path in "<DST_PATH>"
    # note that any symlinks will copy only the symlink itself
    # and NOT the data the link references
    sftp -rpC -P <port> "<user>@<host_ip>:<SRC_PATH>" "<DST_PATH>"
    

    2.本地推送(例如从本地终端,从本地上传文件到远程)

    首先,如果您只是尝试反转参数,就像我原来的答案一样,那么您将收到连接错误。为什么不让sftp上传语法和下载语法一致?你的猜测和我的一样好......我本来会是这种方法的忠实粉丝。但是,如果您尝试一下,会发生以下情况(注意:此输出来自运行 Fedora 35 的 2 台机器,并且正确配置了 sshscp并且rsync ... -e ssh工作正常,并且不提示进行身份验证)。

    # single file
    sftp -pC -P <port> test.txt "<user>@<host_ip>:<DST_PATH>"
    ssh: Could not resolve hostname test.txt: Name or service not known
    Connection closed.  
    Connection closed
    
    # dir
    sftp -rpC -P <port> "<SRC_PATH>" "<user>@<host_ip>:<DST_PATH>"
    ssh: Could not resolve <SRC_PATH>: Name or service not known
    Connection closed.  
    Connection closed
    

    根据我上面链接的答案,正确的方法是如下

    # push a single file from local to remote
    sftp -pC -P <port> "<user>@<host_ip>:<DST_PATH>" <<< 'put test.txt'
    # or
    echo 'put test.txt' | sftp -pC -P <port> "<user>@<host_ip>:<DST_PATH>"
    
    # push a entire dir (and its contents) from local to remote
    # notice the inner single quotes to escape <SRC_PATH>
    # for enclosing paths containing whitespace
    sftp -rpC -P <port> "<user>@<host_ip>:<DST_PATH>" <<< "put '<SRC_PATH>'"
    # or
    echo "put '<SRC_PATH>'" | sftp -rpC -P <port> "<user>@<host_ip>:<DST_PATH>"
    # or
    printf 'put "%s" "%s"\n' "<SRC_PATH>" "<DST_PATH>" | \
    sftp -rpC -P <port> "<user>@<host_ip>"
    

    我在我的脚本中发现使用类似的语法进行下载,例如

    # pull a entire dir (and its contents) from remote to local
    # notice the inner single quotes to escape <SRC_PATH>
    # for enclosing paths containing whitespace
    printf 'get "%s" "%s"\n' "<SRC_PATH>" "<DST_PATH>" | \
    sftp -rpC -P <port> "<user>@<host_ip>"
    

    不那么令人困惑,但以上所有内容都应该有效。

    要一次复制多个路径,可以使用数组(或者您可以创建一个批处理文件put,在单独的行中列出每个命令并将其传递给sftp使用该-b <batchfile>选项)。

    # copy multiple paths from array
    arrPaths=("<SRC_PATH_1>" "<SRC_PATH_2>" "<SRC_PATH_3>");
    printf 'put %s\n' "${arrPaths[@]}" | sftp -rpC -P <port> "<user>@<host_ip>:<DST_PATH>"
    

    2022 年 10 月 10 日更新:在遇到包含空格的副本的一些问题后rsync,我更新了使用该-s选项的命令(在此答案中解释)

    但是,我注意到 rsync 的不同之处scp和sftp(关于处理空格)的一个观察结果是,scp对于包含内部引号的路径总是很好,例如

    scp -rp "remoteuser@remotehost:'/tmp/rsync-test/stuff from server/the data.txt'" "."
    

    然而,如果你在 中这样做rsync,你会得到一个错误:

    $ rsync -saXULz --progress -e ssh \
      "remoteuser@remotehost:'/tmp/rsync-test/stuff from server/the data.txt'" "."
     
    receiving incremental file list
    rsync: [sender] change_dir "/home/remoteuser/'/tmp/rsync-test/stuff from server" failed: No such file or directory (2)
    rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1839) [Receiver=3.2.5]
    rsync: [Receiver] write error: Broken pipe (32)
    

    The fix for this is quite easy but maybe not intuitive if you are using to using the inner quoted path syntax from scp like I was: just use -s and get rid of the inner quotes. rsync is smart enough to handle it and it just works.

    So the above command that had an error, would just be changed to:

    $ rsync -saXULz --progress -e ssh \
      "remoteuser@remotehost:/tmp/rsync-test/stuff from server/the data.txt" "."
    

    And all should be good (assuming scp works fine for the same path).

    • 2

相关问题

  • Auto-SSH 手动工作,但不在后台工作

  • 远程运行 X 应用程序,在远程主机上运行 GUI [关闭]

  • rsync 端口 22 和 873 使用

  • SCP突然中止:管道损坏,消息验证码不正确

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve