Mengizinkan pengguna membiarkan mendengarkan port di bawah 1024

63

Saya perlu mengizinkan pengguna (berbeda dari root) untuk menjalankan server mendengarkan pada port 80.

Apakah ada cara untuk melakukan ini?

peoro
sumber
1
Pertanyaan ini terbuka untuk interpretasi. Saya berharap bahwa yang Anda maksudkan adalah "Anda telah membuat layanan sistem baru yang Anda (sebagai root) ingin jalankan di akun yang tidak terjangkau untuk alasan keamanan" (dianggap praktik yang baik) dan bukan "Saya memiliki pengguna yang ditanya apakah mereka dapat jalankan server web mereka sendiri di sistem saya, bagaimana cara saya mengizinkan mereka mengakses? " (Dianggap latihan yang agak buruk)
Michael Shaw
3
@ Poltemy, alasan sebenarnya adalah: mesin saya ada di belakang firewall yang memblokir port apa pun kecuali 80. Saya ingin meng-host server (yang tidak menjatuhkan hak istimewa!), Sehingga perlu mendengarkannya di port 80, tetapi jangan tidak percaya untuk menjalankannya sebagai root (untuk alasan keamanan yang jelas). Saya diizinkan melakukan ini, jika Anda peduli.
peoro
serverfault.com/questions/112795/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

50

setcap 'cap_net_bind_service=+ep' /path/to/program

ini akan bekerja untuk proses spesifik. Tetapi untuk memungkinkan pengguna tertentu untuk mengikat port di bawah 1024 Anda harus menambahkannya ke sudoers.

Lihat diskusi ini untuk informasi lebih lanjut.

Rohan Monga
sumber
31

(Beberapa metode ini telah disebutkan dalam jawaban lain; Saya memberikan beberapa pilihan yang mungkin dalam urutan kasar preferensi.)

Anda dapat mengarahkan port rendah ke port tinggi dan mendengarkan port tinggi.

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080

Anda dapat memulai server Anda sebagai hak istimewa root dan drop setelah mulai mendengarkan pada port yang diistimewakan. Lebih disukai, daripada mengkode sendiri, mulai server Anda dari pembungkus yang melakukan pekerjaan untuk Anda. Jika server Anda memulai satu instance per koneksi, mulai dari inetd(atau program serupa seperti xinetd). Untuk inetd, gunakan baris seperti ini di /etc/inetd.conf:

http  stream  tcp  nowait  username:groupname  /path/to/server/executable  argv[0] argv[1]…

Jika server Anda mendengarkan dalam satu contoh, mulai dari program seperti authbind. Baik membuat file kosong /etc/authbind/byport/80dan membuatnya dapat dieksekusi untuk pengguna yang menjalankan server; atau buat /etc/authbind/byuid/1234, di mana 1234 adalah UID yang menjalankan server, berisi baris 0.0.0.0/0:80,80.

Jika server Anda dapat dieksekusi disimpan pada sistem file yang mendukung kemampuan, Anda dapat memberikannya kemampuan . Berhati-hatilah karena kemampuannya masih relatif baru dan masih memiliki beberapa ketegaran .cap_net_bind_service

setcap cap_net_bind_service=ep /path/to/server/executable
Gilles 'SANGAT berhenti menjadi jahat'
sumber
4
Dalam setiap kasus saya harus berurusan dengan, executable adalah skrip yang meluncurkan java atau python. Sebagai seorang pria tanpa 10 jam untuk menghabiskan poin-poin bagus, solusi iptables Anda menutupinya tanpa rasa sakit.
srking
Untuk solusi iptables, saya juga harus menambahkan aturan filter seperti -A INPUT -p tcp --dport 1080 -j ACCEPTkalau tidak akan bekerja (saya juga punya -j DROPcatch-all.) Jadi saya pergi dengan dua soket mendengarkan.
thom_nic
4

Jawaban singkatnya adalah bahwa ini tidak dimungkinkan oleh desain.

Jawaban panjangnya adalah bahwa di dunia open source ada banyak orang yang bermain dengan desain dan datang dengan metode alternatif. Secara umum adalah praktik yang diterima secara luas bahwa ini seharusnya tidak mungkin. Fakta bahwa Anda mencoba mungkin berarti Anda memiliki kesalahan desain lain di sistem Anda dan harus mempertimbangkan kembali arsitektur sistem Anda secara keseluruhan mengingat praktik terbaik dan implikasi keamanan.

Yang mengatakan, satu program untuk otorisasi akses non-root ke port rendah adalah authbind . Baik selinux dan grsecurity juga menyediakan kerangka kerja untuk otentikasi yang disesuaikan tersebut.

Terakhir, jika Anda ingin pengguna tertentu menjalankan program tertentu sebagai root dan yang benar-benar Anda butuhkan hanyalah mengizinkan pengguna untuk memulai kembali apache atau sesuatu seperti itu, sudoadalah teman Anda!

