Soru Port 80'de bir sunucu Linux'ta normal kullanıcı olarak nasıl çalıştırılır?


Bir süredir bunun için araştırdım ama bulamadım.

Ubuntu Linux'dayım ve 80 numaralı bağlantı noktasında bir sunucu çalıştırmak istiyorum, ancak Ubuntu'nun güvenlik mekanizması nedeniyle aşağıdaki hatayı alıyorum:

java.net.BindException: İzin verilmedi: 80

Bence bu güvenlik mekanizmasını devre dışı bırakacak kadar basit olmalı, böylece port 80 tüm kullanıcılar tarafından kullanılabilir veya mevcut kullanıcıya port 80'e erişmek için gerekli ayrıcalıkları atayabilir.


282
2017-11-10 14:31


Menşei


Sunucuyu, ayrıcalıklı olmayan başka bir bağlantı noktasında çalıştırmak için sorun nedir? Bu bağlantı noktasında bir sunucuyu çalıştırmak için en az ciddi bir neden sağlamadan güvenlik mekanizmasını devre dışı bırakmak kadar sert bir şey düşünmektesiniz. Sunucu 80 numaralı bağlantı noktasına bağlanacak mı? Eğer öyleyse, atın. - Anonymous
Ya da bir Python hata mesajı: socket.error: [Errno 13] Permission denied - Kazark
olası kopyası 1024 altındaki portları kullanan düzenli kullanıcı - Roman
Yapamazsın. 1024'ün altındaki bağlantı noktaları ayrıcalıklıdır ve sadece kökler üzerinde dinleme soketi açabilir. Yapılacak uygun şey, açıldıktan sonra izinleri bırakmaktır. - Falcon Momot
"Anonim" - dünyadaki kullanıcılar belirli limanlarda belirli servisleri aramak üzere eğitildi. Bazı durumlarda, standartlaştırılmıştır. Örneğin, bağlantı noktası 80 ve bağlantı noktası 443'teki HTTPS'deki HTTP. Kullanıcıları ve dünya standartlarını değiştirmek zor. - jww


Cevaplar:


Kısa cevap: yapamazsın. 1024'ün altındaki portlar sadece root tarafından açılabilir. Yoruma göre - iyi, kullanarak, CAP_NET_BIND_SERVICEAncak, java kutusuna uygulanan bu yaklaşım, herhangi bir java programının bu ayar ile çalıştırılmasını sağlayacaktır, ki bu güvenlik riski olmasa da istenmeyen bir durumdur.

Uzun cevap: Bağlantı noktası 80'deki bağlantıları normal kullanıcı olarak açabileceğiniz başka bir bağlantı noktasına yönlendirebilirsiniz.

Kök olarak çalıştır:

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

Geridöngü aygıtları (localhost gibi), localhost vb. Kullanmanız gerekiyorsa, ön kurallarını kullanmaz. Bu kuralı da ekleyin (teşekkürler @Francesco):

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

NOT: Yukarıdaki çözüm değil çok kullanıcılı sistemler için çok uygundur, herhangi bir kullanıcı 8080 numaralı bağlantı noktasını (veya kullanmaya karar verdiğiniz herhangi bir yüksek portu) açabilir, böylece trafiği engelleyebilir. (Krediler CesarB).

EDIT: yorum sorusu başına - yukarıdaki kuralı silmek için:

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

Bu gibi bir şey çıktı:

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

İlgilendiğiniz kural nr. 2, bunu silmek için:

# iptables -t nat -D PREROUTING 2

331
2017-11-10 14:41



