Apakah ada proxy reverse host SSH virtual berbasis nama?

36

Saya telah tumbuh cukup menyukai proxy reverse HTTP di lingkungan pengembangan kami dan menemukan proxy reverse host virtual berbasis DNS cukup berguna. Hanya memiliki satu port (dan port standar) yang terbuka di firewall membuatnya lebih mudah untuk manajemen.

Saya ingin menemukan sesuatu yang mirip dengan melakukan koneksi SSH tetapi belum beruntung. Saya lebih suka tidak hanya menggunakan tunneling SSH karena itu membutuhkan membuka rentang port selain standar. Adakah yang bisa melakukan ini di luar sana?

Bisakah HAProxy melakukan ini?

ahanson
sumber
Apakah transfer file aplikasi yang Anda maksudkan, atau akses SSH aktual ke host?
Kyle Hodgson
Akses SSH langsung ke tuan rumah adalah tujuannya. Kebutuhan ini berasal dari keinginan untuk menjalankan server Mercurial di rumah tetapi server kami ada di belakang firewall. Saat ini saya sedang mengerjakan pengaturan versi HTTP tetapi saya ingin menggunakan SSH alih-alih HTTP. Akses SSH langsung ke server lain akan menjadi bonus jika ini memungkinkan.
ahanson
Ini masalah yang sangat menyebalkan.
bias
Pemahaman saya adalah bahwa HAProxy sekarang mendukung ini melalui SNI. Meskipun saya belum bisa melakukan ini.
Carel

Jawaban:

24

Saya tidak percaya SSH berbasis nama adalah sesuatu yang akan dimungkinkan mengingat bagaimana protokol bekerja.

Berikut ini beberapa alternatif.

  • Yang bisa Anda lakukan adalah mengatur host yang menjawab port 22 untuk bertindak sebagai gateway. Kemudian Anda dapat mengkonfigurasi server ssh untuk meneruskan permintaan ke bagian dalam berdasarkan kunci. Contoh SSH Gateway dengan kunci

  • Anda dapat menyesuaikan klien Anda untuk menggunakan host itu sebagai proxy. Artinya, itu akan ssh ke host gateway, dan kemudian menggunakan host itu untuk membuat koneksi ke host internal. Proxy SSH dengan konfigurasi klien .

  • Anda juga dapat mengatur proxy http sederhana di tepi. Kemudian gunakan itu untuk memungkinkan koneksi masuk. SSH melalui proksi HTTP .

Tentunya dengan semua hal di atas, pastikan Anda mengkonfigurasi dan mengunci gateway dengan benar cukup penting.

Sakit kepala
sumber
18

Saya telah mencari solusi untuk masalah ini hidup dan mati selama 16 bulan terakhir. Tetapi setiap kali saya melihat, tampaknya tidak mungkin untuk melakukan ini dengan protokol SSH sebagaimana ditentukan dalam RFC yang relevan dan diimplementasikan oleh implementasi besar.

Namun jika Anda bersedia untuk menggunakan klien SSH yang sedikit dimodifikasi dan Anda bersedia untuk menggunakan protokol dengan cara yang tidak persis dimaksudkan ketika mereka dirancang, maka itu mungkin untuk dicapai. Lebih lanjut tentang ini di bawah ini.

Kenapa itu tidak mungkin

Klien tidak mengirim nama host sebagai bagian dari protokol SSH.

Mungkin mengirim nama host sebagai bagian dari pencarian DNS, tetapi itu mungkin di-cache, dan jalur dari klien melalui resolvers ke server otoritatif mungkin tidak melewati proxy, dan bahkan jika itu terjadi, tidak ada cara yang kuat untuk mengaitkan pencarian DNS tertentu dengan klien SSH tertentu.

Tidak ada yang mewah yang dapat Anda lakukan dengan protokol SSH itu sendiri. Anda harus memilih server tanpa melihat spanduk versi SSH dari klien. Anda harus mengirim spanduk ke klien, sebelum itu akan mengirim apa pun ke proxy. Spanduk dari server bisa berbeda, dan Anda tidak memiliki kesempatan untuk menebak, mana yang benar untuk digunakan.

Meskipun spanduk ini dikirim tanpa enkripsi, Anda tidak dapat memodifikasinya. Setiap bit dari spanduk itu akan diverifikasi selama pengaturan koneksi, jadi Anda akan menyebabkan kegagalan koneksi sedikit di telepon.

Kesimpulannya bagi saya cukup jelas, kita harus mengubah sesuatu di sisi klien untuk membuat konektivitas ini berfungsi.

