Meneruskan port lokal atau file socket ke file socket jauh

24

Pertanyaan cepat - Saya menjalankan dua kotak linux, satu desktop saya sendiri dan yang lainnya VPS saya. Untuk alasan keamanan pada ujung VPS saya memilih koneksi soket ke MySQL ( /var/run/mysqld/mysql.sock). Saya tahu saya bisa membuat terowongan seperti ini: ssh -L 3307:127.0.0.1:3306 [email protected]jika saya mengatur server sql jarak jauh untuk mendengarkan pada beberapa port, tetapi yang ingin saya ketahui adalah dapatkah saya melakukan sesuatu seperti: ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.sockdengan demikian tunneling dua soket, sebagai lawan dari dua port?

Solusi yang bisa diterima juga adalah meneruskan port lokal ke file socket jarak jauh, tetapi jika memungkinkan saya berusaha untuk tidak menjalankan server tcp pada kotak remote.

(dan ya, saya tahu tcp akan lebih mudah).


sumber
Jika alasan Anda tidak ingin menggunakan TCP pada kotak mySQL adalah karena masalah keamanan (yaitu serangan jarak jauh, dll.) Anda dapat menyembunyikannya dengan firewall, dan jika itu tidak cukup baik, buatlah mySQL hanya mendengarkan 127.0.0.1 untuk koneksi TCP-nya, maka Anda dapat melakukan tunnel melalui SSH dengan mudah. Jika tidak, saya mendukung solusi socat di bawah ini.
Mattias Ahnberg
lwn.net/Articles/609321 OpenSSH 6.7 akan membawa penerusan soket
Hubbitus
@Hubbitus, apakah fitur ini tersedia sekarang, jika demikian, dapatkah Anda memberikan contoh jawaban?
CMCDragonkai
Komentar itu dalam bentuk jawaban, tetapi diubah menjadi komentar oleh seseorang. Dan saya melihat sekarang Anda sudah menyarankan jawaban di bawah ini.
Hubbitus

Jawaban:

35

Teruskan soket lokal sesuai permintaan

  • Siapkan otentikasi kunci publik SSH
  • Instal socatdi kedua ujungnya
  • buat direktori secara lokal untuk soket Anda, tidak dapat diakses oleh pengguna lain.
export SOCKET_DIR=~/.remote-sockets
mkdir -p $SOCKET_DIR
socat "UNIX-LISTEN:$SOCKET_DIR/mysqld.sock,reuseaddr,fork" \
EXEC:'ssh user@server socat STDIO UNIX-CONNECT\:/var/run/mysqld/mysqld.sock'

kemudian

mysql -S $SOCKET_DIR/mysqld.sock -u mysqluser -p

dicuri dari meneruskan soket domain unix dengan ssh dan socat

ijk
sumber
Ini luar biasa dan harus menjadi jawaban yang diterima.
John Smith Opsional
32

Meskipun pada saat itu, ketika pertanyaan diajukan, itu benar-benar tidak mungkin, tetapi sekarang mungkin.

Anda bisa ke keduanya: penerusan UNIX => TCP dan UNIX => UNIX.

Sebagai contoh:

ssh \
  -R/var/run/mysql.sock:/var/run/mysql.sock \
  -R127.0.0.1:3306:/var/run/mysql.sock \
  somehost

Hal ini dimungkinkan sejak OpenSSH 6.7.

Igor Chubin
sumber
1
Saya berhasil meneruskan soket lokal saya ke soket server jauh menggunakan di atas dan menjalankan docker client dari jarak jauh (bisa dilakukan oleh ssh secara langsung, tetapi di mana asyiknya :)ssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
sdkks
11

saya belum melakukan ini, tetapi saya akan mencoba dengan socat . mungkin sesuatu seperti:

ssh [email protected] -L 9999:localhost:9999 "socat TCP-LISTEN:localhost:9999 UNIX-CONNECT:/var/run/mysqld/mysql.sock"
socat UNIX-LISTEN:/path/to/local/socket TCP:localhost:9999

lagi, saya belum pernah melakukan hal seperti ini.

