Bagaimana cara SSH ke mesin A melalui B dalam satu perintah?

103

Saya ingin mengakses komputer, katakanlah mesin A yang berbasis di jaringan universitas saya. Namun, komputer ini hanya dapat diakses melalui jaringan internal universitas, jadi saya tidak dapat menggunakan SSH ke komputer ini dari rumah secara langsung.

Inilah yang saya lakukan sekarang:

  1. Masuk ke mesin universitas yang berbeda, katakanlah mesin B

    (Mesin B ini dapat diakses melalui SSH dari komputer di rumah saya.)

  2. Gunakan SSH pada B untuk terhubung ke A.

Apakah ada cara untuk melakukannya lebih cepat? Hanya menggunakan satu perintah ssh.

nikosdi
sumber
terkait: ssh via beberapa host
Trevor Boyd Smith

Jawaban:

97

Ya, menggunakan ProxyCommandkonfigurasi SSH Anda.

Buat file konfigurasi SSH di direktori home Anda (kecuali jika Anda ingin membuat seluruh sistem), ~/.ssh/config:

Host unibroker          # Machine B definition (the broker)
Hostname 12.34.45.56    # Change this IP address to the address of the broker
User myusername         # Change this default user accordingly 
                        # (`user@unibroker` can overwrite it)

Host internalmachine    # Machine A definition (the target host)
ProxyCommand ssh -q unibroker nc -q0 hostname.or.IP.address.internal.machine 22

Sekarang Anda dapat mencapai Mesin A secara langsung menggunakan

ssh user@internalmachine

Perhatikan juga bahwa sekarang Anda memiliki satu nama target host SSH untuk itu, Anda dapat menggunakan ini di aplikasi lain juga. Misalnya:

  • SCP untuk menyalin file.

    scp somefile user@internalmachine:~/
    
  • Dalam aplikasi GUI Anda:

    gunakan sftp://user@internalmachine/sebagai lokasi untuk menelusuri di mesin.

    Berbasis KDE (Lumba-lumba): gunakan fish://user@internalmachine/

Catatan

Ubah hostname.or.IP.address.internal.machinedan port ( 22) ke mesin yang ingin Anda jangkau seolah-olah Anda ingin dari unibrokermesin.

Bergantung pada versi netcat pada host unibroker, -q0opsi harus dihilangkan. Mengenai otentikasi; Anda pada dasarnya mengatur dua koneksi SSH dari workstation Anda. Ini berarti host unibroker dan host mesin internal diverifikasi / diautentikasi satu demi satu (untuk keypair / kata sandi dan verifikasi kunci host).

Penjelasan

Pendekatan penggunaan ProxyCommanddan 'netcat' ini hanyalah salah satu cara untuk melakukannya. Saya suka ini, karena klien SSH saya berbicara langsung ke mesin target sehingga saya dapat memverifikasi kunci host dari klien saya dan saya dapat menggunakan otentikasi kunci publik saya tanpa menggunakan kunci lain pada broker.

Masing-masing Hostmendefinisikan awal bagian host baru. Hostnameadalah nama host target atau alamat IP dari host itu. Useradalah apa yang akan Anda berikan sebagai bagian pengguna ssh user@hostname.

ProxyCommandakan digunakan sebagai pipa ke mesin target. Dengan menggunakan SSH ke mesin pertama dan secara langsung membuat 'netcat' ( nc) sederhana ke target dari sana, ini pada dasarnya hanya plaintext maju ke mesin internal dari broker di antara mereka. The -qopsi untuk membungkam setiap keluaran (hanya preferensi pribadi).

Pastikan Anda menginstal netcat di broker (biasanya tersedia secara default di Ubuntu) - baik netcat-openbsdInstal netcat-openbsd atau netcat-traditionalInstal netcat-tradisional .

Perhatikan bahwa Anda masih menggunakan SSH dengan enkripsi dua kali di sini. Sementara saluran netcat adalah teks biasa, klien SSH Anda pada PC Anda akan mengatur saluran terenkripsi lainnya dengan mesin target akhir.

gertvdijk
sumber
4
Saya harus menghapus opsi -q0 karena tidak didukung oleh mesin yang saya gunakan. Selain itu, semuanya bekerja. Ini adalah tip FANTASTIS. Terima kasih banyak. :)
Gerry
Saya mengalami masalah, jawaban Anda berfungsi dengan baik untuk saya dari terminal, tetapi saya tidak dapat melakukannya dengan menggunakan gui sftp, katanya: pesan kesalahan yang tidak tertangani, habis saat masuk.
Vikash B
@ VikashB Yah, itu benar-benar harus bekerja. Pertimbangkan untuk membuat pertanyaan BARU untuk menangani situasi spesifik Anda.
gertvdijk
Yang saya lakukan di sini adalah pertanyaan: askubuntu.com/questions/688567/…
Vikash B
1
Untuk melengkapi kata bijak dari @gertvdijk, ada wikibook hebat tentang topik ssh proxy dan melompat host yang dapat berfungsi sebagai referensi yang sangat berharga.
Travis Clarke
51

Hop dalam sekali jalan

Alternatif yang jelas untuk pendekatan ProxyCommand yang saya berikan di jawaban saya yang lain akan 'melompat' langsung ke mesin target:

ssh -t user@machineB ssh user@machineA

Perhatikan -tpada sshperintah pertama . Tanpa itu, itu akan gagal:

Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh_askpass: exec(/usr/bin/ssh-askpass): No such file or directory
Permission denied, please try again.
[...]

Ini akan memaksa TTY nyata untuk dialokasikan

Kelemahan dari ini adalah bahwa sekarang semua konfigurasi, verifikasi dan otentikasi terjadi di Mesin B, yang saya benar-benar tidak suka dalam situasi saya karena alasan keamanan. Saya suka keypair saya di PC saya sendiri dan mengotentikasi dan memverifikasi mesin target akhir dari PC saya sendiri. Selain itu, Anda hanya dapat menggunakan shell interaktif untuk SSH, jadi ini tidak akan berurusan dengan alat lain seperti SCP atau menggunakan file manager GUI Anda.

Untuk semua alasan yang disebutkan di atas, saya sangat merekomendasikan pendekatan ProxyCommand , tetapi untuk koneksi cepat ini berfungsi dengan baik.

gertvdijk
sumber
Mengapa tidak memiliki satu jawaban dengan solusi 'One Off' dan Permanen?
demure
5
@demure Begitulah cara kerja situs StackExchange ... Lihat: Apa etiket resmi menjawab pertanyaan dua kali? mengatakan "Lebih baik mengirim dua jawaban yang berbeda, daripada memasukkannya ke dalam satu jawaban." . Dan saya tidak menganggap ini sebagai solusi yang sama. Permanen / sementara bukan apa yang membuat pendekatan ini berbeda, menurut saya.
gertvdijk
Panduan lain mengatakan untuk menggunakan, selain itu, saklar -A, tetapi menunjukkan bahwa ini memiliki implikasi keamanan. Apakah Anda tahu apa artinya meneruskan, atau tidak, koneksi agen otentikasi?
Diagon
@gertvdijk super ninja di sini! Anda memiliki solusi DUA teratas. Saya belum pernah melihat itu sebelumnya. sangat keren. jauh lebih baik daripada menciptakan satu solusi mega panjang dengan solusi N (yang biasanya saya lihat).
Trevor Boyd Smith
Ini jauh lebih nyaman daripada mengatur konfigurasi yang akan menghambat ssh lain juga.
Nikhil Sahu
37

Anda bisa menggunakan -Jopsi baris perintah:

ssh -J user@machineB user@machineA

Dari man ssh:

-J [user@]host[:port]
     Connect to the target host by first making a ssh connection to
     the jump host and then establishing a TCP forwarding to the
     ultimate destination from there.  Multiple jump hops may be
     specified separated by comma characters.  This is a shortcut to
     specify a ProxyJump configuration directive.

Itu diperkenalkan di OpenSSH versi 7.3 (dirilis pada Agustus 2016). Ini tersedia di Ubuntu 16.10 dan yang lebih baru.

Erik Sjölund
sumber
3
+1 karena ini berfungsi bahkan jika Anda perlu menentukan file kunci untuk machineA
Duka
1
+1, ini adalah versi yang lebih baik dibandingkan dengan jawaban ProxyCommand saya jika semua host Anda menjalankan versi OpenSSH cukup baru.
gertvdijk
Server OpenSSH harus diinstal pada mesin A dan B dalam hal ini? Apakah saya benar mengerti?
Mikhail
17

Coba gunakan

Host <visible hostname alias>
        Controlmaster auto
        User <user>
        hostname <visible hostname>
        port <port>
        IdentityFile ~/.ssh/<id file>

Host <private LAN hostname alias>
     ProxyCommand ssh -q -W <private LAN hostname>:<private LAN port> <visible hostname alias>

di ~ / .ssh / config Anda dan lakukan semuanya dalam satu kesempatan dengan tombol yang hanya berada di komputer Anda.

Bantuan SSH
sumber
1
Ini lebih bersih daripada memasukkan netcat ke dalam campuran. Juga, kunci SSH pribadi tidak perlu ada pada Bmesin.
danemacmillan
1

Ini adalah saran yang sangat membantu. Setelah mengacaukan selama berjam-jam, saya menemukan catatan ini, & mengkonfirmasi ini berfungsi persis seperti yang didokumentasikan. Untuk menghubungkan melalui MachineA ke MachineB, dari mesin jarak jauhC:

misal: [xuser @ machineC ~] ssh -t MachineSsh MachineB

