作为 Nginx 屏蔽特定 IP(段)/UA 、使用 Nginx + Cloudflare 阻挡赛博垃圾 以及 使用 referrer-spam-list 处理来源垃圾(Referrer spam) 的补充

用 map 创建请求的黑/白名单

# 屏蔽 cookie
map $http_cookie $badcookie {
    default     0;
    ~*cookie1           1;
}

# 屏蔽路径
map $uri $badlocation {
    default            0;
    /path1             1;
    /path2             1;
}

# 屏蔽请求方法
map $request_method $badmethod {
    HEAD    0;
    GET     0;
    POST    0;
    default 1;
}

# 屏蔽 UA
map $http_user_agent $badagent {
    default     0;
    ""          1;
    ~*UA1       1;
}

将以上映射分别存储在对应的文件中,然后在 Nginx 的 http 块内引入这些文件

最后就可以在 server 块内使用 if 语句配置屏蔽状态码

server {
    # ...
    set $flag 0;
    
    if ($badcookie) { set $flag 1; }
    if ($badlocation) { set $flag 1; }
    if ($badagent) { set $flag 1; }
    if ($badmethod) { set $flag 1; }  

    if ($flag = 1) { return [status code]; }
}

除了屏蔽请求,还可以配置默认 server 块:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
    return 444;
}
  • 在 server 块返回 444 状态码,直接中断连接
    • 可以在一定程度上防止端口信息扫描
  • 在使用了 SSL 的 server 块添加 ssl_reject_handshake on,拒绝握手
    • 可以在一定程度上防止端口信息/源站扫描

使用如上 server 配置,会发现访问 IP:443 端口时还是会返回 “HTTP 请求发送到 HTTPS 端口” 的错误

如果不想返回任何信息,可以将配置修改为

server {
        listen 80 default_server;
        listen 443 ssl default_server;
        server_name _;

        ssl_reject_handshake on;

        error_page 497 =444 @close;

        location @close {
                return 444;
        }

        return 444;
}

当 497 错误发生时直接返回 444 状态码

想实现如图效果

简单来说:

  • Frp
    • 客户端将本地的 WebApp 转发到公网
    • 服务端的管理面板监听在本机回环地址(127.0.0.1)
    • 服务端在转发端口时也监听在本机回环地址
      这样可以避免直接在互联网通过 IP/域名访问到本地计算机
      同时不用自己准备 SSL 证书也可以支持 https
  • Nginx
    • Nginx 反向代理 Frp 的管理面板,以及所有端口转发的网页应用
      这样可以利用上 Nginx 的一些功能
  • Cloudflare
    • 接入 Nginx 反代域名,提供SSL、防火墙功能

参考

步骤

Frp

虽然 Frp 自带了 http/https 端口转发,但是这样

  • 无法用到 Nginx、Cloudflare 的很多功能
  • 需要自己准备 SSL 证书
  • 当 frps 所在服务器已经有 Nginx 监听在 80 端口时,无法将 vhost_http(s)_port 设置为 80 端口

frpc 转发本地 WebApp 这里不赘述,按照 tcp 端口转发配置即可

在 frps 的配置文件中

  • 将 dashboard_addr 字段设置为 127.0.0.1
    • 让管理面板监听在本机回环地址
  • 将 proxy_bind_addr 字段设置为 127.0.0.1
    • 实现端口转发时监听在本机回环地址
    • 注意:不能通过直接修改 bind_addr 的方式更改 proxy_bind_addr,否则 frpc 无法连接到服务器,因为 frps 监听在 127.0.0.1,没有对外暴露 bind_port

Nginx

假设 frps 的管理面板监听在 12345 端口,域名为 domain.tld,Nginx 的反代配置如下

server {
        listen 80;
        server_name frp.domain.tld;

        location / {
                proxy_pass http://127.0.0.1:12345;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

其实就是一般的反向代理配置

WebApp 的反向代理同理,更改 server_name 和反代地址的端口即可

注意:不要更改为 frp.domain.tld 的子域名,例如:subdomain.frp.domain.tld,这样无法使用 Cloudflare 的免费 SSL 证书(通配符证书收费)

Cloudflare

将 domain.tld 接入 Cloudflare,进入域名的 DNS 设置

添加 frp.domain.tld 和 webapp.domain.tld 的 A 类型 DNS 记录,都指向 frps 所在的服务器 IP,并开启 Cloudflare 代理

其实就是正常添加 domain.tld 子域名的 A 记录