web-dev-qa-db-ja.com

Linuxで通常のユーザーとしてポート80でサーバーを実行する方法

私はかなり前から解決策についてグーグルで調べましたが、答えを見つけることができませんでした。

Ubuntu Linuxを使用していて、ポート80でサーバーを実行したいのですが、Ubuntuのセキュリティメカニズムのため、次のエラーが発生します。

Java.net.BindException:権限が拒否されました:80

このセキュリティメカニズムを無効にしてすべてのユーザーがポート80を使用できるようにするか、現在のユーザーにポート80にアクセスするために必要な特権を割り当てるのは簡単だと思います。

324
Deepak Mittal

短い答え:できません。 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
366
Sunny

authbind を使用します。

これは、Javaでも機能します。JavaのIPv4専用スタックを有効にすると、次のようになります。

authbind --deep $Java_HOME/bin/Java -Djava.net.preferIPv4Stack=true …
81
geocar

システムでサポートされている場合は、機能を使用できます。 man機能を参照してください。必要なのはCAP_NET_BIND_SERVICEです。

新しいDebian/Ubuntuでは、次のコマンドを実行できます。

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

別の解決策は、ポート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
42
Paul Tomblin

私は単に前の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;
} 
 } 
41
CosmicB

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を維持する必要があります。
  • 他のユーザーは、プロキシサーバーが非標準のSSLポートをサポートしていないため、接続できません。

私は次のアプローチを使用します:

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に直接接続するのを防ぎます

36
Misha

伝統的にUnixでは、ルートのみが低いポート(<1024)にバインドできます。

これを回避する最も簡単な方法は、サーバーをhighポート(たとえば、8080)で実行し、単純なiptablesルールを使用して、接続をポート80からポート8080に転送することです。低ポートからの余分な保護を失う;マシン上のすべてのユーザーがポート8080にバインドできます。

29
CesarB

システムでサポートされている場合は、機能を使用できます。見る man capabilities、必要なのはCAP_NET_BIND_SERVICE。いいえ、私はそれらを自分で使用したことがなく、本当に機能するかどうかはわかりません:-)

23
WMR

アプリケーションサーバーの前でリバースプロキシ(nginx、Apache + mod_proxy)またはキャッシングリバースプロキシ(Squid、Varnish)を使用してください!

リバースプロキシを使用すると、次のような多くの興味深いことが実現できます。

  • 負荷分散
  • 派手なエラーページを受け取ったユーザーでアプリケーションサーバーを再起動する
  • キャッシュでスピードアップ
  • アプリケーションサーバーではなくリバースプロキシで通常行う細かい設定
12

Redirプログラムを使用できます。

Sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
6
user340994

晴れの答えは正しいですが、ループバックインターフェイスが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
4
Francesco

Sudoを使用します。

通常のユーザーが適切なコマンドを実行できるようにSudoを構成します。

/etc/init.d/httpd start

または

apachectl stop

または

/usr/local/Apache2/apachectl restart

または

/myapp/myappbin start

(または、特定のウェブサーバー/アプリを起動/停止するために使用する他のコマンド/スクリプト)

4
Not Now

Linuxでは、他に2つのオプションがあります。

Linuxカーネルの両方の拡張により、非常に細かいレベルでアクセス権を付与できます。これにより、このプロセスにポート80を開く許可を与えることができますが、他のルート権限を継承しません。

私が聞いたところによると、grsecurityの方がはるかに使いやすいですが、SELinuxの方が安全です。

3
Aaron Digulla

私は最良の解決策はあなたのアプリをsgidすることだと思います、そしてそれがそのポートにバインドされたらすぐに別のユーザーに切り替えることによって特権を落とすべきです。

2
Anxy Dicy

1つの解決策は、iptablesを使用してポート80のパケットでPATを実行することです。これを使用して、たとえば、パケットをローカルポート8080にルーティングできます。必ず、送信パケットをポート80に戻すように調整してください。

私の経験では、セキュリティの問題のため、Linuxのきめ細かな権限機能は標準カーネルにコンパイルされていません。

2
Darron

ユーザーが実行するコマンドがポート80を使用できるようにこれを行おうとしている場合、唯一の解決策は、iptablesトリックまたは実行可能なsetuid-to-rootを設定することです。

Apacheのような方法(これはポート80にバインドされますが、root以外の誰かとして実行されています)は、rootとして実行され、ポートにバインドされ、ポートの後にプロセスの所有権を非特権ユーザーに変更しますセットアップされます。作成しているアプリがrootによってrunになる可能性がある場合は、ポートのセットアップ後に所有者を非プライベートユーザーに変更できます。しかし、これが平均的なユーザーがコマンドラインから実行するためだけの場合は、他のソリューションのいずれかを使用する必要があります。

2
rjray

ルートとして実行したくないさまざまな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

2
Anders Westrup

一部のホストシステムは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

http://docs.codehaus.org/display/JETTY/port8 で説明します。

1
Thomas

余談ですが、FreeBSDとSolaris(誰でもthat one?を覚えていますか?)を使用すると、特権の昇格(つまり、プログラムを使用してrootに切り替える)なしでこれを実行できます(低ポートにバインド)。 Linuxを指定したので、この質問を見つける可能性がある他の人への通知としてこれを投稿しています。

0