使用Nginx进行摘要认证

基本认证是将ID/PASS进行Base64编码,因此很容易被解码,不安全。
摘要认证使用MD5进行编码,因此窃听/篡改的风险比基本认证低。
然而,nginx默认不支持摘要认证。可以通过从源代码中添加外部模块并进行编译来实现支持。

环境

在Windows 10 Pro的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的安装是为了使用htdigest生成用于Digest认证的密码文件。

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

从上往下

    • Nginx本体

 

    • Digest認証モジュール https://github.com/samizdatco/nginx-http-auth-digest

zlib (gzip圧縮に使用)
OpenSSL

首先,将其解压缩到/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-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中进行授权设置。请将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;
        }

在创建密码文件时,将指定的realm名称放入auth_digest。在auth_digest_user_file中指定密码文件名。

6. 启动Nginx

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

7. 驗證動作

Image2.png

如果认证成功,页面将显示出来。

Image4.png

顺便提一下,对于curl命令,除了使用 -u “用户名:密码” 参数外,还需添加 –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

暫時看來似乎在運作中。

广告
将在 10 秒后关闭
bannerAds