@Sunny: upvotes batıdaki en hızlı silah için değil, en iyi yanıtlar için. Sizinki şu ana kadarki en iyisi (sadece iptables'den bahsettim; aslında tam komut satırını sağladınız). Benimkilerin sahip olduğu tek şey, diğer kullanıcıların da 8080 numaralı limana bağlanabilmeleri hakkındaki uyarı. - CesarB
Bunun IPv6 ile çalışmadığını unutmayın. - Emmanuel Bourg
İstediğim zaman bu kuralı nasıl kaldırabileceğimi açıklayabilir mi? Çalıştırdıktan sonra işe yarıyor ama görünüşe göre bir "kural" değil çünkü ne zaman yaparım sudo iptables --list. Iptables'in ne olduğunu biliyor ve yapıyor, ama bundan önce hiç kullanmadım. - Encoderer
Cevabınız için teşekkürler ... Ubuntu'yu yeniden başlattığımda, bu kural kaybolur ve tekrar çalıştırmam gerekir. Sonsuza dek saklamanın bir yolu var mı? - Coderji
@Coderji: topluluk belgelerindeki "kaydet" bölümünü kontrol edin: help.ubuntu.com/community/IptablesHowTo - Sunny


kullanım authbind.

Java'nın IPv4-only yığınını etkinleştirirseniz Java ile bile çalışır. Kullanırım:

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

77
2017-11-14 13:12



Sunucu Tomcat ise authbind'i ayarlayarak otomatik olarak kullanabilirsiniz. AUTHBIND=yes / etc / default / tomcat6 içinde - Emmanuel Bourg
Bunu, varsayılan Java paketiyle Ubuntu sunucusunda çalışmak için alamadım ... - Ashley Steel
Ben de bilinen herhangi bir çözüm yok mu? - mark
Yapılandırmanız gerektiğini unutmayın authbind Bunun gerçekleşmesine izin vermek. Man sayfasından: "/ etc / authbind / byport / port sınanmıştır. Bu dosya, çağrı yapan kullanıcıya yürütme için erişilebilirse, erişim (2) 'ye göre, bağlantı noktasına bağlanır.", Örneğin. 80 numaralı bağlantı noktası için sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80. İlk yükleme authbind genellikle önceden yapılandırılmış yetkilendirmelere sahip değildir. - Jason C
Oh nonononononono, asla hiçbir şeye 777 hiç bir şey yapma! - Johannes


Sisteminiz destekliyorsa, yetenekleri kullanabilirsiniz. İhtiyacınız olan kişi yeteneklerine bakın, CAP_NET_BIND_SERVICE.

Daha yeni Debian / Ubuntu'da şunları çalıştırabilirsiniz:

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

46
2018-05-30 20:32



Bu nodejs için çalışır: setcap 'cap_net_bind_service = + ep' / usr / bin / nodejs - JasonS
Bu. Bu cevabın neden daha fazla vahim olmadığını merak ediyorum. Iptables seçeneği imho çok daha kolay. - Dominik R
Bu doğru ve en verimli cevaptır, diğer tüm cevaplar bir performans isabeti veya sadece iffy / güvensizliğe neden olur. - OneOfOne


Başka bir çözüm de uygulamanızı setuid yapmak ve böylece bağlantı noktası 80 ile bağlanabilmektir. Kök olarak aşağıdakileri yapın:

chown root ./myapp
chmod +S ./myapp

Tamamen yapılmadığı sürece bunu yapmanın potansiyel güvenlik açıklarına maruz kalacağını, çünkü uygulamanızın ağla konuşacağını ve tam kök ayrıcalıklarıyla çalışacağını unutmayın. Bu çözümü alırsanız, Apache veya Lighttpd kaynak koduna veya benzer bir bağlantıya bakmanız gerekir, burada bağlantı noktasını açmak için kök ayrıcalıklarını kullanırlar, ancak sonra hemen bu ayrıcalıklardan vazgeçip daha düşük ayrıcalıklı bir kullanıcı haline gelirler. Bir korsan, tüm bilgisayarını ele geçiremez.

Güncelleme: Görüldüğü gibi bu soru, 2.6.24'ten beri Linux çekirdeklerinin, bir çalıştırılabilir dosyayı (tabii ki bir betiği değil) işaretlemenizi sağlayan yeni bir özelliğe sahip olduğu anlaşılıyor.CAP_NET_BIND_SERVICE"kabiliyet. Debian paketini" libcap2-bin "kurarsanız, komutu vererek bunu yapabilirsiniz.

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

39
2017-11-10 14:44



Uygulama, ayrıcalıkları nasıl düşüreceğini bilmedikçe, root olarak çalışmayla aynı şeydir. - CesarB
Bu tehlikeli. Bu, herhangi bir isteğin root olarak çalışacağı anlamına gelir. Apache'nin bile kök olarak bağlanmaya başlaması ve ardından ayrıcalıkların başka bir kullanıcıya bırakılması için bir sebepten dolayı. - Sunny
Paul: iptables çok tehlikeli değil, çünkü uygulama tehlikeye atılsa bile, en azından root imtiyazlarıyla değil, sistem saldırılarına maruz kalmaz. Uygulamayı root olarak çalıştırmak başka bir hikaye. - Sunny
Iptables için tehlike sadece eğer bu çok kişili bir sistemse, CesarB'nin dediği gibi, herkes 8080'e bağlanabilir ve trafiği engelleyebilir. - Sunny
lol, kabul edilen cevabın nasıl olduğunu bir-15 - Evan Teran


Sunny ve CesarB tarafından önerilen yaklaşım:

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

iyi çalışıyor ancak küçük bir dezavantajı var - kullanıcının 80 yerine 8080 portuna doğrudan bağlanmasını engellemez.

Bu bir sorun olduğunda aşağıdaki senaryoyu düşünün.

Bağlantı noktası 8080 ve HTTPS bağlantılarında 8181 numaralı bağlantı noktasında HTTP bağlantılarını kabul eden bir sunucumuz olduğunu varsayalım.

Aşağıdaki yönlendirmeleri kurmak için iptables'i kullanıyoruz:

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

Şimdi, sunucumuzun kullanıcıyı bir HTTP sayfasından bir HTTPS sayfasına yönlendirmeye karar verdiğini varsayalım. Yanıtı dikkatli bir şekilde yeniden yazmadıkça, https://host:8181/. Bu noktada, biz berbatız:

  • Bazı kullanıcılar https://host:8181/ URL ve yer işaretlerini kırmamak için bu URL'yi korumamız gerekiyordu.
  • Diğer kullanıcılar, proxy sunucuları standart olmayan SSL bağlantı noktalarını desteklemediğinden bağlanamazdı.

Aşağıdaki yaklaşımı kullanıyorum:

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

INPUT zincirindeki varsayılan REJECT kuralı ile birleştirildiğinde, bu yaklaşım kullanıcıların doğrudan 8080, 8181 bağlantı noktalarına bağlanmasını önler


35
2018-02-20 16:19



Bu iyi, ama neden sadece locayı localhost'a bağlama: 80.0.0.0.0:8080 yerine? Bunu yapmak istiyorum ama bunun için iptables'e ihtiyacım var. - Amala
Çok güzel çalışıyor. - xtian


Sadece Nginx'i ön tarafta kullanıyorum. Yerelde de çalışabilir.

  • apt-get install nginx

.. ya da ..

  • pkg_add -r nginx 

.. ya da işletim sisteminize uygun olanı.

Eğer localhost üzerinde çalışıyorsanız, nginx.conf içinde ihtiyacınız olan tek şey:

sunucu {
        80'i dinle;
        server_name some.domain.org;
        yer / {
            proxy_set_header Ana bilgisayar barındırıcısı;
            proxy_set_header X-Real-IP $ uzak_addr;
            proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8081;
        }
}

35
2017-11-20 14:30



Bu çözümü çok beğendim. - thomasfedb
Bu, JFrog'un kendisinden önerilen çözümdür (bir tanesi): jfrog.com/confluence/display/RTF/nginx - stolsvik


Geleneksel olarak Unix'te, sadece kök düşük bağlantı noktalarına bağlanabilir (<1024).

Bu konuda çalışmanın en kolay yolu sunucunuzu bir yüksek bağlantı noktası (örneğin, 8080) ve bağlantı noktaları 80'den bağlantı noktası 8080'e iletmek için basit bir iptables kuralı kullanın. Bununla birlikte, düşük bağlantı noktalarından ekstra korumayı kaybedersiniz; Makinenizdeki herhangi bir kullanıcı 8080 numaralı bağlantı noktasına bağlanabilir.


29
2017-11-10 14:36





Sisteminiz destekliyorsa, yetenekleri kullanabilirsiniz. Görmek man capabilities, ihtiyacın olan CAP_NET_BIND_SERVICE. Hayır, onları hiç kullanmadım ve gerçekten çalışıp çalışmadıklarını bilmiyorum :-)


