Nginx + Certbot 反向代理与 HTTPS 配置,含 Basic Auth 认证与 fail2ban 防爆破

作者:war 发布时间: 2026-10-13 阅读量:4 评论数:0

0. 前言

0.1 要完成的事情

本文记录在全新安装的 Nginx 上,完成以下目标:

  • 反向代理两个本地服务:
    • memos.example.com → 127.0.0.1:18002(无认证)
    • panso.example.com → 127.0.0.1:18010(需要认证)
  • 为 panso.example.com 配置 Basic Auth 认证,用户名为 war。
  • 使用 Certbot 自动申请 Let's Encrypt 证书,配置 HTTPS,并将 HTTP 重定向到 HTTPS。
  • 使用 fail2ban 监控 Nginx 日志,自动封禁反复认证失败的 IP,防止暴力破解。
  • 验证证书自动续期是否正常。

域名使用占位符:memos.example.com、panso.example.com,实际使用时替换为自己的域名。

0.2 系统环境

  • 操作系统:Debian 13(apt 包管理)
  • 服务器配置:2H2G,自用
  • 域名:memos.example.com、panso.example.com,均已解析到服务器公网 IP
  • 后端服务:已在本机运行,分别监听 127.0.0.1:18002 和 127.0.0.1:18010
  • 软件环境:
    • Nginx(apt 安装)
    • Certbot、python3-certbot-nginx
    • apache2-utils(提供 htpasswd)
    • fail2ban
  • 网络要求:服务器 80、443 端口已开放

1. 安装 Nginx 与 Certbot

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx apache2-utils -y
  • certbot、python3-certbot-nginx:自动申请并配置 SSL 证书。
  • apache2-utils:提供 htpasswd,用于生成 Basic Auth 密码文件。

安装完成后 Nginx 会自动启动。可访问 http://服务器IP 确认默认页面。

image-kikF.webp

2. 配置 Memos 站点(无认证)

创建配置文件:

sudo nano /etc/nginx/sites-available/memos.example.com

写入:

server {
    listen 80;
    server_name memos.example.com;

    location / {
        proxy_pass http://localhost:18002;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

说明:

  • proxy_pass 指向本机 18002 端口。
  • 四个 proxy_set_header 是反向代理标准配置,确保后端获取真实客户端 IP 和原始协议。

3. 配置 Panso 站点(Basic Auth + 反代)

3.1 生成 Basic Auth 密码文件

使用 htpasswd 创建密码文件,用户名为 war,密码自行设置:

sudo htpasswd -Bc /etc/nginx/.htpasswd war
  • -B:使用 bcrypt 算法加密密码。
  • -c:创建新文件;后续再添加用户时去掉 -c。
  • 按提示输入并确认密码。

如果再执行一次如下命令

sudo htpasswd -B /etc/nginx/.htpasswd alice

就会出现两个用户,两个用户都可以登录网站。/etc/nginx/.htpasswd 生成的格式如下:

war:$2y$05$...
alice:$2y$05$...

3.2 创建 Nginx 配置文件

sudo nano /etc/nginx/sites-available/panso.example.com

写入:

server {
    listen 80;
    server_name panso.example.com;

    location / {
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;

        proxy_pass http://localhost:18010;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

4. 启用站点并测试 Nginx

sudo ln -s /etc/nginx/sites-available/memos.example.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/panso.example.com /etc/nginx/sites-enabled/

sudo nginx -t
sudo systemctl reload nginx

如果 nginx -t 显示 syntax is ok 和 test is successful,说明配置无误。

Ubuntu / Debian 下,Nginx 默认用两个目录管理站点配置:

  • /etc/nginx/sites-available/:站点配置的“仓库”。所有写好的配置文件都放这里,但不会自动生效。

  • /etc/nginx/sites-enabled/:真正启用的站点配置。Nginx 主配置(/etc/nginx/nginx.conf)中通常有一行:

    include /etc/nginx/sites-enabled/*;
    

    因此只有这个目录里的文件或软链接会被 Nginx 加载。

其他发行版也可以自己加这个配置到达和本文档一样的效果。


5. 用 Certbot 配置 HTTPS

一条命令同时为两个域名申请证书并自动修改 Nginx 配置:

sudo certbot --nginx -d memos.example.com -d panso.example.com

Certbot 会:

  • 自动申请 Let's Encrypt 证书;
  • 修改 Nginx 配置文件,添加 SSL 配置;
  • 询问是否将 HTTP 重定向到 HTTPS,建议选择 “2: Redirect”。

完成后访问:

  • https://memos.example.com
  • https://panso.example.com

Panso 会弹出 Basic Auth 登录框,输入用户 war 和密码即可。


6. 验证证书自动续期

Let's Encrypt 证书有效期 90 天,Certbot 会自动续期。手动测试:

sudo certbot renew --dry-run

看到 Congratulations, all simulated renewals succeeded 即表示自动续期配置正常。


7. 日志查看

Nginx 默认日志位置:

  • 访问日志:/var/log/nginx/access.log
  • 错误日志:/var/log/nginx/error.log

筛选认证失败记录:

sudo grep -E " (401|403) " /var/log/nginx/access.log

8. 使用 fail2ban 防止暴力破解

Basic Auth 虽然方便,但公网上面临持续的密码爆破尝试。fail2ban 可以监控 Nginx 日志,自动封禁反复认证失败的 IP,且不会误伤正常访问。

8.1 安装 fail2ban

sudo apt install fail2ban -y

安装后服务会自动启动,但默认没有针对 Nginx Basic Auth 的规则,需要手动添加。

8.2 创建过滤器

新建 /etc/fail2ban/filter.d/nginx-basic-auth.conf:

sudo nano /etc/fail2ban/filter.d/nginx-basic-auth.conf

写入以下内容:

[Definition]
failregex = ^<HOST> - - \[.*\] ".*" (401|403) \d+$
ignoreregex =

说明:

  • 该正则匹配 Nginx 默认 combined 日志格式中状态码为 401 或 403 的行。
  • <HOST> 会被 fail2ban 自动替换为客户端 IP。

8.3 创建 jail 配置

新建 /etc/fail2ban/jail.d/nginx-basic-auth.local:

sudo nano /etc/fail2ban/jail.d/nginx-basic-auth.local

写入:

[nginx-basic-auth]
enabled = true
port = http,https
filter = nginx-basic-auth
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 300
bantime = 600

参数解释:

参数 值 含义
maxretry 10 5 分钟内失败 5 次即封禁
findtime 300 统计窗口为 300 秒(5 分钟)
bantime 600 封禁 10 分钟

可根据需要调整。

推荐一个通用方案:在 jail.local 中补上 jail.d 的 include,然后把每个 jail 的配置放在 jail.d/*.local 里。

理由:

  • jail.d/*.local 是 fail2ban 官方约定,多个 jail 分文件管理更清晰。
  • jail.local 只负责“启用 include”,不堆具体 jail 配置。
  • 这样以后加任何新 jail,直接往 jail.d/ 扔文件即可,不用改 jail.local。
  • Debian 13 的 jail.conf 缺失了这行 include,补上后就符合通用预期。

8.4 让 fail2ban 加载 jail.d 下的配置

Debian 13 的 fail2ban 1.1.0 中,/etc/fail2ban/jail.conf 默认没有 include jail.d/ 目录,导致放在 jail.d/ 下的 jail 配置不会生效。需要在 jail.local 中手动补上 include。

创建或编辑 /etc/fail2ban/jail.local:

sudo nano /etc/fail2ban/jail.local

写入:

[INCLUDES]
after = jail.d/*.conf jail.d/*.local

说明:

  • after 表示在读取完 jail.local 后再加载 jail.d/ 下的文件。
  • *.conf 和 *.local 都包含,兼容两种命名习惯。
  • 这一行让 fail2ban 恢复官方默认行为,之后所有 jail.d/ 下的配置都会生效。

然后重启 fail2ban:

sudo systemctl restart fail2ban
sudo fail2ban-client status

此时 Jail list 中应同时出现 sshd 和 nginx-basic-auth。

8.5 测试并启动

测试过滤器是否能正确匹配日志:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-basic-auth.conf

若输出中 matched 行数大于 0,说明规则有效。

8.6 查看封禁状态

sudo fail2ban-client status nginx-basic-auth

可看到当前被封禁的 IP 列表及失败统计。

8.7 手动解封

如果自己误触封禁,可用以下命令解封:

sudo fail2ban-client set nginx-basic-auth unbanip 你的IP

9. 关闭站点与证书处理

当某个站点不再需要时,根据你是否还想保留证书,有以下几种处理方式。


9.1 暂时关闭站点(保留证书)

如果只是暂时不想让别人访问,但以后可能还会开启,最简单的方法是停用 Nginx 站点配置,证书继续保留并自动续签。

  1. 删除 sites-enabled 中的软链接:

    sudo rm /etc/nginx/sites-enabled/panso.example.com
    
  2. 测试并重载 Nginx:

    sudo nginx -t
    sudo systemctl reload nginx
    

    此时 panso.example.com 将无法访问,但证书文件仍在 /etc/letsencrypt/live/ 下,Certbot 也会继续为它自动续签(因为续签配置未改动)。

  3. 以后想重新启用,只需重新创建软链接:

    sudo ln -s /etc/nginx/sites-available/panso.example.com /etc/nginx/sites-enabled/
    sudo systemctl reload nginx
    

9.2 彻底删除站点与证书

如果确定不再使用该站点,并且希望删除证书、停止续签,按以下步骤操作。

  1. 先从 Nginx 配置中移除对证书的引用编辑 sites-available 中对应的站点文件,删除或注释掉所有 ssl_certificate、ssl_certificate_key 等 SSL 相关行,以及监听 443 的 server 块。也可以直接删除整个站点配置文件。

  2. 删除 sites-enabled 中的软链接:

    sudo rm /etc/nginx/sites-enabled/panso.example.com
    
  3. 删除证书:

    sudo certbot delete --cert-name panso.example.com
    

    如果不确定证书名称,可以先运行 sudo certbot certificates 查看所有证书列表。

  4. 测试并重载 Nginx:

    sudo nginx -t
    sudo systemctl reload nginx
    

9.3 仅停止证书自动续签

如果只想停止某个证书的自动续期,但保留现有证书文件直到过期,可以禁用其续签配置。

  1. 找到对应的续签配置文件:

    ls /etc/letsencrypt/renewal/
    

    文件名通常与证书名一致,例如 panso.example.com.conf。

  2. 重命名该文件,使其不再被 Certbot 识别:

    sudo mv /etc/letsencrypt/renewal/panso.example.com.conf \
            /etc/letsencrypt/renewal/panso.example.com.conf.disabled
    

    或者直接删除:

    sudo rm /etc/letsencrypt/renewal/panso.example.com.conf
    
  3. 验证:

    sudo certbot renew --dry-run
    

    如果输出中没有该证书的续签模拟,说明已成功停止。


9.4 关于共享证书的特别说明

如果多个域名共用同一张证书(例如 memos.example.com 和 panso.example.com 一起申请,证书保存在 /etc/letsencrypt/live/memos.example.com/),则:

  • 不能单独删除 panso 的证书,因为它与 memos 共用同一个证书文件。

  • 执行 sudo certbot delete --cert-name memos.example.com 会同时影响两个站点。

  • 只想关闭 panso、保留 memos:只需停用 panso 的 Nginx 站点配置(删除 sites-enabled 中的软链接),无需操作证书。证书会继续为 memos 自动续签。

  • 想为每个域名使用独立证书:先删除共享证书,再分别申请:

    # 确保两个站点的 Nginx 配置已移除对旧证书的引用
    sudo certbot delete --cert-name memos.example.com
    
    # 分别申请独立证书
    sudo certbot --nginx -d memos.example.com
    sudo certbot --nginx -d panso.example.com
    

评论