その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

Jettyを使ったリバースプロキシ構成のときに本当のアクセス元の情報が知りたいんですけど〜って時

Jettyを使ったリバースプロキシ構成をやっている時に,プロキシではなく本当のアクセス元の情報を知りたいという事があります.例えばHttpServletRequest#getRemoteAddr()とかで取りたい,みたいな.というかほとんどの場合でそういった欲求があります.
そういった時にどうするか,みたいなのを調べたのでメモを記します.なおJettyのバージョンは9です.


プロキシの方は当然ながらX-Forwarded-*系のヘッダを正しく取り扱える様に編集しておきます.
Nginxとかだとこんな感じになるでしょう.

location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}


Jettyの設定の方は,デフォルトのjetty.xml

<!-- Uncomment to enable handling of X-Forwarded- style headers
<Call name="addCustomizer">
    <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
</Call>
-->

コメントアウトされている所のコメントアウトを外してやると良いです.でもってJettyを再起動.
このForwardedRequestCustomizerが何をする君かというと,

  • X-Forwarded-Host
  • X-Forwarded-Server
  • X-Forwarded-For
  • X-Forwarded-Proto

のヘッダを見て,それを処理して Servlet の Request ヘッダをよしなにしてくれる君です.
HttpServletRequest#getRemoteAddr() がリバースプロキシの IP アドレスではなく,リアルのリクエスト元の IP アドレスを返してくるようになったりします.
詳しくはこちらを参照して下さい.
http://download.eclipse.org/jetty/9.2.10.v20150310/apidocs/org/eclipse/jetty/server/ForwardedRequestCustomizer.html


あと,
Plack::Middleware::ReverseProxy でリモートホストを確認する理由 - blog.nomadscafe.jp
というような話題があり,こうした対応が必要となるかも知れません (とは言えJettyが使うポートが外に露出しているというケースはあまり無いと思いますが……).
そうした場合どうするかと言うと,jetty-http.xmlとjetty-https.xmlのそれぞれに

<Set name="host"><SystemProperty name="jetty.host" default="127.0.0.1" /></Set>

と書いてやると良い.こうすると,このJettyに対してはlocalhostからしかアクセス出来ないようになります.
まあ,やっとくと良いでしょうという感じはします.


なお余談ですが,Jettyのリバースプロキシ環境下でのフォワードについて調べると

<Call name="addConnector">
    <Arg>
        <New class="org.eclipse.jetty.nio.SelectChannelConnector">
            <Set name="port">8080</Set>
            <Set name="forwarded">true</Set>
        </New>
    </Arg>
</Call>

とすると良いというような情報に行き着くと思うんですが,これは古いJetty (6とか) のための情報で,
現時点で最新のJetty 9などでは利用不可能な情報です.ご注意ください.