2018年9月26日水曜日

FreeBSD で nginx に挑戦してみた(その4:https 化と Digest 認証)

 前回,FreeBSD で nginx に挑戦してみた(その3)として,FreeBSD 上の nginx 設定の location コンテキストと,nginx で CGI を使うための方法について書いた。 今回は,https 化 (ssl モジュール)と Digest 認証について書いていこう。

http_ssl モジュールと https


https 化を行うには,まず nginx のインストール時に http_ssl モジュールを組み込まないといけない。そのためには
--with-http_ssl_module
オプションをつけてインストールしないといけない。 FreeBSD で /usr/ports/www/nginx/ からインストールする際には「HTTP_SSL」オプションをつけておかないといけない。

 そして,以下のように設定ファイル( /usr/local/etc/nginx/nginx.conf )に記載する必要がある。 下記の設定の青色の辺りがその設定部分である。 設定ファイル自体は前回示した CGI を使う場合の設定ファイルに https 化の部分( server ディレクティブ)を追加している。 そのため,通常の 80 番ポートへのリクエストを受信する server ディレクティブも残してある。
(nginx 設定ファイル:https の例)
user www www;
worker_processes  2;
error_log  /var/log/nginx/error.log error;
pid        /var/run/nginx.pid;
# ==================================================================
events {
    worker_connections  500;
    use                 kqueue;
}
# ==================================================================
http {
    server_tokens      off;
    include            mime.types;
    default_type       application/octet-stream;
    charset            UTF-8;
    sendfile           on;
    tcp_nopush         on;
    keepalive_timeout  75;
    gzip               on;

    root   /usr/local/www/data;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log         /var/log/nginx/access.log  main;
    error_page  401              /401.html;
    error_page  403 404          /404.html;
    error_page  500 502 503 504  /50x.html;
    # ---------------------------------------------------------
    server {
        listen       80 default_server;
        server_name  www.xxxxx.com yyy.xxxxx.com zzz.xxxxx.com;
        location / {
             index  index.html /index.html;
        }
        location ~ \.cgi$ {
            include        fastcgi_params;
            fastcgi_pass   unix:/var/run/fcgiwrap/fcgiwrap.socket;
            fastcgi_index  index.cgi;
            fastcgi_param  SCRIPT_FILENAME  /usr/local/www/data$fastcgi_script_name;
        }
    }
    # ---------------------------------------------------------
    server {
        listen               443 ssl http2 default_server;
        server_name          www.xxxxx.com yyy.xxxxx.com zzz.xxxxx.com;
        ssl_certificate      /usr/local/etc/letsencrypt/live/www.xxxxx.com/fullchain.pem;
        ssl_certificate_key  /usr/local/etc/letsencrypt/live/www.xxxxx.com/privkey.pem;

        access_log /var/log/nginx/https_xxxxxx_access.log main;
        error_log  /var/log/nginx/https_xxxxxx_error.log error;

        location ~ /\.ht {
            deny all;
        }

        location ~ \.cgi$ {
            include        fastcgi_params;
            fastcgi_pass   unix:/var/run/fcgiwrap/fcgiwrap.socket;
            fastcgi_index  index.cgi;
            fastcgi_param  SCRIPT_FILENAME  /usr/local/www/data$fastcgi_script_name;
        }
        location / {
            index  index.html index.cgi /index.html;
        }
    }
}

・まず,listen ディレクティブに「443 ssl http2 default_server;」と記載している。 これは通常の https 受信ポートである「443番ポート」を受信し,SSL モードを用いた通信を行い,HTTP/2 接続を行うことを意味する。さらに「default_server」にも指定している。 最低限「443 ssl」があれば https での受信は問題なく行われる。http2 と default_server は付加的につけている。

server_name ディレクティブは,80番ポートの場合と同じなので,ここでは説明しない (FreeBSD で nginx に挑戦してみた(その2:nginx の設定と初起動)を見てほしい)。