Javier
sumber
Saya akan mencobanya dan memberi tahu Anda bagaimana hasilnya. Saya telah menggunakan implementasi berbasis tcp.
Saya tidak dapat membuatnya berfungsi saat ini tetapi +1 tetap untuk gagasan itu, saya menyukainya. Saya akan memberi tahu Anda jika saya memperbaikinya.
+1 terlihat seperti utilitas yang bermanfaat.
Warner
5

Tidak perlu lagi socat sejak ssh 6.7. Anda dapat meneruskan soket domain unix secara langsung seperti:

ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

Info lebih lanjut: https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160

CMCDragonkai
sumber
Saya juga menemukan ini berguna untuk menghubungkan ke soket lokal sebagai pengguna yang berbeda. Ini biarkan saya menjalankan program klien terhadap proses server yang memutuskan ID pengguna tertentu (koneksi yang berasal dari pelari pekerjaannya sendiri).
Warbo
Meneruskan soket ke mesin yang sama, tetapi direktori berbeda dikontrol oleh pengguna yang berbeda, menggunakan sshd untuk mengotentikasi akses? Apa usecase Anda?
CMCDragonkai
Izin / akses direktori bukan masalah. Sebaliknya, daemon tertentu menjatuhkan segala upaya koneksi yang dilakukan oleh pengguna dalam kelompok tertentu (yang seharusnya untuk mencegah pemula menjadi bingung). Menggunakan ssh memungkinkan para pengguna untuk terhubung (melalui soket terowongan) seolah-olah mereka adalah pengguna yang tidak berada dalam grup itu, dan karenanya tidak terputus.
Warbo
Menarik, lucu bagaimana maksudmu nix-daemon, aku juga berurusan dengan masalah tentang itu. Saya bertanya-tanya mengapa nix-daemon menjatuhkan koneksi ke pengguna dalam grup tertentu? Apakah ini konfigurasi keamanan? Atau terkait dengan: nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai
Menurut pesan commit, itu untuk mencegah penggunaan "tidak disengaja". Saya membawanya ke sini
Warbo
2

Modifikasi lain dari jawaban @mpontes '/ @ javier itu

ssh user@remoteserver -L 9999:localhost:9999 'socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

Pembersih

ssh user@remoteserver -L 9999:localhost:9999 '
  socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock&
  pid=$!
  trap "kill $pid" 0
  while echo -ne " \b"; do
    sleep 5
  done
'

PROS

  1. Bekerja pada openssh lebih awal dari 6,7 (seperti CentOS 7)
  2. Membunuh socat pada ssh terminasi alih-alih harus ssh kembali ke server jauh
  3. Mengizinkan masuk ssh non-publik (tidak seperti solusi ijk)

Fitur

  1. Karena -fopsi ini tidak digunakan, Anda bisa menggunakan kunci publik dan menjalankan di latar belakang melalui &atau Anda bisa masuk secara interaktif dan menggunakan Ctrl + Z dan menggunakan yang sama $!untuk menyimpan pid.

Kon

  1. Tidak dapat dengan mudah menggunakan -fopsi ssh, karena Anda akan kehilangan pid ssh seperti itu. Metode ini bergantung pada berjalan di latar depan dan Ctrl + C untuk membunuh.
  2. Jauh lebih rumit

Penjelasan

  • socat ...& - jalankan socat di latar belakang pada server jauh
  • pid=$! - simpan pid
  • trap kill\ $pid 0- Jalankan kill $piddi bash termination
  • while :; sleep... - Duduk dalam lingkaran yang tak terbatas
  • echo -ne \ \b- Ruang gema diikuti oleh backspace. Ini gagal segera setelah ssh terputus. Dengan a sleep 5, ini artinya socatdapat berjalan hingga 5 detik setelah ssh

Catatan: Sebenarnya diuji menggunakan docker, pelabuhan 2375, /var/run/docker.sockdan variabel lingkungan DOCKER_HOST='tcp://localhost:2375', tetapi harus bekerja untuk mysql semua sama

Memperbarui

Menggunakan Kontrol SSH , Anda dapat menggunakan -fflag menggunakan cara saya, cukup tambahkan flag berikut

-f -o ControlPath=~/.ssh/%C -o ControlMaster=auto

Dan Anda akan mendapatkannya

ssh -f -o ControlPath=~/.ssh/%C -o ControlMaster=auto user@remoteserver -L 9999:localhost:9999 'set -m; socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

