これは何?
前回Lua Scriptについて書いたので今回は実際にLua ScriptとOpenRestyでリバースプロキシを作ってみます。
環境構築
OpenRestyのセットアップ
今回はDocker imageをそのまま使いました。
Lua Scriptのインストール
前回記事にあるようにhererocksをインストールしてhererocks経由でLuaとパッケージ管理ツールのLuaRocksをインストールしました。
proxy_pass
を設定してリバースプロキシ経由でアクセスしてみる
proxy_pass
経由でプロキシされる対象を指定できます。阿部寛のサイトを選んだのは80で動作しており,パケットキャプチャした結果が見やすいからです。
location / {
root /usr/local/openresty/reverse_proxy/html;
# もとのhost = OpenRestyを指定してアクセスされることを確認するためつけておく
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Connection "";
default_type 'text/html';
proxy_pass http://abehiroshi.la.coocan.jp;
}
この際にproxy_pass
には以下の仕様があります。
Passing Request Headers
前記事から抜粋。
By default, NGINX redefines two header fields in proxied requests, “Host” and “Connection”, and eliminates the header fields whose values are empty strings. “Host” is set to the $proxy_host variable, and “Connection” is set to close.
NGINXではプロキシされるリクエストに対してデフォルトでは以下を実施している。
- HTTPヘッダーの
Host
とConnection
が上書きされている。-
Host
: ($proxy_pass
に指定したFQDN)$proxy_host
に書き換わる
nginx公式ドキュメントに以下の記述がある。
$proxy_host
name and port of a proxied server as specified in the proxy_pass directive;つまり,
proxy_pass
を設定すると$proxy_host
が書き換わる -
これのなにがうれしいかというと,localhostでリバースプロキシを起動している際に,自動でHTTPのホストヘッダを書き換えてくれるということです。
Wiresharkでみるとわかりやすいのですが,ブラウザからhttp://localhost:80 にアクセスした場合に最初Hostにはlocalhostが格納されています。
しかし,前述したproxy_pass
の仕様によりHostがabehiroshi.la.coocan.jpに書き換えられるため,正しくアクセスすることができます。
nginx.confのupstream
を指定するとうまくいかない
nginx.confにはupstreamというサーバのグループを定義するためのブロックがあります。
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;
server backup1.example.com:8080 backup;
server backup2.example.com:8080 backup;
}
このブロックはnginx内で名前解決可能です。
そのため,proxy_pass
にbackendを指定するとupstreamだということを解釈してくれます。
そこで新たにproxied_server
というupstreamブロックを作り,proxy_passに設定してみました。
すると,404ページにつながるようになってしまいました。
原因
upstreamをproxy_pass
にした場合にはHostヘッダがproxied_server
になってしまい,404になっているようです。
解決方法
HostヘッダをLuaで無理やり書き換えてやれば良いようです。
うまくいった方法
解決策1: LuaでHostヘッダを書き換える。
nginx.confに新しく変数を追加し,書き換えてやります。
location / {
root /usr/local/openresty/reverse_proxy/html;
default_type 'text/html';
access_by_lua_file /usr/local/openresty/reverse_proxy/src/main.lua;
proxy_pass proxied_server;
# NOTE: upstreamをproxy_passで指定するとHttp Host Headerがupstrem名になるので,Host名の上書きが必要。
set $host_header "";
proxy_set_header Host $host_header;
}
ngx.var.host_header = "abehiroshi.la.coocan.jp"
解決策2: upstreamの名前をproxied_serverからfqdn名に変更する
upstream abehiroshi.la.coocan.jp {
server abehiroshi.la.coocan.jp:80; # テスト用
keepalive 32;
keepalive_requests 100;
keepalive_timeout 10s;
}
うまくいかなかった方法
- Luaの中から
ngx.req.set_header()
を使ってHostヘッダを書き換えてみたがだめ。- upstreamの中にbalancer_by_lua_fileを定義してluaを実行するパターン
- main.luaから実行するパターン
- upstreamの中にproxy_set_headerを定義してみたが,構文エラーになる
おそらくですが,proxied_serverというupstreamの名前の付け方にセンスがないのだと思います。
本来upstreamには使用するFQDNを入れるべきでそこにロードバランシングしたいipを書いていくのが正しいのかなと。
当たり前ですが,ロードバランシングする目的がなければupstreamは使わなくて良いなと(今回興味本位で試しましたが)。
次回
リバースプロキシとして動かすことができたので,次回はBasic認証をかけてみます。