その次の2個のディレクティブが重要である。
ssl_certificate ディレクティブと ssl_certificate_key ディレクティブが SSL モードに必須のサーバーの証明書であり,今回は Let's Encrypt による PEM 形式の認証ファイルを指定している。 Let's Encrypt についてはMyDNS と Let's Encrypt を使って,FreeBSD 上の apache24 を https 化してみた(その3)を見てみて欲しい。
 ここでは,「/usr/local/etc/letsencrypt/live/www.xxxxx.com/」(www.xxxxx.com は server_name ディレクティブで指定したいずれかのサーバー名)にある「fullchain.pem」と「privkey.pem」を指定している。

・他にも,80番ポートとは別にアクセスログとエラーログを記載するために,それぞれファイル名を指定している。

・その他に「location ~ /\.ht」と書かれた location ディレクティブがあるが,これは「.htaccess」を無効にするためのおまじないである。


Digest 認証


 nginx の公式サイトには,Basic 認証のモジュールの説明はあるが,Digest 認証の説明はない。 nginx では Digest 認証はサードパーティー製モジュールとして存在してる。 そのため nginx-http-auth-digest をインストールしないといけない。 FreeBSD の /usr/ports/www/nginx/ からインストールする場合には「HTTP_AUTH_DIGEST」オプションをつけてインストールすれば組み込まれる。

 下記に設定ファイル(/usr/local/etc/nginx/nginx.conf )の例を書いておこう。 今回も青色の部分が上に書いた設定ファイルからの変更点である。
(nginx 設定ファイル:Digest 認証の例)
user www www;
worker_processes  2;
load_module /usr/local/libexec/nginx/ngx_http_auth_digest_module.so;
error_log  /var/log/nginx/error.log error;
pid        /var/run/nginx.pid;
# ==================================================================
events {
    worker_connections  500;
    use                 kqueue;
}
# ==================================================================
http {
    server_tokens      off;
    include            mime.types;
    default_type       application/octet-stream;
    charset            UTF-8;
    sendfile           on;
    tcp_nopush         on;
    keepalive_timeout  75;
    gzip               on;

    root   /usr/local/www/data;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log         /var/log/nginx/access.log  main;
    error_page  401              /401.html;
    error_page  403 404          /404.html;
    error_page  500 502 503 504  /50x.html;
    # ---------------------------------------------------------
    server {
        listen       80 default_server;
        server_name  www.xxxxx.com yyy.xxxxx.com zzz.xxxxx.com;
        location / {
             index  index.html /index.html;
        }
        location ~ \.cgi$ {
            include        fastcgi_params;
            fastcgi_pass   unix:/var/run/fcgiwrap/fcgiwrap.socket;
            fastcgi_index  index.cgi;
            fastcgi_param  SCRIPT_FILENAME  /usr/local/www/data$fastcgi_script_name;
        }
    }
    # ---------------------------------------------------------
    server {
        listen               443 ssl http2 default_server;
        server_name          www.xxxxx.com yyy.xxxxx.com zzz.xxxxx.com;
        ssl_certificate      /usr/local/etc/letsencrypt/live/www.xxxxx.com/fullchain.pem;
        ssl_certificate_key  /usr/local/etc/letsencrypt/live/www.xxxxx.com/privkey.pem;

        auth_digest_shm_size  10m; # default 4m, auth_digest 用のメモリ
        auth_digest_expires 10s; # default 10 s,一度認証に成功したものの再利用時間
        auth_digest_replays 1024;  # default 20 times,一度認証に成功したものの再利用回数上限
        auth_digest_evasion_time 60s; # default 300s,auth_digest_maxtries で指定した回数だけ失敗した時の不能時間
        auth_digest_maxtries 50; # default 5 times,evasion になるまでの失敗数

        client_max_body_size 200m;

        access_log /var/log/nginx/https_xxxxxx_access.log main;
        error_log  /var/log/nginx/https_xxxxxx_error.log error;

        location ~ /\.ht {
            deny all;
        }

        location ~ ^/punipuni/cgi-bin {
            index          index.html index.cgi /index.html;
            auth_digest    'Secret Zone';
            auth_digest_user_file /usr/local/.htdigest;
            include        fastcgi_params;
            fastcgi_pass   unix:/var/run/fcgiwrap/fcgiwrap.socket;
            fastcgi_index  index.cgi;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        }
        location ~ \.cgi$ {
            include        fastcgi_params;
            fastcgi_pass   unix:/var/run/fcgiwrap/fcgiwrap.socket;
            fastcgi_index  index.cgi;
            fastcgi_param  SCRIPT_FILENAME  /usr/local/www/data$fastcgi_script_name;
        }
        location ~ ^/punipuni {
            auth_digest 'Secret Zone';
            auth_digest_user_file /usr/local/.htdigest;
        }
        location / {
            index  index.html index.cgi /index.html;
        }
    }
}

 ここでも上から順に新しい項目について説明していこう。