"-T" sangat penting, ssh gagal jika tidak ada. Anda akan diminta dua kali, pertama untuk kata sandi pada MachineA, kemudian kedua untuk MachineB. Juga, perhatikan bahwa ini mengasumsikan Anda memiliki pengguna "xuser" yang ditentukan pada ketiga mesin. Jika tidak, cukup gunakan sintaks ssh: "yuser @ MachineA ...". Perhatikan juga bahwa Anda dapat menggunakan titik-titik IP mentah #, jika Anda mau. Ini berguna jika Anda menautkan melalui jaringan lokal pribadi yang menggunakan IP yang tidak terpapar ke dunia - yaitu. tidak ada dalam file host lokal Anda, atau DNS apa pun. Untuk mendapatkan file dari MachineB, ke machineC jauh, Anda dapat scp dari MachineB ke MachineA, lalu dari MachineA ke machineC jauh. (Mis. MachineC jarak jauh dapat melakukan ping MachineA, tetapi bukan MachineB.) Peringatan: Saya diuji dengan Fedora dan WindowsXP, MachineA adalah XP-box yang menjalankan ICS (Internet Connection Sharing), sedangkan MachineB dan mesin jarak jauhC adalah kotak Fedora-Linux. Saran ini memecahkan masalah utama bagi saya - yaitu. akses jarak jauh yang terbatas dan dipantau ke situs jarak jauh saya. Perhatikan juga, ketika Anda "logout" dari MachineB, Anda akan melihat dua "Koneksi ke xxx.xxx.xxx.xxx ditutup." pesan.

Mcl
sumber
Jika Anda mengatur dan mengkonfigurasi otentikasi kunci publik, maka Anda tidak perlu khawatir memasukkan kata sandi Anda. Namun -tmasih diperlukan.
Felipe Alvarez
@FelipeAlvarez Anda masih harus khawatir memasukkan kata sandi kedua jika Anda tidak percaya mesin B memiliki login tanpa kata sandi ke A!
Michael
1

ProxyCommand adalah solusi bersih untuk kasus ketika Anda mengizinkan akses shell di kedua sistem. Kami ingin memberikan akses pengguna jarak jauh ke mesin internal (A) melalui broker (B), tetapi tanpa mengizinkan pengguna akses shell ke B untuk meningkatkan keamanan. Ini berhasil:

Ganti shell login

Ganti shell login (gunakan chsh) untuk extuserpada broker dengan skrip berikut (disimpan dalam file):

#!/bin/sh   # this is essential to avoid Exec format error
ssh internaluser@A

Asalkan tidak ada kata sandi login telah diatur di extuser @ B untuk pengguna jarak jauh dan di internaluser @ A untuk extuser @ B, maka menjalankan perintah berikut akan langsung membawa pengguna jarak jauh ke A

ssh extuser@B

Kiat : Buat pengaturan yang diperlukan agar tidak ada kata sandi login yang diotorisasi pada extuser @ B sebelum mengubah ke shell login khusus. Setelah perubahan, karena akun ini tidak dapat diakses oleh siapa pun melalui shell, hanya sudoer @ B yang dapat membuat perubahan pada file berwenang_kunci dengan mengeditnya secara langsung.

sudo vi ~extuser/.ssh/authorized_keys
sudo touch ~extuser/.hushlogin

Baris terakhir adalah untuk menekan tampilan spanduk masuk dari B, sehingga pengguna jarak jauh memiliki akses transparan ke A.

Sunthar
sumber
Pendekatan yang sangat menarik. Namun, kelemahan utama dari ini adalah: 1) Penggunaan terbatas pada penggunaan SSH standar (tidak ada dukungan SFTP / SCP). 2) Seorang pengguna tidak dapat memilih host target lain selain dari yang tunggal (karena hardcoded dalam shell login) 3) Validasi kunci host tidak dapat dilakukan dari workstation ke host target akhir (karena penggunaan biner SSH broker) . 4) Kunci pribadi bagi pengguna untuk mengakses host target akhir berada pada broker daripada dengan pengguna. Ini memungkinkan peniruan pengguna oleh admin (yang biasanya tidak mungkin dilakukan).
gertvdijk
Semua poin benar, terima kasih telah menguraikan. Namun, tujuan utamanya adalah untuk menyediakan akses tepercaya pengguna ssh ke A tanpa masuk ke B. Karena hanya admin yang dapat menambahkan kunci publik dari pengguna tepercaya pada B (melalui sudo, tanpa login), ini sudah menyiratkan bahwa pengguna telah ( admin) akses ke kunci pribadi extuser @ B (bukan pengguna tepercaya di luar), dan telah mengaturnya, sejak awal!
Sunthar
1

Anda berarti Anda memerlukan beberapa jumper :)

Baru-baru ini, saya menemukan masalah ini dengan jumper1 jumper2 dan mesin terakhir saya, seperti untuk sol saya

naskah lokal:

#!/bin/bash
sshpass -p jumper1Passwd ssh -t jumper1@jumper1IP ./Y00.sh

kemudian pada jumper ke-1 (yang merupakan router saya), saya menempatkan skrip bernama Y00.sh:

ssh -tt jumper2@jumper2 -i ~/.ssh/id_rsa sshpass -p finalPassWord ssh -tt final@final

Anda dapat menggantinya dengan IP dan kata sandi Anda, semoga berhasil!

Z-Y00
sumber