tập tin scp qua máy chủ trung gian


85

Tôi có quyền truy cập vào 3 máy, A, B và C. Các kết nối (ssh) duy nhất có thể là:

A -> B
B <-> C

Tôi cần lấy các tệp từ A đến C, vì vậy tôi có thể quét các tệp từ A đến B, sau đó quét chúng từ B đến C. Tuy nhiên, B không có nhiều dung lượng đĩa, vì vậy đây không phải là một tùy chọn. Có cách nào để scp các tập tin từ A đến C qua B không? Lưu ý, tôi không có quyền truy cập root trên bất kỳ máy nào, vì vậy đừng nghĩ rằng tôi có thể thiết lập bất kỳ đường hầm liên tục nào, nhưng hãy sửa tôi nếu tôi sai!


6
Tôi biết điều này không trả lời câu hỏi, nhưng đối với những người không biết về rsync hoặc không biết cách sử dụng nó để nhảy qua máy chủ, đây có thể là một mẹo hữu ích: sử dụng tùy chọn '-e' với rsync như thế này:A$ rsync <options> -e 'ssh B ssh' source C:destination
Được chỉnh sửa vào

Câu trả lời:


108

ProxyJump

Mới trong OpenSSH 7.3:

A$ scp -oProxyJump=B thefile C:destination

(Đằng sau hậu trường, điều này chỉ sử dụng ProxyCommand và ssh -W.)

ProxyCommand

Đã cập nhật để bao gồm -W từ các câu trả lời khác:

A$ scp -oProxyCommand="ssh -W %h:%p B" thefile C:destination

Nếu A đã cài đặt máy khách SSH rất cũ (không có -Whỗ trợ) hoặc nếu B được cấu hình để không cho phép chuyển tiếp TCP (nhưng vẫn cho phép các lệnh shell), hãy sử dụng các lựa chọn thay thế:

A$ scp -oProxyCommand="ssh B socat stdio tcp:%h:%p" thefile C:destination
A$ scp -oProxyCommand="ssh B nc %h %p" thefile C:destination

Ống

A$ tar cf - thefile anotherfile | ssh B "ssh C \"cd destination && tar xvf -\""
A$ (echo thefile; echo anotherfile) | cpio -o | ssh B "ssh C \"cd destination && cpio -i\""

Đối với chỉ một tệp:

A$ ssh B "ssh C \"cd destination && cat > thefile\"" < thefile

"Đường hầm" qua B

A$ ssh -f -N -L 4567:C:22 B
(continues running in background)

A$ scp -P 4567 thefile localhost:destinationPath

Khi bạn đã hoàn tất, đừng quên giết sshquá trình đã bắt đầu trước đó (đã giảm xuống nền do -f -N).

  • -fYêu cầu ssh đi đến nền ngay trước khi thực hiện lệnh. Điều này hữu ích nếu ssh sẽ yêu cầu mật khẩu hoặc cụm mật khẩu, nhưng người dùng muốn nó ở chế độ nền. Điều này ngụ ý -n.
  • -NKhông thực hiện một lệnh từ xa. Điều này rất hữu ích cho việc chuyển tiếp cổng.

Đảo ngược "đường hầm" qua B đến A

Không phải lúc nào cũng hoạt động:

A$ ssh -f -N -R 4567:localhost:22 B
(now you can reach A from B, by using localhost:4567)

B$ scp -P 4567 localhost:thefile C:destination
  • -R Chỉ định rằng các kết nối đến cổng TCP hoặc ổ cắm Unix đã cho trên máy chủ (máy chủ) từ xa sẽ được chuyển tiếp đến máy chủ và cổng cụ thể hoặc ổ cắm Unix ở phía cục bộ.

