Nginx を導入する

Nginx は近年、高速動作する Web 関連サーバーとして人気が出てきている。では実際、慣れ親しんできた Apache と比較して、どんな所が違うのだろうか?

例えばディレクティブに関して言えば、Nginx は貧弱で、複雑な設定には向いていないが、Web キャシュサーバーやロードバランサーとして Apache との併用で力を発揮する場合もある。

そこで今回は、Apache と比較しながら説明していきたいと思う。

※ ここで利用しているのは、Fedora20 の Nginx 1.4.7 です。

インストール

端末からコマンドでインストールを行います。GUIで行う場合はコチラをご覧ください。

※ Fedora22 からは DNF を用いてインストールを行います。詳しくはコチラをご覧下さい。

$ su
# yum install nginx
# yum install php-fpm

Nginx の設定

Nginx 設定の基本概念

Nginx 設定の基本概念

Nginx の設定方法はコチラが参考になるかと思います。

もし Apache に慣れているなら注意が必要だ。Nginx ではディレクティブの数が少なく、しかも制限が多い。また、if ディレクティブ一応存在するのだが、AND や OR 、ELSE さえも存在しない。さらに location ディレクティブが排他的であるため、重複記述も多くなる。

ここで少し、Nginx と Apache に於ける location ディレクティブ設定の違いを見てみよう。

Apache の location ディレクティブ

Apache の location ディレクティブは基本的には継承型であるため、部分的にアクセス制限を行いたい場合などでは、制限部分だけの記述だけのファイルを作成する事で完了する。この機能を利用して、Webalizer(アクセスログ解析ツール)などでは、パッケージをインストールするだけでアクセス制限が掛かるようになっている。また、PHP などのツールでも、インストールするだけで利用できるのもの少なくない。

しかし Nginx では、全ての設定を自分で行う必要がある。

今度は Nginx の location ディレクティブを見てみよう。

Nginx の location ディレクティブ

Nginx の location ディレクティブは排他的である。例えば、上記のような設定で「/admin/index.php」にアクセスしようとした場合、「設定 B」のみが有効になり、「設定 A」、「設定 C」は有効にならない。つまり、「設定 B」に PHP の設定が存在しない場合は、index.php の PHP ソースが表示される事になる。また、「/hoge/hoge/index.html」にアクセスしようとした場合には、「設定 E」のみが有効になり、「設定 D」は有効にならない。

※ location の優先順位については、ココを参考にして下さい。

※ location の入れ子では、index ディレクティブや root ディレクティブなどは継承されますが、これらは本来、http ディレクティブや server ディレクティブ直下に記述すべきものです。ココを参考にして下さい。

location の優先順位や if ディレクティブの制限などが原因でマトモな設定を行える様になるまでは、ある程度の慣れが必要であり、また、設定の分割化も難しくしなっている。事実、ネット上に存在するアクセス制限などの設定では、おかしな設定なども少なくない。コピー&ペーストで設定を行っている人などは十分に注意が必要だ。
以上のことに気を付けて「/etc/nginx/nginx.conf」を編集しよう。

※ 「/etc/nginx/nginx.d」がありますが、これはデフォルトでは「/etc/nginx/nginx.conf」の「http」ディレクティブ内で読み込まれています。つまり、「server」ディレクティブを「/etc/nginx/nginx.d」に「.conf」の拡張子で保存しておく事を意図している様です。

Mime タイプの追加

「/etc/nginx/mime.types」に Mime タイプを定義したファイルが存在します。

不足のタイプがある場合は追加しておきます。

例えば Linux / UNIX で一般的な gunzip 関連の MimeType は次の様になります。

application/x-tar tar;
application/gzip gz;
application/x-gzip tar.gz tgz;

index ディレクティブの追加

「index」ディレクティブにはデフォルトのファイルを指定します。

例えば「index  index.html index.php;」を指定して「/」にアクセスした場合、「/index.html」もしくは「/index.php」がアクセス対称になります。ただし、「/index.php」のみが存在する場合で PHP の設定が行われていない場合は、「/index.php」のソースが表示される事になります。あくまでもデフォルトのファイルを指定しているだけなので注意しましょう。

※ 全体のデフォルトファイルを指定する場合は、「http」ディレクティブに、サーバーのデフォルトを指定する場合は「server」ディレクティブに記述しましょう。

server_name ディレクティブの追加

「server_name」ディレクティブにはサーバー名を指定しておきます。このサーバー名はアクセスする名前を指定しておく必要があります。例えば、「http://localhost/」と「http://127.0.0.1/」でアクセスする場合は、「server_name  localhost 127.0.0.1;」と指定します。また、ワイルド・カードも利用出来ますので、「192.168.0.*」や「*.magic-object.mydns.jp」といった指定も可能です。

※ 「server_name」ディレクティブは必ず「server」ディレクティブで指定します。

※ アクセスする名前を、「server」ディレクティブとセットにする事により、簡単にバーチャルホストを構築する事が出来ます。

root ディレクティブの追加

「root」ディレクティブにはファイルシステムのパスを指定します。つまり、ドキュメントルートです。通常は「server」ディレクティブで指定するのが良いでしょう。

ここで少し、「server_name」ディレクティブとの組み合わせでバーチャルホストを実現してみましょう。

Nginx のバーチャルホスト設定

