2017年7月13日木曜日

ApacheをNginxの裏に

前回Nginxをリバースプロキシとし、
Node.jsをその裏に持っていきましたが、
今回はApacheをNginxの裏へ移動させます。
ただし、とりあえずテストということで、
現在動作中のApacheはこれまでどおり80番(http)と
443番(https)ポートに置いた上で、
Nginxを8000(http)と8001(https)で仮動作させ、
8000/8001へのリクエストを80に転送する形で構成します。

最初に行うべきはApache側の修正です。
Apacheのバーチャルホストで立ち上げているサイトを
別々のTCPポートで公開するように変更し、
Nginxで接続先バーチャルホストを判別して
各TCPポートに振り分けるような構成にすれば
よさそうなことは前から分かっていましたが、
バーチャルホストの数がたくさんあると面倒で、
これが二の足を踏む原因でありました。

今回Apache側の変更をもっと少なくする方法がないかと
本気で探していたところ、
Nginxにproxy_bind設定があることを発見しました。
NginxのApacheへのリクエストの送信先をIPアドレスで指定でき、
かつ接続先サイトのホスト名も指定もできれば、
Apacheは無変更で対応できるような気がします。
で、Nginxの設定ファイルの
location / {
    proxy_pass http://127.0.0.1;
}
の部分を
location / {
    proxy_bind 127.0.0.1;
    proxy_pass http://<ホスト名>;
}
のようにしてみると…予想どおりの動作をします。
やった!! と思ったのも束の間、
ブラウザの更新ボタンを押すとエラー500が…orz
どうも成功と失敗が半々ぐらいになるようです。
これでは使い物になりません。
しょうがないのでエラーログ"/var/log/nginx/error.log"を見ると
****/**/** **:**:** [crit] 1161#0: *7 bind(127.0.0.1) failed (22: Invalid argument) while connecting to upstream, client: ***.***.***.***, server: <ホスト名>, request: "GET / HTTP/1.1", upstream: "http://[****:***:***:*:*:*:*:***]:80/", host: "<ホスト名>:8000"
とか出てます。
これを眺めながら考えた結果、この中のhostが悪いような気がしてきて、
この"host"という言葉から別の方法を思いつきました。

その別の方法とはHostヘッダに直接目的のホスト名を指定することです。
ウェブサーバーはこれでどのバーチャルホストを返すべきか判断します。
裏のApacheにそれをさせればいいのです。
この目論見は見事的中。
結果設定ファイルは以下のようにします。
"/etc/nginx/sites-available/"ディレクトリに
複数の"<ホスト名>"設定ファイルを作成し、
内容を以下のようにします。
server {
    listen 8000;
    listen [::]:8000;

    server_name <ホスト名>;
    proxy_set_header Host <ホスト名>;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        proxy_pass http://127.0.0.1;
    }
}

server {
    listen 8001;
    listen [::]:8001;
    server_name <ホスト名>;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/<ホスト名>/cert.pem;
    ssl_certificate_key /etc/letsencrypt/live/<ホスト名>/privkey.pem;
    proxy_set_header Host <ホスト名>;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        proxy_pass http://127.0.0.1;
    }
}
ここでサーバ証明書関連のファイル名やパスは
実環境に合わせて読み替えてください。
これで
# cd /etc/nginx/sites-enabled
# ln -s ../sites-available/<ホスト名> <ホスト名>
# /etc/init.d/nginx stop
# /etc/init.d/nginx start
を実行すれば望んだ構成になります。

本格的にNginxをリバースプロキシとして運用する覚悟ができたら、
Apache側で"/etc/apache2/sites-enabled/"ディレクトリ下にある
SSLなサイトの個別設定ファイルを削除し、
"/etc/apache2/mods-enabled/"ディレクトリ下にある
設定ファイル"ssl.conf"と"ssl.load"を削除し、
"/etc/apache2/ports.conf"設定ファイルの
Listen 80
のポート番号を未使用なものに変更して再起動し、
Nginxの設定ファイルで公開ポート(listen設定)を
80(http)/443(https)に変更し、
参照先URL(proxy_pass設定)のポート番号を
Apacheの設定に合わせて変更して再起動すればいいでしょう。
多分。
なお、先の"/etc/apache2/ports.conf"設定ファイルについて、
Listen 127.0.0.1:<ポート番号>
としておくとApacheが外部からのリクエストに答えなくなり、
ローカルのNginx経由でしかアクセスできなくなります。
セキュリティのためにもしておいた方がいい設定でしょう。
まあ直接アクセスできる余地を残しておくと、
何かの時に便利かもしれませんが。

0 件のコメント:

コメントを投稿