Sebagian besar solusi adalah merangkum lalu lintas SSH di dalam protokol yang berbeda. Orang juga bisa membayangkan penambahan pada protokol SSH itu sendiri, di mana banner versi yang dikirim oleh klien menyertakan nama host. Ini dapat tetap kompatibel dengan pengungkit yang ada, karena bagian dari spanduk saat ini ditentukan sebagai bidang identifikasi formulir gratis, dan meskipun klien biasanya menunggu spanduk versi dari server sebelum mengirimkan milik mereka, protokol tersebut mengizinkan klien untuk mengirim spanduk mereka. pertama. Beberapa versi terbaru dari ssh client (misalnya yang ada di Ubuntu 14.04) mengirim banner tanpa menunggu banner server.

Saya tidak tahu ada klien, yang telah mengambil langkah-langkah untuk memasukkan nama host dari server di spanduk ini. Saya telah mengirim patch ke milis OpenSSH untuk menambahkan fitur seperti itu. Tapi itu ditolak berdasarkan keinginan untuk tidak mengungkapkan nama host kepada siapa pun yang mengintip lalu lintas SSH. Karena nama host rahasia pada dasarnya tidak sesuai dengan operasi proksi berbasis nama, jangan berharap untuk melihat ekstensi SNI resmi untuk protokol SSH dalam waktu dekat.

Solusi nyata

Solusi yang paling berhasil bagi saya adalah menggunakan IPv6.

Dengan IPv6 saya dapat memiliki alamat IP terpisah yang ditetapkan untuk setiap server, sehingga gateway dapat menggunakan alamat IP tujuan untuk mengetahui server mana yang akan dikirimi paket. Klien SSH kadang-kadang mungkin berjalan di jaringan di mana satu-satunya cara untuk mendapatkan alamat IPv6 adalah dengan menggunakan Teredo. Teredo diketahui tidak bisa diandalkan, tetapi hanya ketika ujung IPv6 asli dari koneksi menggunakan relay Teredo publik. Seseorang bisa dengan mudah meletakkan relay Teredo di gateway, tempat Anda menjalankan proxy. Miredo dapat diinstal dan dikonfigurasi sebagai relay dalam waktu kurang dari lima menit.

Sebuah solusi

Anda dapat menggunakan host host / bastion. Pendekatan ini dimaksudkan untuk kasus-kasus di mana Anda tidak ingin mengekspos port SSH dari masing-masing server langsung ke internet publik. Itu memang memiliki manfaat tambahan untuk mengurangi jumlah alamat IP eksternal yang Anda butuhkan untuk SSH, itulah sebabnya mengapa ini dapat digunakan dalam skenario ini. Fakta bahwa itu adalah solusi yang dimaksudkan untuk menambahkan lapisan perlindungan lain untuk alasan keamanan tidak mencegah Anda menggunakannya ketika Anda tidak membutuhkan keamanan tambahan.

ssh -o ProxyCommand='ssh -W %h:%p user1@bastion' user2@target

Kotor untuk diretas untuk membuatnya berfungsi jika solusi nyata (IPv6) berada di luar jangkauan Anda

Retas yang akan saya uraikan seharusnya hanya digunakan sebagai upaya terakhir. Bahkan sebelum Anda berpikir tentang menggunakan peretasan ini, saya sangat menyarankan untuk mendapatkan alamat IPv6 untuk masing-masing server yang ingin Anda jangkau secara eksternal melalui SSH. Gunakan IPv6 sebagai metode utama Anda untuk mengakses server SSH Anda dan hanya gunakan peretasan ini saat Anda perlu menjalankan klien SSH dari jaringan khusus IPv4 di mana Anda tidak memiliki pengaruh apa pun untuk menerapkan penyebaran IPv6.

Idenya adalah bahwa lalu lintas antara klien dan server harus benar-benar berlaku untuk lalu lintas SSH. Tetapi proxy hanya perlu cukup memahami tentang aliran paket untuk mengidentifikasi nama host. Karena SSH tidak menentukan cara untuk mengirim nama host, Anda dapat mempertimbangkan protokol lain yang memang menyediakan kemungkinan seperti itu.

HTTP dan HTTPS keduanya memungkinkan klien untuk mengirim nama host sebelum server mengirim data apa pun. Pertanyaannya sekarang adalah, apakah mungkin untuk membangun aliran byte yang secara simultan valid sebagai lalu lintas SSH dan sebagai HTTP dan HTTPS. HTTPs bukan non-starter, tetapi HTTP mungkin (untuk definisi HTTP yang cukup liberal).