23
2017-11-10 16:27



Çalışırlar, normal bir kullanıcı olarak tcpdump gibi araçları çalıştırmak için CAP_NET_RAW kullanırım. - Justin


Uygulama sunucularınızın önünde bir ters proxy (nginx, apache + mod_proxy) veya bir önbellek ters proxy (Squid, Vernik) kullanın!

Bir ters proxy ile, aşağıdaki gibi birçok ilginç şey elde edebilirsiniz:

  • Yük dengeleme
  • Uygulama sunucularınızı fantezi bir hata sayfası alan kullanıcılarla yeniden başlatma
  • Önbelleği ile şeyleri hızlandır
  • Bir uygulama sunucusu ile değil, ters proxy ile yaptığınız ince ayarlı ayarlar

11
2017-10-18 15:36





Yönlendirme programını kullanabilirsiniz:

sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1

6
2017-11-27 12:48





Sudo kullan.

Sudo'yu, normal kullanıcının uygun komutları çalıştırabileceği şekilde yapılandırın:

/etc/init.d/httpd start

Veya

apachectl stop

Veya

/usr/local/apache2/apachectl restart

Veya

/myapp/myappbin start

(Ya da belirli bir web sunucusu / uygulaması başlatmak / durdurmak için kullandığınız diğer komut / komut dosyaları)


4
2017-11-10 19:40



Bu aynı soruna sahiptir - bir hizmetin kök olarak çalışması kötü bir uygulamadır. - Kevin Panko