Pertanyaan Bagaimana cara menjalankan server di port 80 sebagai pengguna normal di Linux?


Saya telah googled tentang itu untuk beberapa waktu, tetapi tidak dapat menemukannya.

Saya berada di Ubuntu Linux dan ingin menjalankan server di port 80, tetapi karena mekanisme keamanan Ubuntu, saya mendapatkan kesalahan berikut:

java.net.BindException: Izin ditolak: 80

Saya pikir itu harus cukup sederhana untuk menonaktifkan mekanisme keamanan ini sehingga port 80 tersedia untuk semua pengguna atau untuk menetapkan hak yang diperlukan kepada pengguna saat ini untuk mengakses port 80.


281
2017-11-10 14:31




Apa masalah untuk menjalankan server pada port lain yang tidak memiliki hak? Anda berpikir tentang sesuatu yang keras seperti menonaktifkan mekanisme keamanan tanpa memberikan setidaknya alasan yang sangat serius untuk menjalankan server di port itu. Apakah server hardcoded untuk berikatan dengan port 80? Jika demikian, buanglah. - Anonymous
Atau pesan kesalahan Python: socket.error: [Errno 13] Permission denied - Kazark
kemungkinan duplikat dari Pengguna biasa menggunakan port di bawah 1024 - Roman
Anda tidak bisa. Port di bawah 1024 memiliki hak istimewa dan hanya root yang dapat membuka soket mendengarkan di atasnya. Hal yang tepat untuk dilakukan adalah menjatuhkan izin setelah membukanya. - Falcon Momot
"Anonim" - pengguna di dunia telah dilatih untuk mencari layanan tertentu di port tertentu. Dalam beberapa contoh, sudah distandardisasi. Misalnya, HTTP pada port 80 dan HTTPS pada port 443. Agak sulit untuk mengubah pengguna dan standar dunia. - jww


Jawaban:


Jawaban singkat: Anda tidak bisa. Port di bawah 1024 hanya dapat dibuka oleh root. Sesuai komentar - baik, Anda bisa, menggunakan CAP_NET_BIND_SERVICENamun, pendekatan itu, diterapkan pada java bin akan membuat program java dijalankan dengan pengaturan ini, yang tidak diinginkan, jika bukan risiko keamanan.

Jawaban panjang: Anda dapat mengalihkan koneksi pada port 80 ke beberapa port lain yang dapat Anda buka sebagai pengguna biasa.

Jalankan sebagai root:

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Karena perangkat loopback (seperti localhost) tidak menggunakan aturan prerouting, jika Anda perlu menggunakan localhost, dll., Tambahkan juga aturan ini (terima kasih @Francesco):

# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080

CATATAN: Solusi di atas tidak cocok untuk sistem multi-pengguna, karena setiap pengguna dapat membuka port 8080 (atau port tinggi lainnya yang Anda putuskan untuk digunakan), sehingga mencegat lalu lintas. (Kredit untuk CesarB).

EDIT: sesuai pertanyaan komentar - untuk menghapus aturan di atas:

# iptables -t nat --line-numbers -n -L

Ini akan menghasilkan sesuatu seperti:

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 redir ports 8088
2    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 8080

Aturan yang Anda minati adalah nr. 2, jadi untuk menghapusnya:

# iptables -t nat -D PREROUTING 2

330
2017-11-10 14:41



@Sunny: upvotes bukan untuk senjata tercepat di barat, tetapi untuk respons terbaik. Anda adalah yang terbaik sejauh ini (saya hanya menyebutkan iptables; Anda benar-benar menyediakan baris perintah lengkap). Satu-satunya milik saya memiliki Anda tidak adalah peringatan tentang pengguna lain juga bisa mengikat ke port 8080. - CesarB
Perhatikan bahwa ini tidak bekerja dengan IPv6. - Emmanuel Bourg
Adakah yang bisa menjelaskan bagaimana saya dapat menghapus aturan ini nanti ketika saya ingin? Setelah menjalankannya, itu berhasil, tetapi tampaknya itu bukan "aturan" karena tidak muncul ketika saya melakukannya sudo iptables --list. Saya tahu apa itu iptables dan apa yang dilakukannya, tetapi saya tidak pernah benar-benar menggunakannya sebelum ini. - Encoderer
Terima kasih atas jawaban Anda ... setiap kali saya mereboot Ubuntu, aturan ini menghilang dan saya harus menjalankannya lagi. Apakah ada cara untuk menyimpannya selamanya? - Coderji
@Coderji: periksa bagian "simpan" di dokumentasi komunitas: help.ubuntu.com/community/IptablesHowTo - Sunny


