私はかなり長い間解決策についてGoogleで調べましたが、答えが見つかりませんでした。
Ubuntu Linuxでポート80でサーバーを実行したいのですが、Ubuntuのセキュリティメカニズムにより、次のエラーが表示されます。
java.net.BindException:許可が拒否されました:80
すべてのユーザーがポート80を使用できるようにこのセキュリティメカニズムを無効にするか、現在のユーザーにポート80にアクセスするために必要な特権を割り当てるのは、十分に簡単だと思います。
私はかなり長い間解決策についてGoogleで調べましたが、答えが見つかりませんでした。
Ubuntu Linuxでポート80でサーバーを実行したいのですが、Ubuntuのセキュリティメカニズムにより、次のエラーが表示されます。
java.net.BindException:許可が拒否されました:80
すべてのユーザーがポート80を使用できるようにこのセキュリティメカニズムを無効にするか、現在のユーザーにポート80にアクセスするために必要な特権を割り当てるのは、十分に簡単だと思います。
回答:
簡単な答え:できません。1024未満のポートは、rootのみが開くことができます。コメントによると-よく、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
sudo iptables --list
。私はiptablesが何であり、何をするか知っていますが、これまで実際に使ったことはありません。
JavaのIPv4専用スタックを有効にすると、Javaでも動作します。私が使う:
authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …
AUTHBIND=yes
、/ etc / default / tomcat6に設定することで自動的にauthbindを使用できます
authbind
これを実際に許可するように設定する必要があることに注意してください。manページから:「/ etc / authbind / byport / portがテストされています。access(2)に従って、このファイルが呼び出しユーザーに実行のためにアクセス可能である場合、ポートへのバインドが許可されます。」、ポート80用などsudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80
。の初期インストールにauthbind
は、通常、事前に構成された承認はありません。
システムでサポートされている場合は、機能を使用できます。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することです。rootとして、以下を実行します
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を前で使用します。localhostでも実行できます。
apt-get install nginx
.. または ..
pkg_add -r nginx
..またはOSに適したもの。
localhostで実行している場合、nginx.confで必要なのは次のとおりです。
サーバー{ 80を聞きます。 server_name some.domain.org; 場所/ { 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に直接接続できないようになります。
アプリケーションサーバーの前でリバースプロキシ(nginx、apache + mod_proxy)またはキャッシュリバースプロキシ(Squid、Varnish)を使用してください!
リバースプロキシを使用すると、次のような多くの興味深いことが実現できます。
redirプログラムを使用できます。
sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1
Linuxでは、次の2つのオプションがあります。
Linuxカーネルの両方の拡張機能により、非常に細かいレベルでアクセス権を付与できます。これにより、このプロセスにポート80を開くことを許可できますが、他のルート権限は継承されません。
私が聞いたところでは、grsecurityの使用ははるかに簡単ですが、SELinuxはより安全です。
1つの解決策は、iptablesを使用してポート80のパケットでPATを実行することです。これを使用して、たとえばパケットをローカルポート8080にルーティングできます。必ず発信パケットをポート80に戻して調整してください。
私の経験では、セキュリティの問題のために、Linuxのきめ細かい許可機能は標準カーネルにコンパイルされません。
ユーザー実行コマンドがポート80を使用できるようにこれを実行しようとしている場合、唯一の解決策はiptablesトリックまたは実行可能setuid-to-rootの設定です。
Apacheのようなものがこれを行う方法(ポート80にバインドしますが、ルート以外のユーザーとして実行します)は、ルートとして実行し、ポートにバインドし、ポートの後にプロセスの所有権を非特権ユーザーに変更します設定されています。あなたが書いているアプリができる場合に実行するルートで、あなたは、ポートが設定された後、それは非PRIVのユーザーに所有者を変更することができます。ただし、これが平均的なユーザーがコマンドラインから実行するだけの場合は、他のソリューションのいずれかを使用する必要があります。
ルートとして実行したくないさまざまなWebサービスアプリケーション(Pythonスクリプト、Tomcatエンジンなど)がある場合、通常はそれらの前にApache Webサーバーを構成します。Apacheはポート80をリッスンし、tomcatは8080をリッスンします。
apache:s config:
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
最善の解決策はアプリをsgidすることで、ポートがバインドされるとすぐに別のユーザーに切り替えて特権を削除する必要があると思います。
一部のホストシステムは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/port80でさらに詳しく説明しています。
余談ですが、FreeBSDとSolaris(だれでも覚えていますか?)を使用すると、特権を昇格させることなく(つまり、ルートに切り替えるプログラムを使用して)これを(低ポートにバインドして)実行できます。Linuxを指定したので、この質問を見つける可能性のある他の人への通知としてこれを投稿しています。
ネクロマンシング。
シンプル。通常または古いカーネルでは、そうではありません。
他の人が指摘したように、iptablesはポートを転送できます。
他の人からも指摘されているように、CAP_NET_BIND_SERVICEも仕事をすることができます。
もちろん、スクリプトからプログラムを起動した場合、CAP_NET_BIND_SERVICEは失敗します。シェルインタープリターにキャップを設定しない限り、意味がありません。サービスをルートとして実行することもできます。
たとえば、Javaの場合、適用する必要がありますJAVA JVMへ
sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/lib/jvm/java-8-openjdk/jre/bin/java
それは明らかに、Javaプログラムがシステムポートをバインドできることを意味します。
モノ/.NET用のDito。
また、xinetdが最良のアイデアではないことも確信しています。
しかし、どちらの方法もハックなので、制限を解除して制限を解除しないのはなぜですか?
通常のカーネルを実行する必要があるとは誰も言わなかったので、自分で実行することができます。
最新のカーネル(または現在使用しているカーネル)のソースをダウンロードするだけです。その後、次の場所に移動します。
/usr/src/linux-<version_number>/include/net/sock.h:
そこでこの行を探します
/* Sockets 0-1023 can't be bound to unless you are superuser */
#define PROT_SOCK 1024
に変更します
#define PROT_SOCK 0
安全でないssh状況にしたくない場合は、これに変更します:#define PROT_SOCK 24
一般的に、必要な最低設定を使用します。たとえば、httpの場合は79、ポート25でSMTPを使用する場合は24です。
すでにすべてです。
カーネルをコンパイルし、インストールします。
リブート。
完了-その愚かな制限はGONEであり、スクリプトでも機能します。
カーネルのコンパイル方法は次のとおりです。
https://help.ubuntu.com/community/Kernel/Compile
# You can get the kernel-source via package linux-source, no manual download required
apt-get install linux-source fakeroot
mkdir ~/src
cd ~/src
tar xjvf /usr/src/linux-source-<version>.tar.bz2
cd linux-source-<version>
# Apply the changes to PROT_SOCK define in /include/net/sock.h
# Copy the kernel config file you are currently using
cp -vi /boot/config-`uname -r` .config
# Install ncurses libary, if you want to run menuconfig
apt-get install libncurses5 libncurses5-dev
# Run menuconfig (optional)
make menuconfig
# Define the number of threads you wanna use when compiling (should be <number CPU cores> - 1), e.g. for quad-core
export CONCURRENCY_LEVEL=3
# Now compile the custom kernel
fakeroot make-kpkg --initrd --append-to-version=custom kernel-image kernel-headers
# And wait a long long time
cd ..
簡単に言えば、セキュリティを維持したい場合はiptablesを使用し、この制限が二度とわからないことを確認したい場合はカーネルをコンパイルします。
sudo setcap cap_net_bind_service=+ep /path-to-java/java
)がjava: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
、javaに上限が設定されている場合は常に取得します。unix.stackexchange.com/a/16670/55508
<javahome>/lib/amd64/jli/
しld.so.conf
て実行することで以前のエラーを解決しましたsudo ldconfig