上の様な設定になっている場合、「http://localhost/」でアクセスした場合は「/usr/share/nginx/html1/」、「http://127.0.0.1/」でアクセスした場合は「/usr/share/nginx/html2/」のファイルが参照されます。

PHP の設定

「/etc/php-fpm.d/www.conf」を編集
変更前 変更後
listen = 127.0.0.1:9000 listen = /run/php-fpm/php-fpm.sock
;listen.owner = nobody
;listen.group = nobody
;listen.mode = 0660
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
user = apache user = nginx
group = apache group = nginx

Nginx に PHP の為の location 設定を追加する。勿論この設定は通常は複数箇所に記述する必要がある。

location ~ \.php$ {
    fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $docuent_root$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
}

ここで注意して欲しいのは、UNIXドメインソケット利用している事である。このソケットは TCP/IP のオーバーヘッドを防ぐなど多くの利点がある。また、Nginx の PHP 設定は、location が排他的に動作する都合上、他の location 内で動作させる場合には、同様の設定を記述する必要がある。

ロードバランサーの設定

Nginx はロードバランサーの設定が容易に行える。詳しくはココを参照して下さい。

upstream virtual_loadbalabce_server {
    # 転送されたアクセスを以下のサーバーに分配する。
    server www.server1.co.jp;
    server www.server2.co.jp;
    server www.server3.co.jp;
}server {
    location / {
        # 外部からのアクセスを架空のサーバーへ転送する。
        proxy_pass http://virtual_loadbalabce_server;
    }
}

元々 Nginx は、C10K問題(クライアント1万台の同時接続要求に関する問題)に対応するために誕生した Web サーバーなので、こういった処理にはめっぽう強い。

勿論、数万/秒のアクセスに対応するなら、チューニングが必要なのだが、フロントエンドとしての意義は大きい。

※ Nginx は1日に5億リクエストを処理する HTTP サーバーと言われている。

Nginx とセキュリティー

phpMyAdmin や WordPress などを有効にする情報はネット上に多数存在する。しかし、Apache 用のアクセス制限などは正しいモノが多いが、Nginx 用は勘違いしているモノや不十分なモノも少なくない。公開 Web サーバーを運用した経験があるなら知っているかとは思うが、phpMyAdmin や WordPress は確実にクラッカーの攻撃対象になると考えて良い。コピー&ペーストでしか設定できないなら、Nginx の使用は止めて、Apache を使うべきだろう。どうしても Nginx を使用したいなら、キッチリと考えながら行なう方が良いだろう。

DDoS攻撃は別として、Web アプリケーションに対する攻撃で最も多いのがツールを使用したモノです。つまり、解析などの工程が存在せず、脆弱性を利用した攻撃だと言えます。

これに対して有効な方法の1つがアクセス制限です。

server {
    # 外部からアクセスされるアドレス
    server_name www.hoge.co.jp;    # アクセスを拒否
    location /admin/ {
        return 403;
    }
}server {
    # 内部からアクセスされるアドレス
    server_name localhost 127.0.0.1 192.168.1.*;    # 内部プロキシ経由では失敗する場合もある。偽装対策。
    # 無くてもツール攻撃には効果がある。
     if ( $remote_addr !~ ‘^((192\.168\.[0-9]+\.[0-9]+)|(localhost)|(127\.0\.0\.1)|(::1))$’ ) {
return 403;
}
}

例えば「http://www.hoge.co.jp/admin/」に対して外部からのアクセスを拒否したい場合、上記のような方法で制限を掛けることが行えます。この時、内部からアクセスされる場合は、「http://localhost/adomin/」とする必要があります。勿論、内部のプロキシ経由でアクセスした場合などでは、外部からでもアクセスされる可能性もありますが、アドレスによって分ける方法は、記述を簡単に出来ますのでオススメです。

Nginx の設定は、記述が複雑になりがちですので、簡単に記述する方法を考えるのも重要な要素の1つです。

アクセス制限を設定した場合は、必ずテストを行いましょう。

文法チェックと起動

# # デフォルトの設定ファイルに対する文法チェック
# nginx -t
#
# # 設定ファイルを指定してチェック
# nginx -t -c /etc/nginx/nginx.conf
#
# # デフォルトで起動するように設定
# systemctl enable nginx.service
#
# # 起動
# systemctl start nginx.service
#
# # 確認
# systemctl status nginx.service

Nginx と Apache

ginx は高速作動を目的としており、メモリ消費量などのメリットもある。全体的な目的などを見ても、基本的な考えは「速さこそ正義」なのだろう。

ただし高速性を意識しすぎたセイか、扱いが難しいスポーツカーの様だ。

それに対し Apache は大衆車の様だ。色々拡張すれば重くなる事もあるし、チューニングパーツを利用すれば、速度もそれなりに出る。ただし、元が大衆車だけに高速化しても、本気を出したスポーツカーには及ばない。だが、長年の実績による豊富なマニュアルと多彩な拡張パーツが存在する。

多くの場合、Web サーバー選びで重要なのは、運用上の利便性であると言える。例えば、高速性が必要だが Apache の方に十分な運用実績があるなら、フロントエンドに Nginx、バックエンドに Apache と言う選択もアリだろう。Nginx に得意なプロキシ(キャシュ)やロードバランサーを任せ、その他の部分は Apache に任せると言う選択だ。あるいは Apache のチューニングで対応する方法もある。トラブル時の対応も重要な要素なので、それを踏まえながら導入するのが良いだろう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です