使用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. 驗證動作
如果认证成功,页面将显示出来。
顺便提一下,对于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
暫時看來似乎在運作中。