SSH-2.0-OpenSSH_6.6.1 / HTTP/1.1
$: 
Host: example.com

Apakah ini terlihat seperti SSH atau HTTP untuk Anda? Ini adalah SSH dan benar-benar sesuai RFC (kecuali beberapa karakter biner agak rusak oleh rendering SF).

String versi SSH menyertakan bidang komentar, yang di dalamnya memiliki nilai / HTTP/1.1. Setelah baris baru SSH memiliki beberapa data paket biner. Paket pertama adalah MSG_SSH_IGNOREpesan yang dikirim oleh klien dan diabaikan oleh server. Payload yang harus diabaikan adalah:

: 
Host: example.com

Jika proxy HTTP cukup liberal dalam apa yang diterimanya, maka urutan byte yang sama akan ditafsirkan sebagai metode HTTP yang disebut SSH-2.0-OpenSSH_6.6.1dan data biner pada awal pesan abaikan akan ditafsirkan sebagai nama header HTTP.

Proxy tidak akan mengerti metode HTTP atau header pertama. Tapi itu bisa memahami Hostheader, yang dibutuhkan untuk menemukan backend.

Agar ini berfungsi, proksi harus dirancang dengan prinsip bahwa hanya perlu memahami cukup HTTP untuk menemukan backend, dan setelah backend ditemukan, proksi hanya akan melewati stream byte mentah dan meninggalkan penghentian nyata. koneksi HTTP yang harus dilakukan oleh backend.

Mungkin terdengar seperti peregangan untuk membuat begitu banyak asumsi tentang proksi HTTP. Tetapi jika Anda ingin menginstal perangkat lunak baru yang dikembangkan dengan maksud untuk mendukung SSH, maka persyaratan untuk proxy HTTP tidak terdengar terlalu buruk.

Dalam kasus saya sendiri, saya menemukan metode ini berfungsi pada proksi yang sudah diinstal tanpa mengubah kode, konfigurasi, atau lainnya. Dan ini untuk proxy yang ditulis hanya dengan HTTP dan tanpa SSH.

Bukti konsep klien dan proksi . (Penafian bahwa proxy adalah layanan yang dioperasikan oleh saya. Jangan ragu untuk mengganti tautan begitu proxy lain dikonfirmasi untuk mendukung penggunaan ini.)

Peringatan hack ini

  • Jangan gunakan itu. Lebih baik menggunakan solusi nyata, yaitu IPv6.
  • Jika proxy mencoba untuk memahami lalu lintas HTTP, itu pasti akan rusak.
  • Mengandalkan klien SSH yang dimodifikasi tidak baik.
kasperd
sumber
Bisakah Anda menguraikan apa yang Anda maksud dengan the gateway can use the destination IP address to find out which server to send the packet to, dalam solusi IPv6?
Jacob Ford
@JacobFord Kunci untuk memahami kalimat itu adalah saya menggunakan kata gateway bukan proxy . Dengan IPv6 Anda mendapatkan alamat IP yang cukup untuk menetapkan satu untuk setiap host dan masih memiliki alamat untuk cadangan. Semua mesin yang Anda tempatkan di belakang proxy akan memiliki alamat IP sendiri yang merupakan tujuan Anda menyelesaikannya. Jadi Anda tidak lagi memerlukan proxy, klien mengirim lalu lintas mereka ke alamat IP dari host yang diinginkan, dan Anda dapat mengarahkan lalu lintas langsung ke sana.
kasperd
untuk bagian solusinya, ada saklar perintah yang relatif baru untuk ssh -J, sehingga Anda dapat menggunakan: ssh -J user1 @ depan user2 @ target
PMN
3

Saya tidak percaya ini adalah sesuatu yang mungkin, setidaknya seperti yang Anda gambarkan, meskipun saya ingin terbukti salah. Tampaknya klien tidak mengirimkan nama host yang ingin disambungkan (setidaknya di tempat kosong). Langkah pertama koneksi SSH tampaknya adalah mengatur enkripsi.

Selain itu, Anda akan memiliki masalah dengan verifikasi kunci host. Klien SSH akan memverifikasi kunci berdasarkan alamat IP serta nama host. Anda akan memiliki beberapa nama host dengan kunci yang berbeda, tetapi IP yang sama dengan yang Anda hubungkan.

Solusi yang mungkin adalah memiliki host 'bastion', di mana klien dapat ssh masuk ke mesin itu, mendapatkan shell normal (atau dibatasi jika diinginkan), dan kemudian dapat ssh ke host internal dari sana.