Cảm ơn rất nhiều vì những ví dụ này @grawity. Một câu hỏi - là có thể đảo ngược `tar c thefile Anotherfile | ssh B "ssh C \" cd Destination && tar xv \ ""

@dmeu: Vâng, nó có thể.
grawity

Làm cách nào để "tiêu diệt" quá trình ssh đã bắt đầu trước đó nếu tôi nói tôi đang sử dụng MacOS?
Aero Windwalker

Lưu ý: Như thường lệ, nếu bạn muốn scp từ C, mặc dù B, đến A, bạn có thể làm A$ scp -oProxyJump=B C:destination thefile.
jvriesem

@Pablo Sử dụng tốt hơn -S, sau đó và -O thoát. Hoặc ... ít nhất là pkill -f.
grawity

24

Các phiên bản của scp từ đầu năm 2011 trở về sau có thể có tùy chọn "-3":

 -3      Copies between two remote hosts are transferred through the local
         host.  Without this option the data is copied directly between
         the two remote hosts.  Note that this option disables the
         progress meter.

Nếu bạn có thứ này, bạn có thể chạy:

B$ scp -3 A:file C:file

Trong trường hợp của tôi, máy chủ A chỉ có thể truy cập từ B (được VPN). Máy chủ C ở cùng mạng LAN với B. Tôi muốn lấy một tệp từ A đến C và scp -3 đã giải quyết nó một cách xuất sắc.
Joe

Tôi gặp rắc rối với điều này khi cả hai máy chủ yêu cầu mật khẩu. Nó dường như sẽ yêu cầu cả hai cùng một lúc (hai lời nhắc mật khẩu xuất hiện trên cùng một dòng) và sau đó nó không thể chấp nhận mật khẩu của tôi. Cuối cùng tôi có thể làm cho nó hoạt động bằng cách gõ mật khẩu của mình nhiều lần (cùng một mật khẩu trên cả hai máy chủ), nhưng thật khó để tìm ra.
Colin D

8

Gần như tất cả đã được đã nói nhưng đây là đồng xu cuối cùng của tôi: Tôi sử dụng ProxyCommand biến thể mà không nchay soc. Dựa trên OpenSSH Proxy và Jumphost Cookbook, tôi đã tạo ra một cấu hình sau:

  1. Vì vậy, chúng tôi có những người chơi sau:

    • HOME_HOST: đó là nơi chúng tôi sao chép tệp vào máy chủ đích
    • HOP_HOST: chúng tôi sao chép qua máy chủ này (đăng nhập là HOP_USER)
    • TARGET_HOST: đó là đích đến của chúng tôi (được xác thực là TARGET_USER)
  2. Trước tiên tôi thêm chìa khóa công cộng địa phương của tôi từ máy chủ nhà của tôi .ssh/id_dsa.pub để .ssh/authorized_keysở cả hai hop và mục tiêu chủ. Có, cùng một khóa công khai từ chủ nhà cho cả hai. Thông thường, bạn sẽ mong đợi nó là khóa công khai HOP mà bạn phải thêm vào MỤC TIÊU.

  3. Sau đó, tôi tinh chỉnh .ssh/configmột chút bằng cách thêm mục sau:

    Host TARGET_HOST
       User TARGET_USER
       ProxyCommand ssh -W %h:%p HOP_USER@HOP_HOST
    
  4. Sau đó, thao tác sao chép đơn giản như : scp FILE TARGET_HOST:. Nó hiển thị các biểu ngữ kép từ cả nút hop và nút đích nhưng nó hoạt động.

Tất nhiên bạn có thể sử dụng ở trên để ssh trực tiếp đến mục tiêu : ssh TARGET_HOST. Nó hoạt động với scp và ssh.

Một tùy chọn khác chung hơn có thể là tiện ích sshript dường như là một loại proxy trong suốt (vpn over ssh). Vì vậy, trong trường hợp của bạn về A-> B <-> C, nó cho phép kết nối với từng nút tại mạng của C: A-> B- [CDEFG]. Nó không cần admin nhưng nó yêu cầu Python 2.7 (3.5 cũng OK) không phải lúc nào chúng ta cũng có. Đó là giá trị để thử nó.


7
ssh -L 4321:hostC:22 youruser@hostB

trong một vỏ khác:

scp -P 4321 localfile youruser@127.0.0.1

Đây là sử dụng cổng chuyển tiếp. Giới hạn duy nhất ở đây là máy chủ B cần được cấu hình để cho phép chuyển tiếp cổng. Nếu không thì điều này sẽ làm việc tốt.

Theo cách giải thích, -L-Rcho phép bạn chuyển tiếp cổng. Trong đó -L, cổng đầu tiên được cung cấp là cổng ssh sẽ bắt đầu nghe trên máy gốc (máy chủ A) và nó sẽ chuyển tiếp bất cứ thứ gì nó nhận được trên cổng đó qua kết nối SSH của bạn đến máy chủ B, sau đó định tuyến đến máy chủ C trên cổng 22.

biên tập

Tôi hơi nhầm cú pháp. Nó thiết lập một chuyển tiếp trên máy ĐỊA PHƯƠNG của bạn.


@astrofrog - nếu một trong những câu trả lời của chúng tôi thỏa mãn nhu cầu của bạn, có lẽ bạn nên chấp nhận một trong số chúng.
Brian Vandenberg

2

Câu trả lời ProxyCommand của Grawity đã có hiệu quả với tôi nhưng vì tôi không quen với SSH nên tôi đã thử nghiệm một số thứ. Tôi nghĩ rằng tôi sẽ chỉ đánh vần câu trả lời của Grawity với nhiều chi tiết hơn để giúp đỡ bất kỳ người mới nào khác với SSH như tôi. Dưới đây là các định nghĩa cho ký hiệu rõ ràng hơn:

Máy A: máy bạn đang bật

Máy chủ B: userB@ip.address.for.B (máy chủ nhảy hoặc máy chủ giữa)

Máy chủ C: userC@ip.address.for.C (máy chủ từ xa bạn muốn sao chép vào)

ProxyCommnad

    A$ scp -oProxyCommand="ssh -W %h:%p userB@ip.address.for.B" thefile userC@ip.address.for.C:destination

Ví dụ cụ thể

Vì vậy, đối với một ví dụ cụ thể, giả sử bạn có quyền truy cập vào máy chủ có IP 0.0.1.2bằng tài khoản người dùng có tên bar(Máy chủ C). Nhưng để đến được nó, trước tiên bạn phải đăng nhập vào một máy chủ có IP 0.0.1.1bằng tài khoản người dùng có tên foo(Máy chủ B). Bây giờ bạn muốn sao chép tệp baz.txtnằm trên máy hiện tại của bạn (Máy A) vào thư mục 0.0.1.2của máy chủ /home/bar/. Để sử dụng ProxyCommand ở trên cho ví dụ này, bạn sẽ thực hiện như sau:

    A$ scp -oProxyCommand="ssh -W %h:%p foo@0.0.1.1" baz.txt bar@0.0.1.2:/home/bar/

Bạn cũng có thể dễ dàng sao chép một tệp từ Máy chủ C bằng cách chuyển đổi thứ tự của tệp và đích. Vì vậy, ví dụ, nếu baz.txtđã ở trên máy chủ 0.0.1.2đặt tại /home/bar/thì bạn có thể sao chép nó vào máy tính của bạn sử dụng:

    A$ scp -oProxyCommand="ssh -W %h:%p foo@0.0.1.1" bar@0.0.1.2:/home/bar/baz.txt /destination/path/on/A

Hy vọng điều này sẽ giúp những người cần những thứ được đánh vần cho họ nhiều hơn một chút so với những người khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.