JettyはTomcatと比べて、ファイルサイズも小さく、起動が早いので最近、僕のお気にいりのWebサーバ兼サーブレットコンテナなんですが、困った点が1つあります。
デフォルトPortは8080なんですが、Portを80に変更して運用するには管理者権限(root)が必要になってしまうようです。一般Shellユーザー(例えばjettyとかユーザーを作成した場合)でPort:80で試してみましたところ、起動はできるんですが途中でExceptionを吐いてコケテしまいます。
本来はApacheのように実行権限のないnologinのWebサーバ用ユーザー(daemon、 nobody...)で起動するのが理想です。というかセキュリティ面を考えると当たり前だと思うんですよね。管理者権限(root)、一般ShellユーザーでJettyを起動してサービスを運用したくない。万が一JettyにBugがあった場合、バッファーオーバーフローをつかれて、権限を奪取されサーバ内に侵入されてしまうわけですから。そこで JettyをPort:80でnologinユーザー(実行権限の無い)で起動する方法をまとめてみました。下記のJettyのFAQページを参考にしました。
http://docs.codehaus.org/display/JETTY/port80
(※)Jetty7や他のバージョンでは試していないので同じ方法かどうかはご注意
今回使用したミドルウェア情報・補助情報
[ミドルウェア]
OS :2.6.31-17-generic(Ubuntu、CentOS)
Jetty :6.1.22(STABLE)
Java :1.6.0_15(OpenJDK)
[補助用語]
$JETTY_HOME :Jettyのソースを設置したディレクトリ
$JAVA_HOME :Java SDKをインストールしたディレクトリ
(コンパイルが発生するのJava Runtimeだけでは駄目かも)
導入方法は次の2パターンが有ります
(1):一般ShellューザでPort:8080で起動してOSの機能である、
ipchains、iptablesを使って、Port:80へのリクエストを8080へフォワードする
(2):JNIを使って、Nativeライブラリを起動時に読み込みnologinユーザーにsetuid (and setumask)を行う
(1):iptables、ipchainsを使用して実現する方法
iptables
/sbin/iptables -t nat -I PREROUTING -p tcp --dport 80 \ -j REDIRECT --to-port 8080
ipchains
/sbin/ipchains -I input --proto TCP --dport 80 \ -j REDIRECT 8080
(2):nologinユーザーにsetuidを使用して実現する方法
setuidのNativeライブラリをJettyにあてるために解凍したJettyのソースに移動する
-
(a):Mavenを使ってNativeライブラリ(org_mortbay_setuid_SetUID.c)をインストールする場合
$JETTY_HOME/extras/setuid配下にMavenの設定ファイル (pom.xml)があるので、mvn installを実行する
(b):手動でNativeライブラリ(org_mortbay_setuid_SetUID.c)をインストールする場合
-
libsetuid.soファイルができているか確認する
-
Jettyを実行させたいnologinユーザのユーザーIDとグループIDを設定ファイルに指定する
-
jetty.xmlのPort指定箇所を8080から80に変更する
-
jetty-setuid.xmlを指定して、Jettyを起動させる
cd $JETTY_HOME/extras/setuid
mkdir -p modules/native/target/generated cp modules/native/src/main/native/ \ org_mortbay_setuid_SetUID.c modules/native/target/generated javah -d modules/native/target/generated \ -classpath modules/java/target/ \ jetty-setuid-java-6.1.22.jar org.mortbay.setuid.SetUID gcc -I$JAVA_HOME/include/ \ -I$JAVA_HOME/include/linux/ \ -shared \ modules/native/target/generated/ \ org_mortbay_setuid_SetUID.c -o ../../lib/ext/libsetuid.so
ls $JETTY_HOME/lib/ext/libsetuid.so
ただし、何故かJetty6.1.22のバージョンでは解凍した段階でlibsetuid.soも同梱されていた・・・どの環境によるコンパイルか不明のため、自分でコンパイルは行った方がよいと思います
vi $JETTY_HOME/etc/jetty-setuid.xml
nobodyユーザーのuid、gidに修正する。uid、gidはお使いの環境によってことなるので/etc/passwdなどで確認して適時値を変更してください
<Configure id="Server" class="org.mortbay.setuid.SetUIDServer"> <Set name="startServerAsPrivileged">false</Set> <Set name="umask">2</Set> <Set name="uid">jetty</Set> (変更)=> <Set name="uid">6553</Set> <Set name="gid">jetty</Set> (変更)=> <Set name="gid">6553</Set> <!--↑↑uid、gidの値をjettyから6553に変更する↑↑-->
この時の注意点として、読み込ませる設定ファイルの中で、jetty-setuid.xmlを一番最初に指定すること。指定順番が大事です
<Call name="addConnector">
<Arg>
<New class="org.mortbay.jetty.nio.SelectChannelConnector">
<Set name="host"><SystemProperty name="jetty.host" /></Set>
<Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>
<!--↑↑defaultの値を8080から80に変更する↑↑-->
<Set name="maxIdleTime">30000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">5000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
</Arg>
</Call>
$JAVA_HOME/bin/java -jar $JETTY_HOME/start.jar \
$JETTY_HOME/etc/jetty-setuid.xml \
$JETTY_HOME/etc/jetty.xml
設定、コンパイルが上手くいかない場合
java.net.SocketException: Permission denied at sun.nio.ch.Net.bind(Native Method) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:119) at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
Permission deniedで一般ユーザーでは権限がないというメッセージがでて起動途中でとまってしまいます。この場合は設定ファイル、コンパイル内容などを疑ってください
結論
(1)のほうが、Jettyのソースを変更することなく、Port:80で起動を可能にしますし、お手軽だと思います。ですがPortフォワードというOSの機能を使って実現するあたりが、スマートではないように思います。リクエストのたびにOSに多少なりともフォワード負荷が余計にかかる事が、本来ならアプリケーション処理に割り当てられるはずの、サーバのリソースを無駄に消費している感がなんとも損した気持ちになってしまいます。実際Portフォワードでサーバが消費するリソースは微々たるものだと思いますが・・・。
なにより一般Shellユーザーで結局はPort:8080で起動しないといけないので、セキュリティ的な不安は残ってしまいます。
やはり個人的には(2)がベストだと思います、GCCによるコンパイルなど、ちょっと面倒ではありますが、 Mavenがインストールされている環境であれば、ワンステップで処理が完了するので、そこまで苦にはならないだろうし、nologinのWebサーバ用ユーザーで実行するので、通常のApacheとかの起動内容と同じになりますので、実行ユーザーに関する点のセキュリティ的リスクは限りなく低くなると思います。
Trackback URL
http://blog.fukaoi.org/2010/03/11/jetty-port-80?tb=y&entry_id=23
XML
