Proxy SSH Socks berdasarkan permintaan melalui unit pengguna systemd dengan aktivasi soket tidak memulai kembali seperti yang diinginkan

14

Untuk mencapai jaringan yang terisolasi saya menggunakan -D .

Untuk menghindari keharusan mengetikkan detail setiap kali saya menambahkannya ke ~/.ssh/config:

$ awk '/Host socks-proxy/' RS= ~/.ssh/config
Host socks-proxy
  Hostname pcit
  BatchMode yes
  RequestTTY no
  Compression yes
  DynamicForward localhost:9118

Kemudian saya membuat file definisi unit layanan :

$ cat ~/.config/systemd/user/SocksProxy.service 
[Unit]
Description=SocksProxy Over Bridge Host

[Service]
ExecStart=/usr/bin/ssh -Nk socks-proxy

[Install]
WantedBy=default.target

Saya membiarkan daemon memuat ulang definisi layanan baru, mengaktifkan layanan baru, memulainya, memeriksa statusnya, dan memverifikasi, bahwa ia mendengarkan:

$ systemctl --user daemon-reload
$ systemctl --user list-unit-files | grep SocksP
SocksProxy.service   disabled

$ systemctl --user enable SocksProxy.service
Created symlink from ~/.config/systemd/user/default.target.wants/SocksProxy.service to ~/.config/systemd/user/SocksProxy.service.

$ systemctl --user start SocksProxy.service 
$ systemctl --user status SocksProxy.service 
● SocksProxy.service - SocksProxy Over Bridge Host
   Loaded: loaded (/home/alex/.config/systemd/user/SocksProxy.service; enabled)
   Active: active (running) since Thu 2017-08-03 10:45:29 CEST; 2s ago
 Main PID: 26490 (ssh)
   CGroup: /user.slice/user-1000.slice/[email protected]/SocksProxy.service
           └─26490 /usr/bin/ssh -Nk socks-proxy

$ netstat -tnlp | grep 118
tcp     0    0 127.0.0.1:9118        0.0.0.0:*             LISTEN     
tcp6    0    0 ::1:9118              :::*                  LISTEN

Ini berfungsi sebagaimana dimaksud. Kemudian saya ingin menghindari keharusan untuk memulai layanan secara manual, atau menjalankannya secara permanen dengan , dengan menggunakan untuk pemijahan on-demand (re-). Itu tidak berhasil, saya pikir (versi saya) sshtidak dapat menerima deskriptor file socket.

Saya menemukan dokumentasi ( 1 , 2 ), dan contoh untuk menggunakan systemd-socket-proxyd-tool untuk membuat 2 layanan "wrapper", "service" dan "socket":

$ cat ~/.config/systemd/user/SocksProxyHelper.socket 
[Unit]
Description=On Demand Socks proxy into Work

[Socket]
ListenStream=8118
#BindToDevice=lo
#Accept=yes

[Install]
WantedBy=sockets.target

$ cat ~/.config/systemd/user/SocksProxyHelper.service 
[Unit]
Description=On demand Work Socks tunnel
After=network.target SocksProxyHelper.socket
Requires=SocksProxyHelper.socket SocksProxy.service
After=SocksProxy.service

[Service]
#Type=simple
#Accept=false
ExecStart=/lib/systemd/systemd-socket-proxyd 127.0.0.1:9118
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

$ systemctl --user daemon-reload

Ini sepertinya berhasil, sampai sshmati atau terbunuh. Maka itu tidak akan muncul kembali pada upaya koneksi berikutnya ketika seharusnya.

Pertanyaan:

  1. Bisakah / usr / bin / ssh benar-benar tidak menerima soket systemd-pass? Atau hanya versi yang lebih baru? Milik saya adalah dari up2date Debian 8.9 .
  2. Bisakah hanya unit root menggunakan BindTodeviceopsi?
  3. Mengapa layanan proxy saya tidak respawn dengan benar pada koneksi baru pertama setelah terowongan lama mati?
  4. Apakah ini cara yang tepat untuk mengatur "proksi ssh socks proxy"? Jika tidak, bagaimana Anda melakukannya?
Alex Stragies
sumber
autosshharus berhati-hati dalam menyambung kembali jika koneksi gagal (meskipun itu bukan cara sistem).
Jakuje
@ Jakuje: Terima kasih atas komentarnya, tapi saya tidak ingin koneksi menjadi permanen. Saya ingin itu muncul ketika saya menggunakannya, dan kemudian (idealnya setelah timeout no-data-sent-in-x-menit) berhenti sendiri. Juga, solusi saya sebelumnya digunakan autossh.
Alex Stragies

Jawaban:

4
  • Bisakah / usr / bin / ssh benar-benar tidak menerima soket systemd-pass?

