LoginSignup
4

More than 3 years have passed since last update.

posted at

updated at

Nginx でDigest認証を使う

Basic認証はID/PASSをBase64エンコードしているため簡単にデコード可能でありセキュリティ面でよろしくない。
Digest認証はMD5でエンコードされるため盗聴/改ざんのリスクはBasic認証より低い。
しかしnginxは標準でDigest認証に対応していない。ソースから外部モジュールを追加してコンパイルすることで対応させることができる。

環境

Windows10ProのHyper-V上に下記仮想マシンを作成して検証

  • CentOS 8.0.1905
  • Nginx 1.17.7

なお FirewalldとSELinuxはいずれも有効にしている

流れ

コマンドはすべてrootユーザで実行する

1. 必要なパッケージをインストール

# dnf install gcc pcre pcre-devel make perl httpd-tools

gcc pcre pcre-devel make perl は コンパイル&インストールで必要
httpd-tools はDigest認証で使うパスワードファイルを生成する htdigest を使うために導入

2. ソースのダウンロード

# wget "http://nginx.org/download/nginx-1.17.7.tar.gz" -O /tmp/nginx-1.17.7.tar.gz
# wget "https://github.com/atomx/nginx-http-auth-digest/archive/master.zip" -O /tmp/nginx-http-auth-digest.zip
# wget "http://zlib.net/zlib-1.2.11.tar.gz" -O /tmp/zlib-1.2.11.tar.gz
# wget "https://www.openssl.org/source/openssl-1.1.1d.tar.gz" -O /tmp/openssl-1.1.1d.tar.gz

上から

とりあえず /usr/local/src/ に展開する

# tar zxvf /tmp/nginx-1.17.7.tar.gz -C /usr/local/src/
# unzip /tmp/nginx-http-auth-digest.zip -d /usr/local/src/
# tar zxvf /tmp/zlib-1.2.11.tar.gz -C /usr/local/src/
# tar zxvf /tmp/openssl-1.1.1d.tar.gz -C /usr/local/src/

3. コンパイル&インストール

# cd /usr/local/src/nginx-1.17.7
# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-openssl=/usr/local/src/openssl-1.1.1d --with-zlib=/usr/local/src/zlib-1.2.11 --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_v2_module --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' --add-module=../nginx-http-auth-digest-master/
# make && make install

4. 足りないモノをいろいろ作成

自動で作成されないモノを作っていく

4-1. ユーザ作成

nginx実行用のユーザを作成

# groupadd nginx
# useradd -g nginx nginx
# usermod -s /bin/false nginx

4-2. キャッシュディレクトリ作成

# mkdir -p /var/cache/nginx/client_temp

4-3. 起動スクリプト作成

systemd のスクリプトも自分で作成する。

# cat <<EOF > /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

4-4. ログローテート設定

logrotate.dの設定ファイルを作成する

# cat <<EOF > /etc/logrotate.d/nginx
/var/log/nginx/*log {
    create 0664 nginx root
    daily
    rotate 10
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}
EOF

4-5.firewalld

外部からアクセスできないためfirewalldに許可設定を行う
HTTP, HTTPSの両方を開けておく

# firewall-cmd --add-service=http --zone=public
# firewall-cmd --add-service=https --zone=public

4-6. パスワードファイル作成

# htdigest -c /etc/nginx/.htdigest_test "test" user
Adding password for user in realm test.
New password:
Re-type new password:

-c オプション でパスワードファイルの新規作成
"test" の部分に realm名
user の部分は認証時のユーザ名

パスワードは対話式で入力を求められる

5. NginxにDigest認証を設定

# vi /etc/nginx/nginx.conf

お試しで / に設定

        location / {
            root   html;
            index  index.html index.htm;
            auth_digest "test";
            auth_digest_user_file /etc/nginx/.htdigest_test;
        }

auth_digest にパスワードファイル作成時に指定した realm名を入れる
auth_digest_user_file にパスワードファイル名を指定

6. Nginx起動

# systemctl enable nginx.service
# systemctl start nginx.service

7. 動作確認

ブラウザからアクセスすると下記のようなダイアログが表示される。
設定したユーザ名とパスワードを入力
Image2.png

認証が通ればページが表示される

Image4.png

ちなみに curl の場合は -u "user:password" に加えて --digest オプションを付ける

C:\>curl --digest -u "user:password" -I http://192.168.0.31/
HTTP/1.1 401 Unauthorized
Server: nginx/1.17.7
Date: Mon, 24 Feb 2020 04:39:39 GMT
Content-Type: text/html
Content-Length: 179
Connection: keep-alive
WWW-Authenticate: Digest algorithm="MD5", qop="auth", realm="test", nonce="39e753bf5e53538b"

HTTP/1.1 200 OK
Server: nginx/1.17.7
Date: Mon, 24 Feb 2020 04:39:40 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 24 Feb 2020 04:21:48 GMT
Connection: keep-alive
Authentication-Info: qop="auth", rspauth="0565bae4b6bfbda5513657687d318700", cnonce="66a3a2f56a85034803fdd085b686f8c3", nc=00000001
ETag: "5e534f5c-264"
Accept-Ranges: bytes

とりあえず動いていそう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4