Menggunakan authbind.

Ia bahkan bekerja dengan Java jika Anda mengaktifkan Java's IPv4-only stack. Saya menggunakan:

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …

77
2017-11-14 13:12



Jika server adalah Tomcat Anda dapat menggunakan authbind secara otomatis dengan pengaturan AUTHBIND=yes di / etc / default / tomcat6 - Emmanuel Bourg
Saya tidak bisa mendapatkan ini untuk bekerja pada server Ubuntu dengan paket Java default ... - Ashley Steel
Saya tidak, solusi yang dikenal? - mark
Perhatikan bahwa Anda harus mengonfigurasi authbind untuk benar-benar memungkinkan ini terjadi. Dari halaman manual: "/ etc / authbind / byport / port diuji. Jika file ini dapat diakses untuk dieksekusi ke pemanggil pengguna, sesuai dengan akses (2), maka mengikat ke port berwenang.", mis. untuk port 80, sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80. Pemasangan awal authbind umumnya tidak memiliki otorisasi pra-konfigurasi. - Jason C
Oh nonononononono, jangan pernah kicau 777 apapun! - Johannes


Jika sistem Anda mendukungnya Anda mungkin bisa menggunakan kemampuan. Lihat kemampuan manusia, yang Anda butuhkan adalah CAP_NET_BIND_SERVICE.

Pada Debian / Ubuntu yang lebih baru Anda dapat menjalankan:

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program

45
2018-05-30 20:32



ini berfungsi untuk nodejs: setcap 'cap_net_bind_service = + ep' / usr / bin / nodejs - JasonS
Ini. Saya bertanya-tanya mengapa jawaban ini tidak lebih menghasut. Jauh lebih mudah daripada opsi iptables imho. - Dominik R
ini adalah jawaban yang benar dan paling efisien, semua jawaban yang lain menyebabkan pukulan kinerja atau hanya meragukan / tidak aman. - OneOfOne


Solusi lain adalah membuat aplikasi Anda setuid sehingga dapat mengikat dengan port 80. Sebagai root, lakukan hal berikut

chown root ./myapp
chmod +S ./myapp

Perlu diingat bahwa melakukan hal ini, kecuali jika dilakukan dengan benar, akan memaparkan Anda ke lubang keamanan potensial, karena aplikasi Anda akan berbicara dengan jaringan, dan akan berjalan dengan privilese root penuh. Jika Anda mengambil solusi ini, Anda harus melihat kode sumber untuk Apache atau Lighttpd atau yang serupa, di mana mereka menggunakan hak akses root untuk membuka port, tetapi kemudian segera menyerahkan privs tersebut dan "menjadi" pengguna istimewa yang lebih rendah sehingga pembajak tidak dapat mengambil alih seluruh komputer Anda.

Pembaruan: Seperti yang terlihat di pertanyaan ini, tampaknya kernel Linux sejak 2.6.24 memiliki kemampuan baru yang memungkinkan Anda untuk menandai eksekusi (tetapi bukan skrip, tentu saja) karena memiliki "CAP_NET_BIND_SERVICE"Kemampuan. Jika Anda menginstal paket debian" libcap2-bin ", Anda dapat melakukannya dengan mengeluarkan perintah

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

39
2017-11-10 14:44



