빠른 버전:
ssh
& scp
내 데스크탑과 노트북에서 작동합니다. 내 Android 휴대폰에서 termux는 ssh
작동하지만 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
- 장치 C(전화): 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와 방화벽을 (일시적으로) 비활성화했지만 여전히 동일한 문제가 있습니다.
- 기반으로이 게시물, 기본 이름을 사용하도록 사용자 정의 id_rsa(및 id_rsa.pub) 파일 이름을 바꾸고 해당
~/.ssh/config
정의를 편집했습니다. 잔돈을 유지해주세요. - C에서 파일을 받거나 가져오는 대신~에서원격으로 파일을 푸시/전송하려고 합니다.도착하다리모콘. 잔돈을 유지해주세요.
- C부터 시작하여 모든 패키지가 최신 상태인지 확인합니다. 잔돈을 유지해주세요.
- 자세한 디버깅 정보를 제공하기 위해 플래그를
scp
사용하여 C에서 명령을 실행합니다 .-v
해시 등을 편집한 후 추가했습니다.페이스트빈. 내가 본 가장 중요한 점은 키가 승인된 것 같지만 마지막 줄에 "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
답변1
익스프레스 버전(TL;DR)
고쳐 쓰다: 빨리 알고 싶고, 최소한의 내용이라도 읽고 싶은 분들을 위한 제품입니다.
알다:
- 이는 실제로 Termux와 관련이 없습니다. OpenSSH 8.8+를 사용하는 모든 Linux에 영향을 미칩니다. OpenSSH 8.7p1을 사용하는 Fedora 35에서도 이 문제가 발생했습니다.
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 프로토콜을 사용합니다. 레거시 SCP 프로토콜을 사용하려면 -O 옵션이 필요합니다.
-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
(예: "오", 예전과 마찬가지로 0이 아님):릴리즈 노트openssh 8.8의 경우 주요 위험은 다음과 같습니다.
이전 버전의 scp/rcp는 원격 셸을 통해 원격 파일 이름(예: "scp 호스트:* .")의 와일드카드 확장을 수행합니다. 이에 대한 부작용은 scp(1) 명령줄에 포함된 파일 이름에 쉘 메타 문자를 큰따옴표로 묶어야 한다는 것입니다. 그렇지 않으면 원격 측에서 쉘 명령으로 해석될 수 있습니다.
저는 개인적으로 이것이 이전 명령에 익숙하고 이를 수동으로 실행하거나 가정용 컴퓨터에서 신뢰할 수 있는 스크립트를 통해 실행하는 사람들에게는 큰 위험이라고 생각하지 않습니다. 그러나 위험 평가/사용 사례는 다양할 수 있습니다. 특히 확인되지 않거나 신뢰할 수 없는 스크립트를 사용하는 비즈니스 시스템 또는 설정의 경우 더욱 그렇습니다. 이건 일부의 경우인 것 같습니다RHEL 9는 scp 프로토콜을 더 이상 사용하지 않습니다., 인용하다:
SCP 프로토콜은 수십 년이 지났고 직접적인 해결책이 없는 여러 보안 위험과 문제가 있기 때문에 이렇게 변경했습니다. 새로운 문제가 자주 보고됩니다(CVE-2020-15778이 글을 쓰는 시점에서는 최신이지만 마지막이 될지 확신할 수 없습니다.) 프로토콜은 본질적으로 인증된 세션을 신뢰할 수 있기 때문에 이를 올바르게 수정하는 것은 매우 어렵습니다.
위의 릴리스 노트와 링크, 댓글에서아치스 위키, 완전히 사용하지 않으려는 의도인 것 같습니다.SCP(예: 프로토콜) 은 및 (아래 참조) sftp
과 같은 대안을 지원합니다. rsync
회사의 향후 계획이 무엇인지 모르겠습니다.scp
주문하다예, 특히 단기적으로는 그렇습니다. 하지만 향후에는 더 이상 사용되지 않을 가능성이 높습니다.
권장 대안
스크립트에서 삽입-교체로 sftp
사용 하면 적어도 Fedora 35부터 시작해야 하는 호스트 변경이 필요하지 않으므로 삽입-교체가 더 쉬울 것입니다 .rsync
rsync
sftp
sftp
sftp <user>@<host_ip>
아래 명령은 다음을 사용하여 연결할 수 있는 한 작동합니다(이 방법으로 연결하면 "쉘" ssh
에 들어가게 됩니다 . 종료하려면 를 사용하십시오 ). 그렇지 않으면 호스트 시스템에서 이를 활성화해야 할 수도 있습니다. Fedora 35의 경우 프로세스는 다음과 같습니다.sftp
exit
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +'%F_%T').bak
sudo sed -Ei 's~^(Subsystem[ \t]+sftp[ \t]+)(/usr/lib/openssh/sftp-server)~#\1\2\n\1internal-sftp~g' /etc/ssh/sshd_config
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
기본적으로 심볼릭 링크의 내용은 대신 복사됩니다.~처럼심볼릭 링크. Rsync를 사용 -l
하면 기호 링크로 복사 또는 -L
기호 링크가 참조하는 항목 복사를 사용하여 이 동작을 제어할 수 있습니다 . 별도로 지정 하지 않는 한 (아카이브) 옵션 -a
의 기본값은 입니다 . 심볼릭 링크를 링크로 복사합니다(예: 다음과 같은 항목을 가리킴).-l
-L
sftp
아니요복사됨), 이 글을 쓰는 시점에는 이 동작을 제어할 수 있는 옵션이 없습니다. -r
옵션에 대한 문서와 해당 옵션 아래의 문서를 각각 보면 이를 확인할 수 있습니다 .man scp
man sftp
~/.ssh/config
다음은 모든 SSH를 수행하고 설정과 ID를 가져오는 거의 동일한 명령의 몇 가지 예입니다 .
디렉터리를 원격에서 로컬로 반복적으로 복사합니다.
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
업로드 구문이 다운로드 구문과 일치하지 않는 이유 는 무엇입니까 ? 당신의 추측은 나만큼 훌륭합니다. 나 자신도 이 방법의 열렬한 팬입니다. 그러나 시도해 보면 다음과 같은 일이 발생합니다(참고: 이 출력은 ssh가 올바르게 구성된 Fedora 35를 실행하는 두 시스템에서 나온 것이며 scp
인증 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
use -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)
이 문제를 해결하는 것은 매우 간단하지만 scp
저처럼 내부 인용 경로 구문을 사용하는 데 익숙하다면 직관적이지 않을 수 있습니다. -s
내부 인용을 사용하고 제거하면 됩니다. rsync
그것을 처리할 수 있을 만큼 똑똑하면 실제로 작동합니다.
따라서 위의 잘못된 명령을 다음과 같이 변경하면 됩니다.
$ rsync -saXULz --progress -e ssh \
"remoteuser@remotehost:/tmp/rsync-test/stuff from server/the data.txt" "."
모든 것이 잘 작동해야 합니다( scp
모든 것이 동일한 경로에서 잘 작동한다고 가정).