Sekarang Anda dapat menghentikan semua sesi terkontrol menggunakan

ssh -o ControlPath=~/.ssh/%C -O exit remoteserver

The -opilihan dapat disimpan dalam Anda .ssh/configfile, atau Anda dapat menggunakan -S bukan (tapi Anda akan masih perlu -o ControlMaster)

Andy
sumber
Saya menggunakan skrip di dalam wadah Docker untuk menyebarkan kode ke host lain. Logika koneksi Anda luar biasa tetapi berakhir ketika sesi bash berakhir. Ini mencegah saya menelepon docker run ... connect.shuntuk mengatur terowongan diikuti oleh docker run ... deploy.sh. Saya mencoba nohup,, &dan disowntetapi mereka tampaknya pecah socatdengan menutup stdoutdan memicu kill. Adakah ide untuk tweak untuk mendukung kasus ini (yaitu masih dekat ketika SSH tidak tetapi bertahan dari penolakan)?
claytond
BAIK. Ini sebenarnya berfungsi dengan baik (w / -fdan & disown) di terminal. Rupanya masalah ini dibuat oleh skrip "wrapper". Saya akan menyambut masukan tetapi saya melihat T&J yang lebih tepat sekarang.
claytond
@ claytond Tidak yakin persis apa yang Anda lakukan, tapi ya, semua perintah lain dihentikan ketika pid 1 dari sebuah wadah berakhir. Apa yang biasanya saya lakukan dalam skenario skrip deploy Anda adalah menggunakan perintah "deploy" dan menulis titik masuk untuk wadah saya gambar yang akan mengatakan "jika $ 1 (perintah) == deploay lalu" jalankan perintah ssh, dan menyebarkan perintah, dan kemudian akhiri, yang akan menutup koneksi ssh. Anda juga bisa docker run ... connect.sh, dan docker exec {container name/id} deploy.shmereka bermain bersama.
Andy
Kamu benar. Saya sebenarnya menggunakan wadah yang execsudah runada dan pipa SSH tidak bertahan setelah execberakhir. Saya mengklarifikasi bahwa itu disebabkan oleh kekhasan dengan cara skrip dieksekusi. Jika saya memindahkan panggilan ke skripnya sendiri dan menelepon nohup <script.sh> & disown, ia akan bertahan setelah selesai exec.
claytond
1

Menguraikan jawaban Javier, ini bekerja untuk saya:

ssh -f [email protected] -L 9999:localhost:9999 "socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock"

Anda perlu forkuntuk dapat terhubung beberapa kali tanpa sekarat begitu Anda menutup koneksi pertama. Juga, cara socat memungkinkan Anda menentukan alamat yang akan diikat adalah melalui bindopsi, bukan sebagai alamat sebelum port.

Setelah ini, cukup sambungkan ke localhost:9999normal seperti yang Anda inginkan. Kemudian untuk merobohkan terowongan:

ssh -f [email protected] "killall socat"

(atau yang serupa, Anda dapat melakukan lebih banyak hal rumit yang melibatkan menjaga PID socat)

mpontes
sumber
1

Ya, Anda bisa menggunakan socat.

Pertama lakukan tunnel TCP dengan SSH. Kemudian gunakan socat seperti ini:

socat unix-listen: /var/run/mysqld/mysqld.sock,fork,unlink-early tcp: 127.0.0.1: 3306

Kemudian berikan izin ke soket baru yang dibuat (chmod 777 mungkin)

pengguna190133
sumber
Ini dimungkinkan karena OpenSSH 6.6.
ysdx
3
chmod 777: nonononono! Tidak pernah lari chmod 777. Praktis tidak pernah diperlukan! Bahkan untuk "tujuan pengujian". Jika file dapat dibaca, maka itu dapat dibaca. Jika itu dapat ditulisi oleh useratau groupyang perlu ditulisi, maka itu dapat ditulisi. Sama sekali tidak perlu memberi semua orang izin menulis, dan lupa chmodmengembalikannya ke sesuatu yang waras adalah cara perusahaan multinasional diretas. Tapi jangan lakukan itu. Pernah. Saya menulis pengantar izin Unix . Silakan baca!
Martin Tournoij