Saya tidak yakin apa yang dirujuk oleh jawaban dan komentar lain di sini. Ini mungkin agak mudah. Ada dua opsi, keduanya memungkinkan akses ke port bernomor rendah tanpa harus meningkatkan proses ke root:
Opsi 1:Gunakan CAP_NET_BIND_SERVICE
untuk memberikan akses port bernomor rendah ke suatu proses:
Dengan ini, Anda dapat memberikan akses permanen ke biner tertentu untuk mengikat port bernomor rendah melalui setcap
perintah:
sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary
Untuk detail lebih lanjut tentang bagian e/i/p, lihat cap_from_text
.
Setelah melakukan ini, /path/to/binary
akan dapat mengikat ke port bernomor rendah. Perhatikan bahwa Anda harus menggunakan setcap
pada biner itu sendiri daripada symlink.
Opsi 2:Gunakan authbind
untuk memberikan akses satu kali, dengan kontrol pengguna/grup/port yang lebih baik:
authbind
(halaman manual) alat ada tepat untuk ini.
-
Instal
authbind
menggunakan pengelola paket favorit Anda. -
Konfigurasikan untuk memberikan akses ke port yang relevan, mis. untuk mengizinkan 80 dan 443 dari semua pengguna dan grup:
sudo touch /etc/authbind/byport/80 sudo touch /etc/authbind/byport/443 sudo chmod 777 /etc/authbind/byport/80 sudo chmod 777 /etc/authbind/byport/443
-
Sekarang jalankan perintah Anda melalui
authbind
(secara opsional tentukan--deep
atau argumen lain, lihat halaman manual):authbind --deep /path/to/binary command line args
Mis.
authbind --deep java -jar SomeServer.jar
Ada keuntungan dan kerugian dari kedua hal di atas. Opsi 1 memberikan kepercayaan kepada biner tetapi tidak memberikan kontrol atas akses per-port. Opsi 2 memberikan kepercayaan kepada pengguna/grup dan memberikan kontrol atas akses per-port tetapi versi yang lebih lama hanya mendukung IPv4 (karena saya awalnya menulis ini, versi yang lebih baru dengan dukungan IPv6 dirilis).
Dale Hagglund sangat tepat. Jadi saya hanya akan mengatakan hal yang sama tetapi dengan cara yang berbeda, dengan beberapa hal spesifik dan contoh. ☺
Hal yang benar untuk dilakukan di dunia Unix dan Linux adalah:
- untuk memiliki program kecil, sederhana, mudah diaudit, yang berjalan sebagai pengguna super dan mengikat soket pendengar;
- untuk memiliki program lain yang kecil, sederhana, mudah diaudit, yang menghilangkan hak istimewa, yang dihasilkan oleh program pertama;
- untuk mendapatkan inti dari layanan, di ketiga yang terpisah program, dijalankan di bawah akun non-pengguna super dan rantai dimuat oleh program kedua, berharap untuk mewarisi deskriptor file terbuka untuk soket.
Anda salah paham tentang di mana risiko tinggi itu. Risiko tinggi adalah membaca dari jaringan dan menindaklanjuti apa yang dibaca bukan dalam tindakan sederhana membuka soket, mengikatnya ke port, dan memanggil listen()
. Ini adalah bagian dari layanan yang melakukan komunikasi sebenarnya yang berisiko tinggi. Bagian yang terbuka, bind()
, dan listen()
, dan bahkan (sampai batas tertentu) bagian accepts()
, tidak berisiko tinggi dan dapat dijalankan di bawah perlindungan pengguna super. Mereka tidak menggunakan dan menindaklanjuti (dengan pengecualian alamat IP sumber di accept()
kasus) yang berada di bawah kendali orang asing yang tidak dipercaya melalui jaringan.
Ada banyak cara untuk melakukan ini.
inetd
Seperti yang dikatakan Dale Hagglund, "superserver jaringan" lama inetd
Melakukan hal ini. Akun tempat proses layanan dijalankan adalah salah satu kolom di inetd.conf
. Itu tidak memisahkan bagian mendengarkan dan menjatuhkan hak istimewa menjadi dua program terpisah, kecil dan mudah diaudit, tetapi memisahkan kode layanan utama menjadi program terpisah, exec()
ed dalam proses layanan yang muncul dengan deskriptor file terbuka untuk soket.
Sulitnya mengaudit tidak terlalu menjadi masalah, karena hanya perlu mengaudit satu program saja. inetd
masalah utama adalah tidak terlalu banyak mengaudit tetapi tidak memberikan kontrol layanan waktu proses yang sederhana dan terperinci, dibandingkan dengan alat yang lebih baru.
UCSPI-TCP dan daemontools
Paket UCSPI-TCP dan daemontools Daniel J. Bernstein dirancang untuk melakukan hal ini bersamaan. Sebagai alternatif, seseorang dapat menggunakan perangkat daemontools-encore Bruce Guenter yang sebagian besar setara.
Program untuk membuka deskriptor file soket dan mengikat ke port lokal istimewa adalah tcpserver
, dari UCSPI-TCP. Ia melakukan keduanya listen()
dan accept()
.
tcpserver
kemudian memunculkan program layanan yang menghapus hak akses root itu sendiri (karena protokol yang dilayani melibatkan memulai sebagai pengguna super dan kemudian "masuk", seperti halnya, misalnya, daemon FTP atau SSH) atau setuidgid
yang merupakan program mandiri kecil dan mudah diaudit yang hanya membuang hak istimewa dan kemudian memuat rantai ke program layanan yang tepat (tidak ada bagian yang pernah berjalan dengan hak istimewa pengguna super, seperti halnya dengan, katakanlah, qmail-smtpd
).
Layanan run
skrip dengan demikian misalnya (yang ini untuk dummyidentd untuk menyediakan layanan null IDENT):
#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl
tidak
Paket nosh saya dirancang untuk melakukan ini. Ini memiliki setuidgid
kecil utilitas, sama seperti yang lain. Satu perbedaan kecil adalah dapat digunakan dengan systemd
-style layanan "LISTEN_FDS" serta dengan layanan UCSPI-TCP, jadi tcpserver
tradisional program diganti dengan dua program terpisah:tcp-socket-listen
dan tcp-socket-accept
.
Sekali lagi, utilitas tujuan tunggal menelurkan dan memuat rantai satu sama lain. Satu kekhasan yang menarik dari desain ini adalah seseorang dapat melepaskan hak superuser setelah listen()
tetapi bahkan sebelum accept()
. Ini adalah run
skrip untuk qmail-smtpd
yang memang melakukan hal itu:
#!/bin/nosh
fdmove -c 2 1
clearenv --keep-path --keep-locale
envdir env/
softlimit -m 70000000
tcp-socket-listen --combine4and6 --backlog 2 ::0 smtp
setuidgid qmaild
sh -c 'exec \
tcp-socket-accept -v -l "${LOCAL:-0}" -c "${MAXSMTPD:-1}" \
ucspi-socket-rules-check \
qmail-smtpd \
'
Program-program yang berjalan di bawah naungan superuser adalah alat pemuat berantai layanan-agnostik kecil fdmove
, clearenv
, envdir
, softlimit
, tcp-socket-listen
, dan setuidgid
. Sampai-sampai sh
dimulai, soket terbuka dan terikat ke smtp
port, dan prosesnya tidak lagi memiliki hak superuser.
s6, s6-networking, dan execline
Paket jaringan s6 dan s6 Laurent Bercot dirancang untuk melakukan ini bersamaan. Perintah secara struktural sangat mirip dengan daemontools
dan UCSPI-TCP.
run
skrip akan hampir sama, kecuali untuk penggantian s6-tcpserver
untuk tcpserver
dan s6-setuidgid
untuk setuidgid
. Namun, seseorang juga dapat memilih untuk menggunakan perangkat execline M. Bercot pada saat yang sama.
Berikut adalah contoh layanan FTP, dimodifikasi ringan dari versi asli Wayne Marshall, yang menggunakan execline, s6, s6-networking, dan program server FTP dari publicfile:
#!/command/execlineb -PW
multisubstitute {
define CONLIMIT 41
define FTP_ARCHIVE "/var/public/ftp"
}
fdmove -c 2 1
s6-envuidgid pubftp
s6-softlimit -o25 -d250000
s6-tcpserver -vDRH -l0 -b50 -c ${CONLIMIT} -B '220 Features: a p .' 0 21
ftpd ${FTP_ARCHIVE}
ipsvd
Ipsvd Gerrit Pape adalah perangkat lain yang berjalan di jalur yang sama dengan ucspi-tcp dan s6-networking. Alatnya adalah chpst
dan tcpsvd
kali ini, tetapi mereka melakukan hal yang sama, dan kode berisiko tinggi yang melakukan pembacaan, pemrosesan, dan penulisan hal-hal yang dikirim melalui jaringan oleh klien yang tidak dipercaya masih dalam program terpisah.
Inilah contoh M. Pape dalam menjalankan fnord
dalam run
skrip:
#!/bin/sh
exec 2>&1
cd /public/10.0.5.4
exec \
chpst -m300000 -Uwwwuser \
tcpsvd -v 10.0.5.4 443 sslio -v -unobody -//etc/fnord/jail -C./cert.pem \
fnord
systemd
systemd
, pengawasan layanan baru dan sistem init yang dapat ditemukan di beberapa distribusi Linux, dimaksudkan untuk melakukan apa inetd
bisa lakukan. Namun, itu tidak menggunakan serangkaian program mandiri kecil. Seseorang harus mengaudit systemd
secara keseluruhan, sayangnya.
Dengan systemd
seseorang membuat file konfigurasi untuk menentukan soket yang systemd
mendengarkan, dan layanan yang systemd
dimulai. File "unit" layanan memiliki setelan yang memungkinkan seseorang mengontrol banyak proses layanan, termasuk pengguna yang menjalankannya.
Dengan pengguna tersebut ditetapkan sebagai bukan pengguna super, systemd
melakukan semua pekerjaan membuka soket, mengikatnya ke port, dan memanggil listen()
(dan, jika diperlukan, accept()
) dalam proses #1 sebagai pengguna super, dan proses layanan yang dihasilkannya berjalan tanpa hak pengguna super.
Saya memiliki pendekatan yang agak berbeda. Saya ingin menggunakan port 80 untuk server node.js. Saya tidak dapat melakukannya karena Node.js diinstal untuk pengguna non-sudo. Saya mencoba menggunakan symlink, tetapi tidak berhasil untuk saya.
Kemudian saya mengetahui bahwa saya dapat meneruskan koneksi dari satu port ke port lain. Jadi saya memulai server pada port 3000 dan menyiapkan port forward dari port 80 ke port 3000.
Tautan ini menyediakan perintah aktual yang dapat digunakan untuk melakukan ini. Inilah perintahnya -
localhost/loopback
sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 3000
eksternal
sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
Saya telah menggunakan perintah kedua dan berhasil untuk saya. Jadi menurut saya ini adalah jalan tengah untuk tidak mengizinkan proses pengguna mengakses port yang lebih rendah secara langsung, tetapi memberi mereka akses menggunakan penerusan port.