Saya pikir itu tidak terlalu mengejutkan, mengingat:

  • OpenSSH adalah proyek OpenBSD
  • systemd hanya mendukung kernel Linux
  • dukungan systemd perlu ditambahkan secara eksplisit ke OpenSSH, sebagai dependensi opsional / build-time, jadi itu mungkin merupakan penjualan yang sulit.

  • Bisakah hanya unit root menggunakan BindTodeviceopsi?

Instance systemd pengguna umumnya cukup terisolasi, dan misalnya tidak dapat berkomunikasi dengan instance pid-0 utama. Hal-hal seperti bergantung pada unit sistem dari file unit pengguna tidak dimungkinkan.

Dokumentasi untuk BindToDevicemenyebutkan:

Perhatikan bahwa pengaturan parameter ini dapat mengakibatkan dependensi tambahan yang akan ditambahkan ke unit (lihat di atas).

Karena pembatasan yang disebutkan di atas, kita dapat menyiratkan bahwa opsi tidak berfungsi dari instance systemd pengguna.


  • Mengapa layanan proxy saya tidak respawn dengan benar pada koneksi baru pertama setelah terowongan lama mati?

Seperti yang saya mengerti, rantai acara adalah sebagai berikut:

  • SocksProxyHelper.socket sudah dimulai.
  • Klien SOCKS terhubung ke localhost: 8118.
  • systemd dimulai SocksProxyHelper.service.
  • Sebagai ketergantungan SocksProxyHelper.service, systemd juga mulai SocksProxy.service.
  • systemd-socket-proxydmenerima soket systemd, dan meneruskan datanya ke ssh.
  • ssh mati atau terbunuh.
  • pemberitahuan systemd, dan menempatkan SocksProxy.serviceke keadaan tidak aktif, tetapi tidak melakukan apa-apa.
  • SocksProxyHelper.serviceterus berjalan dan menerima koneksi, tetapi gagal terhubung ssh, karena tidak lagi berjalan.

Cara mengatasinya adalah dengan menambahkan BindsTo=SocksProxy.serviceke SocksProxyHelper.service. Mengutip dokumentasinya (penekanan ditambahkan):

Mengkonfigurasi dependensi persyaratan, sangat mirip dengan gaya Requires=. Namun, tipe dependensi ini lebih kuat: selain efeknya Requires=menyatakan bahwa jika unit terikat dihentikan, unit ini akan dihentikan juga . Ini berarti unit terikat ke unit lain yang tiba-tiba memasuki keadaan tidak aktif akan dihentikan juga. Unit dapat tiba-tiba, tiba-tiba memasuki keadaan tidak aktif karena berbagai alasan: proses utama unit layanan mungkin berakhir atas pilihannya sendiri , perangkat pendukung unit perangkat mungkin dicabut atau titik pemasangan unit pemasangan mungkin dilepas tanpa keterlibatan dari manajer sistem dan layanan.

Ketika digunakan bersama dengan After=pada unit yang sama perilaku BindsTo=bahkan lebih kuat. Dalam hal ini, unit yang terikat secara ketat harus dalam keadaan aktif agar unit ini juga dalam keadaan aktif . Hal ini tidak hanya berarti satu unit terikat ke unit lain yang tiba-tiba memasuki keadaan tidak aktif, tetapi juga salah satu yang terikat ke unit lain yang mendapat dilewati karena cek kondisi gagal (seperti ConditionPathExists=, ConditionPathIsSymbolicLink=, ... - lihat di bawah) akan dihentikan, seharusnya hal itu sedang berlari. Oleh karena itu, dalam banyak kasus yang terbaik adalah untuk menggabungkan BindsTo=dengan After=.


  • Apakah ini cara yang tepat untuk mengatur "proksi ssh socks proxy"? Jika tidak, bagaimana Anda melakukannya?

Mungkin tidak ada "jalan yang benar". Metode ini memiliki kelebihan (semuanya "on-demand") dan kerugian (ketergantungan pada systemd, koneksi pertama yang tidak bisa lewat karena ssh belum mulai mendengarkan). Mungkin menerapkan dukungan aktivasi soket systemd di autossh akan menjadi solusi yang lebih baik.

Vladimir Panteleev
sumber
Saya telah menambahkan BindsTo=SocksProxy.serviceke bagian Unit file ~/.config/systemd/user/SocksProxyHelper.service, setelah After=SocksProxy.servicebaris. Me-restart secara manual Layanan SocksProxy sekarang tidak diperlukan lagi, ketika SSH meninggal / mendapat_killed. Apakah ada cara bagi systemd untuk "menahan" koneksi awal, sehingga tidak mendapatkan reset TCP?
Alex Stragies
@Vladimir Panteleev satu hal yang ingin saya perjelas: dukungan untuk aktivasi soket systemd dapat diimplementasikan secara relatif mudah dengan mem $LISTEN_FDS- parsing tanpa menambahkan ketergantungan sd_listen_fds(), sehingga mungkin masih merupakan penjualan yang sulit, tetapi tidak terlalu sulit.
Amir