Itu sama dengan menjalankan sebagai root, kecuali aplikasi tahu cara menjatuhkan priviledges. - CesarB
Ini berbahaya. Ini berarti bahwa setiap permintaan akan dijalankan sebagai root. Ini karena suatu alasan bahwa bahkan apache dimulai sebagai root untuk mengikat, dan kemudian menjatuhkan privileges ke pengguna lain. - Sunny
Paul: iptables tidak begitu berbahaya, karena meskipun aplikasi tersebut disusupi, ia tidak akan mengekspos sistem pada serangan, setidaknya tidak dengan hak akses root. Menjalankan aplikasi sebagai root adalah cerita lain. - Sunny
Bahaya untuk iptables hanya jika ini adalah sistem multi-pengguna, seperti yang dikatakan CesarB, karena siapa pun dapat mengikat ke 8080, dan memotong lalu lintas. - Sunny
lol, suka bagaimana jawaban yang diterima memiliki -15 - Evan Teran


Pendekatan yang diusulkan oleh Sunny dan CesarB:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

berfungsi dengan baik tetapi memiliki kelemahan kecil - itu tidak mencegah pengguna menghubungkan langsung ke port 8080, bukan 80.

Pertimbangkan skenario berikut ketika ini bisa menjadi masalah.

Katakanlah kita memiliki server yang menerima koneksi HTTP pada port 8080 dan koneksi HTTPS pada port 8181.

Kami menggunakan iptables untuk menetapkan pengalihan berikut:

80  ---> 8080
443 ---> 8181

Sekarang, anggap server kami memutuskan untuk mengalihkan pengguna dari halaman HTTP ke halaman HTTPS. Kecuali kita menulis ulang jawaban dengan hati-hati, itu akan mengarahkan ke https://host:8181/. Pada titik ini, kita gagal:

  • Beberapa pengguna akan mem-bookmark https://host:8181/ URL dan kami perlu mempertahankan URL ini untuk menghindari pembatas bookmark mereka.
  • Pengguna lain tidak akan dapat terhubung karena server proxy mereka tidak mendukung port SSL non-standar.

Saya menggunakan pendekatan berikut:

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT

Dikombinasikan dengan aturan REJECT default pada rantai INPUT, pendekatan ini mencegah pengguna menghubungkan langsung ke port 8080, 8181


35
2018-02-20 16:19



Ini bagus, tetapi mengapa tidak hanya mengikat daemon ke localhost: 8080 alih-alih 0.0.0.0:8080? Saya ingin melakukan itu, tapi saya butuh iptables untuk itu. - Amala
Ini bekerja, sangat keren. - xtian


Saya hanya menggunakan Nginx di depan. Ini dapat berjalan di localhost juga.

  • apt-get install nginx

.. atau ..

  • pkg_add -r nginx 

.. atau apa yang cocok dengan OS Anda.

Yang Anda butuhkan di nginx.conf, jika berjalan di localhost, adalah:

server {
        dengarkan 80;
        server_name some.domain.org;
        lokasi / {
            proxy_set_header Host $ host;
            proxy_set_header X-Real-IP $ remote_addr;
            proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8081;
        }
}

34
2017-11-20 14:30



Saya sangat suka solusi ini. - thomasfedb
Ini adalah (salah satu) solusi yang disarankan dari JFrog sendiri: jfrog.com/confluence/display/RTF/nginx - stolsvik


Secara tradisional pada Unix, hanya root yang dapat berikatan dengan port rendah (<1024).

Cara termudah untuk mengatasi ini adalah dengan menjalankan server Anda pada tinggi port (misalnya, 8080) dan menggunakan aturan iptables sederhana untuk meneruskan koneksi dari port 80 ke port 8080. Perhatikan bahwa dengan ini Anda kehilangan perlindungan ekstra dari port rendah; setiap pengguna di komputer Anda dapat mengikat ke port 8080.


29
2017-11-10 14:36





Jika sistem Anda mendukungnya Anda mungkin bisa menggunakan kemampuan. Lihat man capabilities, yang Anda butuhkan CAP_NET_BIND_SERVICE. Tidak, saya tidak pernah menggunakan mereka sendiri dan saya tidak tahu apakah mereka benar-benar berfungsi :-)


23
2017-11-10 16:27



mereka bekerja, saya menggunakan CAP_NET_RAW untuk menjalankan alat seperti tcpdump sebagai pengguna biasa. - Justin