Bagaimana cara membuat pengguna SSH terbatas untuk penerusan porta?

106

ændrük menyarankan koneksi terbalik untuk mendapatkan koneksi SSH yang mudah dengan orang lain (untuk bantuan jarak jauh). Agar itu berfungsi, pengguna tambahan diperlukan untuk menerima koneksi. Pengguna ini harus dapat meneruskan porta melalui server (server bertindak sebagai proxy).

Bagaimana cara membuat pengguna terbatas yang tidak dapat melakukan lebih dari yang dijelaskan di atas?

Pengguna baru tidak boleh dapat:

  • jalankan perintah shell
  • mengakses file atau mengunggah file ke server
  • gunakan server sebagai proxy (mis. webproxy)
  • mengakses layanan lokal yang tidak dapat diakses publik karena firewall
  • bunuh server

Ringkasnya, bagaimana cara membuat pengguna SSH terbatas yang hanya dapat terhubung ke server SSH tanpa hak istimewa, sehingga saya dapat terhubung melalui koneksi itu dengan komputernya?

Lekensteyn
sumber

Jawaban:

166

TL; DR - buka bagian bawah jawaban, "Menerapkan batasan"

Menambahkan pengguna terbatas terdiri dari dua bagian: 1. Membuat pengguna 2. Mengkonfigurasi daemon SSH (sshd)

Konfigurasi sshd

Tempat terbaik untuk mengetahui kemungkinan SSH adalah dengan membaca halaman buku panduan terkait:

Di mana klien SSH dapat melakukan tindakan?

Sebelum Anda dapat membatasi sesuatu, Anda perlu mengetahui fitur SSH. Meludah melalui halaman buku panduan menghasilkan:

  • Shell memerintahkan eksekusi
  • Unggah file melalui sftp
  • Penerusan port
    • Klien meneruskan port (un) yang digunakan ke server
    • Server meneruskan portanya ke klien
    • Server meneruskan port host lain ke klien (proxy-ish)
  • Penerusan X11 (penerusan tampilan)
  • Penerusan agen otentikasi
  • Penerusan perangkat terowongan

Dari Otentikasi bagian dari halaman manual sshd (8) :

Jika klien berhasil mengotentikasi dirinya sendiri, dialog untuk mempersiapkan sesi dimasukkan. Pada saat ini klien dapat meminta hal-hal seperti mengalokasikan pseudo-tty, meneruskan koneksi X11, meneruskan koneksi TCP, atau meneruskan koneksi agen otentikasi melalui saluran aman.

Setelah ini, klien meminta shell atau eksekusi perintah . Sisi kemudian memasuki mode sesi. Dalam mode ini, kedua sisi dapat mengirim data kapan saja, dan data tersebut diteruskan ke / dari shell atau perintah di sisi server, dan terminal pengguna di sisi klien.

Opsi untuk membatasi fitur SSH

File dan opsinya yang mengubah perilaku adalah:

  • ~/.ssh/authorized_keys - berisi kunci yang diizinkan untuk terhubung yang dapat diberikan opsi:
    • command="command"- Perintah yang diberikan oleh pengguna (jika ada) diabaikan. Perhatikan bahwa klien dapat menentukan penerusan TCP dan / atau X11 kecuali jika mereka secara eksplisit dilarang . Perhatikan bahwa opsi ini berlaku untuk eksekusi shell, perintah atau subsistem.
    • no-agent-forwarding - Melarang penerusan agen otentikasi ketika kunci ini digunakan untuk otentikasi.
    • no-port-forwarding - Melarang penerusan TCP saat kunci ini digunakan untuk otentikasi
    • no-X11-forwarding - "Melarang penerusan X11 saat kunci ini digunakan untuk otentikasi."
    • permitopen="host:port" - Batasi penerusan port 'ssh -L' lokal sehingga hanya dapat terhubung ke host dan port yang ditentukan.
  • ~/.ssh/environment- File ini dibaca ke lingkungan saat login (jika ada). Pemrosesan lingkungan dinonaktifkan secara default dan dikendalikan melalui opsi PermitUserEnvironment
  • ~/.ssh/rc - Berisi rutin inisialisasi yang harus dijalankan sebelum direktori home pengguna menjadi dapat diakses.
  • /etc/ssh/sshd_config - file konfigurasi seluruh sistem
    • AllowAgentForwarding - Menentukan apakah penerusan ssh-agent (1) diizinkan.
    • AllowTcpForwarding
    • ForceCommand - "Memaksa pelaksanaan perintah yang ditentukan oleh ForceCommand, mengabaikan perintah yang diberikan oleh klien dan ~ / .ssh / rc jika ada. Perintah ini dipanggil dengan menggunakan shell login pengguna dengan opsi -c."
    • GatewayPorts - "Menentukan apakah host jarak jauh diizinkan untuk terhubung ke port yang diteruskan untuk klien. Secara default, sshd (8) mengikat penerusan port jarak jauh ke alamat loopback. Ini mencegah host jarak jauh lain dari koneksi ke port yang diteruskan. GatewayPort dapat digunakan untuk menentukan sshd itu harus memungkinkan penerusan port jarak jauh untuk mengikat ke alamat non-loopback, sehingga memungkinkan penghuni lain untuk terhubung. "
    • PermitOpen:

      Menentukan tujuan yang diizinkan penerusan port TCP. Spesifikasi penerusan harus salah satu dari bentuk berikut:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      Multiple forward dapat ditentukan dengan memisahkannya dengan spasi putih. Argumen 'apa pun' dapat digunakan untuk menghapus semua batasan dan mengizinkan permintaan penerusan. Secara default semua permintaan penerusan port diizinkan.

    • PermitTunnel- Menentukan apakah tun (4) penerusan perangkat diizinkan. Standarnya adalah 'tidak'
    • X11Forwarding- Menentukan apakah penerusan X11 diizinkan. Standarnya adalah 'tidak'

