私はかなり前から解決策についてグーグルで調べましたが、答えを見つけることができませんでした。
Ubuntu Linuxを使用していて、ポート80でサーバーを実行したいのですが、Ubuntuのセキュリティメカニズムのため、次のエラーが発生します。
Java.net.BindException:権限が拒否されました:80
このセキュリティメカニズムを無効にしてすべてのユーザーがポート80を使用できるようにするか、現在のユーザーにポート80にアクセスするために必要な特権を割り当てるのは簡単だと思います。
短い答え:できません。 1024未満のポートは、ルートのみが開くことができます。コメントどおり CAP_NET_BIND_SERVICE を使用できますが、Java binに適用されるそのアプローチは、Javaプログラムを作成しますこの設定で実行することは、セキュリティリスクではないとしても望ましくありません。
長い答え:ポート80の接続を、通常のユーザーとして開くことができる他のポートにリダイレクトできます。
ルートとして実行:
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
ループバックデバイス(localhostなど)は事前ルーティングルールを使用しないため、localhostなどを使用する必要がある場合は、このルールも追加します( thanks @Francesco ):
# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
注:上記のソリューションはマルチユーザーシステムには適していません。これは、どのユーザーもポート8080(または使用する他のハイポート)を開くことができるためです。 )、トラフィックを遮断します。 ( CesarB へのクレジット)。
編集:コメントの質問に従って-上記のルールを削除するには:
# iptables -t nat --line-numbers -n -L
これは次のようなものを出力します:
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
関心のあるルールはnrです。 2、それを削除するには:
# iptables -t nat -D PREROUTING 2
authbind を使用します。
これは、Javaでも機能します。JavaのIPv4専用スタックを有効にすると、次のようになります。
authbind --deep $Java_HOME/bin/Java -Djava.net.preferIPv4Stack=true …
システムでサポートされている場合は、機能を使用できます。 man機能を参照してください。必要なのはCAP_NET_BIND_SERVICEです。
新しいDebian/Ubuntuでは、次のコマンドを実行できます。
Sudo apt-get install libcap2-bin
Sudo setcap 'cap_net_bind_service=+ep' /path/to/program
別の解決策は、ポート80でバインドできるようにアプリをsetuidすることです。ルートとして、次の操作を行います
chown root ./myapp
chmod +S ./myapp
アプリがネットワークと通信し、完全なルート権限で実行されるため、これを行うと、完全に正しく行われない限り、潜在的なセキュリティホールにさらされることに注意してください。このソリューションを採用する場合は、ApacheやLighttpdなどのソースコードを確認してください。ルート特権を使用してポートを開き、すぐにそれらの特権を放棄して、より低い特権のユーザーになるようにしてください。ハイジャッカーがコンピュータ全体を乗っ取ることはできません。
更新: この質問 に見られるように、2.6.24以降のLinuxカーネルには、実行可能ファイル(もちろんスクリプトではない)に「CAP_NET_BIND_SERVICE
"機能。debianパッケージ" libcap2-bin "をインストールする場合は、次のコマンドを発行して実行できます。
setcap 'cap_net_bind_service=+ep' /path/to/program
私は単に前のNginxを使用します。ローカルホストでも実行できます。
apt-get install nginx
..または..
pkg_add -r nginx
..または、これまであなたのOSに適したもの。
ローカルホストで実行している場合、nginx.confに必要なのは次のとおりです。
server { listen 80; server_name some.domain.org; location/{ 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; } }
SunnyとCesarBによって提案されたアプローチ:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
正常に動作しますが、小さな欠点があります-ユーザーが80ではなくポート8080に直接接続することを妨げません。
これが問題になる可能性がある場合は、次のシナリオを検討してください。
ポート8080でHTTP接続を受け入れ、ポート8181でHTTPS接続を受け入れるサーバーがあるとします。
Iptablesを使用して、次のリダイレクトを確立します。
80 ---> 8080
443 ---> 8181
ここで、サーバーがユーザーをHTTPページからHTTPSページにリダイレクトすることを決定したとします。応答を慎重に書き換えない限り、https://Host:8181/
にリダイレクトされます。この時点で、私たちはねじ込まれています:
https://Host:8181/
URLをブックマークします。ブックマークを壊さないように、このURLを維持する必要があります。私は次のアプローチを使用します:
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チェーンのデフォルトのREJECTルールと組み合わせると、このアプローチはユーザーがポート8080、8181に直接接続するのを防ぎます
伝統的にUnixでは、ルートのみが低いポート(<1024)にバインドできます。
これを回避する最も簡単な方法は、サーバーをhighポート(たとえば、8080)で実行し、単純なiptablesルールを使用して、接続をポート80からポート8080に転送することです。低ポートからの余分な保護を失う;マシン上のすべてのユーザーがポート8080にバインドできます。
システムでサポートされている場合は、機能を使用できます。見る man capabilities
、必要なのはCAP_NET_BIND_SERVICE
。いいえ、私はそれらを自分で使用したことがなく、本当に機能するかどうかはわかりません:-)
アプリケーションサーバーの前でリバースプロキシ(nginx、Apache + mod_proxy)またはキャッシングリバースプロキシ(Squid、Varnish)を使用してください!
リバースプロキシを使用すると、次のような多くの興味深いことが実現できます。
Redirプログラムを使用できます。
Sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
晴れの答えは正しいですが、ループバックインターフェイスがPREROUTINGテーブルを使用しないため、追加の問題に直面する可能性があります。
追加するiptablesルールは2つです。
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
Sudoを使用します。
通常のユーザーが適切なコマンドを実行できるようにSudoを構成します。
/etc/init.d/httpd start
または
apachectl stop
または
/usr/local/Apache2/apachectl restart
または
/myapp/myappbin start
(または、特定のウェブサーバー/アプリを起動/停止するために使用する他のコマンド/スクリプト)
Linuxでは、他に2つのオプションがあります。
Linuxカーネルの両方の拡張により、非常に細かいレベルでアクセス権を付与できます。これにより、このプロセスにポート80を開く許可を与えることができますが、他のルート権限を継承しません。
私が聞いたところによると、grsecurityの方がはるかに使いやすいですが、SELinuxの方が安全です。
私は最良の解決策はあなたのアプリをsgidすることだと思います、そしてそれがそのポートにバインドされたらすぐに別のユーザーに切り替えることによって特権を落とすべきです。
1つの解決策は、iptablesを使用してポート80のパケットでPATを実行することです。これを使用して、たとえば、パケットをローカルポート8080にルーティングできます。必ず、送信パケットをポート80に戻すように調整してください。
私の経験では、セキュリティの問題のため、Linuxのきめ細かな権限機能は標準カーネルにコンパイルされていません。
ユーザーが実行するコマンドがポート80を使用できるようにこれを行おうとしている場合、唯一の解決策は、iptablesトリックまたは実行可能なsetuid-to-rootを設定することです。
Apacheのような方法(これはポート80にバインドされますが、root以外の誰かとして実行されています)は、rootとして実行され、ポートにバインドされ、ポートの後にプロセスの所有権を非特権ユーザーに変更しますセットアップされます。作成しているアプリがrootによってrunになる可能性がある場合は、ポートのセットアップ後に所有者を非プライベートユーザーに変更できます。しかし、これが平均的なユーザーがコマンドラインから実行するためだけの場合は、他のソリューションのいずれかを使用する必要があります。
ルートとして実行したくないさまざまなWebサービスアプリケーション(Pythonスクリプト、Tomcatエンジンなど)がある場合、通常はそれらの前にApache Webサーバーを構成します。 Apacheはポート80をリッスンし、Tomcatは8080をリッスンします。
Apacheの構成:
ProxyPass /webapp http://localhost:8080/webapp
ProxyPassReverse /webapp http://localhost:8080/webapp
詳細については、mod-proxyのドキュメントを参照してください。 http://httpd.Apache.org/docs/2.2/mod/mod_proxy.html
一部のホストシステムはNATモジュールの使用を許可していません。'iptables 'はこの場合の問題を解決しません。
Xinetdはどうですか?
私の場合(ubuntu 10.04)
# apt-get install xinetd
# touch /etc/xinetd.d/my_redirect
# vim /etc/xinetd.d/my_redirect
構成を貼り付けます。
service my_redirector_80
{
disable = no
socket_type = stream
protocol = tcp
user = root
wait = no
port = 80
redirect = localhost 8080
type = UNLISTED
}
次に:
# service xinetd restart
余談ですが、FreeBSDとSolaris(誰でもthat one?を覚えていますか?)を使用すると、特権の昇格(つまり、プログラムを使用してrootに切り替える)なしでこれを実行できます(低ポートにバインド)。 Linuxを指定したので、この質問を見つける可能性がある他の人への通知としてこれを投稿しています。