Caleb
sumber
8
Port "keamanan" tidak benar-benar memberi Anda banyak di dunia modern.
pjc50
3
@ pjc50: Ya, benar. Ini tentang kepercayaan yang tersirat. Angka port yang rendah menyiratkan kepercayaan yang tinggi. SSH, POP, FTP, dan daemon lain diharapkan untuk meminta kata sandi tingkat sistem dan kredensial lainnya ketika port mereka dibuka. Jika pengguna diizinkan untuk mendengarkan pada port rendah pada sebuah kotak, mereka dapat memulai daemon palsu pada port yang tidak digunakan (atau macet) dan mengambil kata sandi dari pengguna yang tidak curiga. Kata sandi tersebut kemudian dapat digunakan pada kotak itu untuk berkompromi dengan akun lain, termasuk root.
Caleb
8
Itu bentuk keamanan yang cukup lemah. Jika Anda terhubung ke sesuatu dan tidak melakukan transaksi sertifikat maka Anda tidak tahu dengan siapa Anda berbicara - yaitu serangan MITM.
pjc50
5
Saya kira yang dibutuhkan adalah chown untuk port: maka Anda bisa "chown mail port25" lalu (a) daemon mail Anda tidak perlu dimulai dengan root privs dan (b) tidak ada orang lain yang dapat membajaknya.
pjc50
7
Walaupun ini mungkin benar "dengan desain" ketika linux masih dalam masa pertumbuhan, itu sangat tidak masuk akal dulu dan sekarang. Keamanan adalah tentang apa yang dapat dan tidak bisa dilakukan oleh pengguna. Membiarkan hanya pengguna root untuk menggunakan port 80, misalnya, adalah risiko keamanan yang sangat besar, karena itu berarti Anda harus memberikan akses root kepada orang-orang yang perlu menggunakan port 80 tetapi tidak boleh memiliki akses root. Jika Anda memercayai pengguna X-root untuk menggunakan port 80, Anda harus bisa menyandikan kepercayaan itu di OS Anda. Untungnya, seperti yang Anda sebutkan, ada pekerjaan kasar yang memungkinkan ini, seperti authbind.
BT
3

Anda bisa menggunakan penerusan port netcat atau xinetd atau iptables, atau menggunakan apache sebagai proxy ujung depan dan menjalankan proses pada port yang tidak memiliki hak istimewa.

jamespo
sumber
3

Authbind , @Gilles sudah menyebutkannya, tapi saya ingin sedikit mengembangkannya.

Ini memiliki kontrol akses yang mudah (detail dalam halaman manual): Anda dapat memfilter akses berdasarkan port, alamat antarmuka, uid, rentang alamat atau port dan kombinasi dari semuanya.

Ini memiliki parameter yang sangat berguna --depth:

- Tingkat kedalaman

Menyebabkan authbind mempengaruhi program yang levelnya jauh di dalam grafik panggilan. Standarnya adalah 1.

"Levels deep" artinya ketika skrip (atau program), menjalankan skrip lain, skrip ini turun satu level. Jadi jika Anda memilikinya --depth 5berarti pada level 1 (atau 0?) Hingga 5 Anda memiliki izin untuk mengikat, sedangkan pada level 6 dan seterusnya, Anda tidak. Berguna saat Anda ingin skrip memiliki akses, tetapi bukan program yang dijalankan dengan atau tanpa sepengetahuan Anda.


Sebagai ilustrasi, Anda dapat memiliki sesuatu seperti ini: demi keamanan, Anda memiliki pengguna javayang dimaksudkan untuk hanya menjalankan java dan Anda ingin memberinya akses ke port 80:

echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80

Saya telah membuat ../byport/80 file, memberikannya ke javagrup pengguna (setiap pengguna memiliki grup sendiri), dan membuatnya dapat dijalankan oleh grup, yang berarti itu dapat dieksekusi oleh javapengguna. Jika Anda memberikan akses dengan port, file harus dapat dieksekusi oleh pengguna yang seharusnya memiliki akses, jadi kami melakukannya.

Ini mungkin cukup untuk Joe rata-rata, tetapi karena Anda tahu cara menggunakan --depthparameter, Anda menjalankan (sebagai javapengguna) authbind --depth [depth] my_web_app's_start_scriptmulai --depth 1dan bekerja sampai Anda menemukan kedalaman terkecil yang berfungsi dan menggunakannya.

Baca halaman manual untuk detailnya .

Dominykas Mostauskis
sumber
1

Saya mencoba metode iptables PREROUTING REDIRECT, tetapi ternyata itu juga mempengaruhi paket yang diteruskan. Yaitu, jika mesin juga meneruskan paket antar antarmuka (mis. Jika itu bertindak sebagai titik akses Wi-Fi yang terhubung ke jaringan Ethernet), maka aturan iptables juga akan menangkap koneksi klien yang terhubung ke tujuan Internet, dan mengarahkan mereka ke mesin. Bukan itu yang saya inginkan — saya hanya ingin mengarahkan kembali koneksi yang diarahkan ke mesin itu sendiri.

Salah satu kemungkinan adalah menggunakan penerusan port TCP. Misalnya menggunakan socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

Namun satu kelemahan dengan metode itu adalah, aplikasi yang mendengarkan pada port 8080 kemudian tidak tahu alamat sumber koneksi yang masuk (misalnya untuk logging atau keperluan identifikasi lainnya).

Craig McQueen
sumber