Menerapkan pembatasan

Memodifikasi file konfigurasi seluruh sistem /etc/ssh/sshd_configmemungkinkan konfigurasi diterapkan bahkan jika otentikasi berbasis kata sandi diterapkan atau jika batasan dalam ~/.ssh/authorized_keysdihapus secara tidak sengaja. Jika Anda telah memodifikasi default global, Anda harus menghapus komentar opsi yang sesuai.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Sekarang tambahkan pengguna:

sudo useradd -m limited-user

Opsi ForceCommanddapat dihilangkan jika shell diatur ke non-shell seperti /bin/false(atau /bin/true) karena /bin/false -c [command]tidak akan melakukan apa-apa.

Sekarang klien hanya dapat terhubung ke port 62222 pada alamat loopback server melalui SSH (tidak akan mendengarkan alamat IP publik)

Menonaktifkan AllowTcpForwardingjuga akan melarang penggunaan -R, sehingga mengalahkan penggunaan akun terbatas tersebut untuk meneruskan satu port. PermitOpen localhost:62222mengasumsikan bahwa port 62222 di server tidak pernah digunakan karena klien dengan senang hati dapat terhubung dan mendengarkannya juga.

Jika penerusan TCP diizinkan dalam konfigurasi sistem dan otentikasi berbasis kata sandi yang dinonaktifkan, Anda dapat menggunakan pengaturan per-kunci juga. Edit ~/.ssh/authorized_keysdan tambahkan opsi berikutnya sebelum ssh-(dengan spasi di antara opsi dan ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

Memeriksa

Untuk memastikan bahwa itu berfungsi seperti yang diharapkan, beberapa kasus uji harus dijalankan. Dalam perintah di bawah ini, hostharus diganti dengan login yang sebenarnya jika tidak diatur ~/.ssh/config. Di belakang perintah, ditampilkan perintah yang harus dijalankan pada klien atau server (sebagaimana ditentukan).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Kesimpulan

Daftar periksa: Pengguna SSH seharusnya tidak dapat:

  • jalankan perintah shell - selesai
  • mengakses file atau mengunggah file ke server - selesai
  • gunakan server sebagai proxy (mis. webproxy) - selesai
  • mengakses layanan lokal yang sebelumnya tidak dapat diakses oleh publik karena firewall - sebagian , klien tidak dapat mengakses port lain selain 62222, tetapi dapat mendengarkan dan terhubung ke port 62222 di server
  • bunuh server - selesai (perhatikan bahwa pemeriksaan ini terbatas pada server SSH. Jika Anda memiliki layanan lain yang rentan pada mesin, itu dapat memungkinkan penyerang yang mungkin menjalankan perintah, membunuh server, dll.)
Lekensteyn
sumber
3
Agar ini berfungsi, akun yang ditambahkan oleh useraddharus dibuka kuncinya. Itu bisa dilakukan dengan mengganti kata sandi /etc/shadowdengan asterik ( *) atau dengan mengatur kata sandi menggunakan sudo passwd limited-user.
Lekensteyn
2
SFTP berfungsi karena server SSH menjalankan sftp-serverperintah. Dengan ForceCommand, perintah ini tidak akan dieksekusi lagi.
Lekensteyn
2
Juga berguna adalah from=opsi di authorized_keys. Ini memungkinkan Anda membatasi penggunaan kunci untuk sumber dengan alamat IP atau nama host tertentu. Contoh, from="1.1.1.1"atau from="10.0.0.?,*.example.com". Lihat bagian "FORMAT FILE AUTHORIZED_KEYS" di halaman manual ( linux.die.net/man/8/sshd ) untuk semua opsi Authorized_keys.
Donn Lee
2
"AllowTcpForwarding local" melarang penerusan jarak jauh. (Saya tidak tahu apakah itu ada ketika jawaban ini ditulis.)
Simon Sapin
1
Perhatikan bahwa ini terputus oleh koneksi ssh persisten, jadi Anda seharusnya tidak memiliki sesuatu seperti Host * ControlMaster autodi ~/.ssh/configfile Anda saat terhubung dengan ssh -N. Jika Anda benar-benar membutuhkannya, gunakanssh -N -o ControlMaster=no
nh2
3

Saya yakin ada banyak solusi untuk ini, dan banyak lagi yang lebih kuat daripada yang saya usulkan. Namun, ini mungkin cukup untuk kebutuhan Anda. Untuk melakukannya, saya berasumsi pengguna telah dapat melakukan otentikasi berbasis kunci ssh (dempul atau ssh unix harus mendukung ini).

  • Tambahkan pengguna seperti biasa ('adduser' atau alat lainnya)

  • Buat dir .ssh pengguna dan .ssh / berwenang_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • Nonaktifkan akses kata sandi ke akun ini.
your_user $ sudo usermod --lock ssh_forwarder

Sekarang, satu-satunya cara pengguna dapat masuk ke sistem Anda adalah melalui akses ke kunci ssh yang tepat, dan ssh akan menjalankan "/ bin / bash -c 'read a'" untuk mereka, tidak peduli apa yang mereka coba jalankan. 'read a' hanya akan membaca hingga baris baru, dan kemudian shell akan keluar, sehingga pengguna hanya perlu menekan 'enter' untuk mematikan koneksi.

Ada banyak hal lain yang dapat Anda lakukan di 'command ='. Lihat man authorized_keysdan cari 'perintah' untuk informasi lebih lanjut.

Jika Anda tidak menyukai kenyataan bahwa menekan enter membunuh koneksi, Anda bisa menggunakan sesuatu seperti berikut ini untuk entri 'command =':

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

Ini hanya membuat fifo sementara di direktori home pengguna, dan kemudian mencoba untuk membacanya. Tidak ada yang akan menulis ke file itu, jadi ini akan menggantung tanpa batas. Selain itu, jika Anda ingin memutuskan koneksi itu secara paksa, Anda dapat melakukan sesuatu seperti:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

Ini harus menggunakan sumber daya yang sangat sedikit, dan tidak ada yang bisa salah dalam skrip yang tidak akan berakhir pada penghentian shell.

sleep 1h; echo You have been here too long. Good bye.

Saya tidak melihat secara langsung bagaimana Anda dapat memungkinkan pengguna untuk maju jauh ( ssh -R) tetapi membatasi ( ssh -L). Mungkin 'permitopen' dapat digunakan. Googling tidak terlalu membantu. Tampaknya sesuatu seperti 'no-port-forwarding, permitremoteopen = 10001' akan berguna untuk memungkinkan ssh -R 6901:localhost:6901.

Ini adalah sebuah solusi. Ini pasti dapat ditingkatkan, dan setiap pembukaan port jarak jauh harus diteliti. Jika tujuan saya adalah untuk memungkinkan Nenek saya terhubung ke LAN saya sehingga saya dapat menggunakan vnc untuk melihat layarnya, dan akses ke tombol-tombol itu terbatas padanya, saya pribadi akan merasa cukup aman. Jika ini untuk perusahaan, investigasi yang lebih menyeluruh akan diperlukan. Satu hal yang perlu diperhatikan adalah ssh -Ntidak meminta shell sama sekali, jadi kode 'command =' tidak dapat dijalankan.

Lainnya, mekanisme yang mungkin lebih aman mungkin termasuk membuat shell khusus untuk pengguna, dan bahkan menguncinya dengan apparmour.

tukang smoser
sumber
3
Ini terlihat sangat retas, bahkan tidak perlu memiliki shell karena tidak ada perintah yang perlu dijalankan. Lihat halaman manualssh untuk -Nopsi. Harus ada cara yang lebih bersih untuk mencapai ini.
Lekensteyn
Itu benar. Saya berharap untuk melihat solusi yang lebih bersih juga. Saya pikir bahwa otor_keys bersama dengan no-port-forwarding akan menjadi solusi yang cukup bagus jika ada opsi 'permitremoteopen'.
smoser
Saya melakukan beberapa penelitian (lihat di atas). Karena ssh -Ntidak menjalankan perintah sama sekali, tidak ada masalah yang command="something"menutup sesi.
Lekensteyn
Apakah saya melewatkan sesuatu? Tampaknya chsh ssh_forwarder -s /bin/false hanya itu yang diperlukan.
typelogic