Menandai
sumber
Konsep bastion adalah apa yang kami setup saat ini tetapi bermasalah untuk kontrol versi saya (tanpa usaha ekstra).
ahanson
Sangat menjengkelkan karena ssh tidak mengirim fqdn dan menangani DNS di sisi klien. Saya kira orang tidak khawatir tentang IP publik mengasapi dan NAT ketika sebagian besar protokol tingkat aplikasi TCP / IP dibuat. Karena, serius, Anda harus dapat melakukan NAT berbasis FQDN dengan iptables (yaitu filter kernel).
bias
Hostkey bisa menjadi kunci dari proxy terbalik. Ini adalah manfaat jika Anda mempercayai keamanan backend, karena Anda memiliki kendali atas jaringan internal dan host.
rox0r
@bias Anda tidak dapat melakukan NAT berdasarkan nama host, bahkan jika protokol tingkat tinggi mengirim nama host. Alasan itu tidak dapat dilakukan adalah, bahwa pilihan backend harus dilakukan ketika paket SYN diterima, tetapi nama host hanya dikirim setelah SYN telah diproses dan SYN-ACK telah dikembalikan. Namun Anda dapat menggunakan proxy lapisan aplikasi yang sangat tipis untuk protokol yang mengirimkan nama host, seperti http dan https.
kasperd
3

Ada anak baru di blok itu. SSH piper akan merutekan koneksi Anda berdasarkan nama pengguna yang telah ditentukan, yang harus dipetakan ke host dalam. Ini adalah solusi terbaik dalam konteks reverse-proxy.

Piper SSh di github

Tes pertama saya dikonfirmasi, SSH dan SFTP keduanya berfungsi.

Király István
sumber
Itu efektif serangan MITM. Saya berharap itu akan pecah di setiap pengaturan yang dilindungi terhadap serangan MITM.
kasperd
1
Sebenarnya pesta hosting keduanya, tuan rumah dan pria di tengah, sehingga hanya keduanya yang terlibat.
Király István
@ KirályIstván ini adalah proyek yang luar biasa dan membuktikan bahwa jawaban lain tidak 100% benar. Saya membuat alat serupa berdasarkan pada berdasarkan github.com/gliderlabs/sshfront dan beberapa bash / python (Saya tidak bisa membukanya tetapi tidak begitu menarik - bash menjalankan ssh client dan python digunakan sebagai auth handler). Tapi saya punya satu masalah dengan solusi saat ini. Itu tidak mendukung sftp (scp works). Itu hang mencoba menjalankan subsistem debug1: Sending subsystem: sftp. Ternyata kemeja-depan tidak mendukung subsistem. Apakah Anda mendukung hem di piper SSh?
Maciek Sawicki
1
@ MaciekSawicki Saya bukan penulis. Saya hanya menggunakannya dalam proyek saya. .)
Király István
2

Saya bertanya-tanya apakah Honeytrap (honeypot interaksi rendah) yang memiliki mode proxy tidak dapat dimodifikasi untuk mencapai itu.

Honeypot ini dapat meneruskan protokol apa pun ke komputer lain. Menambahkan sistem vhost berbasis nama (seperti yang diterapkan oleh Apache) dapat membuatnya menjadi proxy terbalik yang sempurna untuk protokol apa pun?

Saya tidak memiliki keterampilan untuk mencapai itu, tetapi mungkin itu bisa menjadi proyek yang hebat.

Kafeine
sumber
ide bagus!
bias
1
Fitur vhost di Apache bergantung pada klien yang mengirim nama host sebelum data telah dikirim dari server. Protokol SSH tidak melibatkan nama host seperti itu, jadi saya tidak melihat bagaimana Anda bahkan mulai menerapkan fitur seperti itu. Tetapi jika Anda dapat menguraikan ide-ide Anda, saya akan dengan senang hati menerapkan bukti konsep atau memberi tahu Anda, mengapa itu tidak berhasil.
kasperd
1

Karena jumlah port / host yang ingin Anda akses di belakang firewall meningkat, kenyamanan VPN meningkat.

Saya tidak suka VPN.

alex
sumber
1

karena cara kerja ssh saya pikir itu tidak mungkin. Mirip dengan https Anda harus memiliki IP (eksternal) yang berbeda untuk host yang berbeda, karena gateway tidak tahu ke mana Anda ingin terhubung karena semua yang ada di ssh dienkripsi

Jure1873
sumber