load_module ディレクティブでは「ngx_http_auth_digest_module.so」を読み込ませている。これは「ngx_http_auth_digest_module」が「動的モジュール」のため,インストールはされたが(モジュールは作られたが)設定ファイルで読み込まないと起動時に読み込まれないから,である。

・「443 ssl」と書かれた server ディレクティブの中にある auth_digest_shm_size, auth_digest_expires, auth_digest_replays, auth_digest_evasion_time, auth_digest_maxtries や,下の方にある location ディレクティブの中にある auth_digest, auth_digest_user_file は,いずれも nginx-http-auth-digest の下の方に説明があるので,詳しくはそちらを見て欲しい。

これらは auth_digest_shm_size 以外は,すべて server のコンテキストと location のコンテキストに記載ができる。 auth_digest_shm_size だけは server のコンテキストしか記載が許されていない。

「443 ssl」と書かれた server ディレクティブの中にある auth_digest_shm_size, auth_digest_expires, auth_digest_replays, auth_digest_evasion_time, auth_digest_maxtries はそれぞれコメントに書いておいたが,
auth_digest_shm_size は,auth_digest 用のメモリであり,デフォルト値は 4m (4MB) である。
auth_digest_expires は,一度認証に成功したものの再利用時間であり,デフォルト値は 10 秒である。
auth_digest_replays は,一度成功したものの再利用回数上限であり,デフォルト値は 20 回である。

順序が逆になるが,
auth_digest_maxtries は,evasion モード(回避モード)になるまでに許される失敗の回数であり,デフォルト値は5回である。
auth_digest_evasion_time は,evasion モード(回避モード)になった時の接続不能時間であり,デフォルト値は 300 秒である。
evasion(回避)モードに入ると,auth_digest_evasion_time で指定される時間は Digest 認証に挑戦させてくれず,サーバーが止まったように見えてしまう。 これが頻繁に起こると,接続に異常に長い時間がかかる,という状態に陥る。
 それを避けるには,auth_digest_replays の値を大きな値にすればいいみたい。 なので,ここでは 1024 に設定してある。

下の方にある location ディレクティブの中にある auth_digestauth_digest_user_file はそれぞれ下記のような意味がある。
auth_digest は Digest 認証の ON/OFF を示し,ON にしたければ「realm(分野)値」を記載し,OFF にしたければ「off」と書けばよい。
auth_digest_user_file は,Digest 認証のユーザー名とパスワードが入ったファイル名であり,そのファイルは web で通常アクセスされないディレクトリに置くのがよい。

 最後に,client_max_body_size ディレクティブは,クライアントからのリクエスト時のパケットのサイズの上限を決めている。デフォルト値は 1m (1 MB) である。通常は 1 MB で問題ないと思うが,ファイルのアップロードをさせたい時にはそれなりに大きな値が欲しい。ここでは 100m (100 MB) に設定している。

 今回は https 化の設定と,Digest 認証について書いてみた。一度お試しあれ。

0 件のコメント: