nginx 反向代理 qBittorrent 并跳过登录

分享
2024-01-10 02:30

qBittorrent 可以配置子网白名单跳过登录,这里从代码层面介绍一下如何配置 Docker 部署的 nginx 反向代理 qBittorrent,并使跳过登录仍然可用

假设有两个子网,一个本地网络:192.168.0.0/16,一个 Docker 网络:172.18.0.0/16

nginx 配置:

server {
  listen                80;
  server_name           <server_name>;

  location / {
    proxy_pass http://<qbittorrent_ip>:<qbittorrent_port>;
    proxy_http_version 1.1;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

qbittorrent 配置:

Options -> WebUI:

  ┌── Authentication ───────────────────────────────────────────────────────┐
  │                                                                         │
  │ [x] Bypass authentication for clients in whitelisted IP subnets         │
  │     ┌───────────────────────────────────┐                               │
  │     │ 192.168.0.0/16                    │                               │
  │     │                                   │                               │
  │     └───────────────────────────────────┘                               │
  │                                                                         │
  └─────────────────────────────────────────────────────────────────────────┘

  ┌── [x] Enable reverse proxy support ─────────────────────────────────────┐
  │                        ┌───────────────────────────────────┐            │
  │  Trusted proxies list: │ 172.18.0.0/16                     │            │
  │                        └───────────────────────────────────┘            │
  └─────────────────────────────────────────────────────────────────────────┘

分析

https://github.com/qbittorrent/qBittorrent/blob/ad22237a2f50f9a636ed39bfc3f70e32c0e439ea/src/webui/webapplication.cpp#L840

// qBittorrent 解析本地 ip 的代码
QHostAddress WebApplication::resolveClientAddress() const
{
    // 如果 反向代理支持 选项未启用,直接返回 clientAddress
    if (!m_isReverseProxySupportEnabled)
        return m_env.clientAddress;

    // 如果 clientAddress 不在配置的反向代理列表的子网中,直接返回 clientAddress
    // Only reverse proxy can overwrite client address
    if (!Utils::Net::isIPInSubnets(m_env.clientAddress, m_trustedReverseProxyList))
        return m_env.clientAddress;

    // 读取 X_FORWARDED_FOR 请求头
    const QString forwardedFor = m_request.headers.value(Http::HEADER_X_FORWARDED_FOR);

    // 如果 X_FORWARDED_FOR 不为空,则返回 X_FORWARDED_FOR 配置的 ip 作为 clientAddress
    if (!forwardedFor.isEmpty())
    {
        // client address is the 1st global IP in X-Forwarded-For or, if none available, the 1st IP in the list
        const QStringList remoteIpList = forwardedFor.split(u',', Qt::SkipEmptyParts);

        if (!remoteIpList.isEmpty())
        {
            QHostAddress clientAddress;

            for (const QString &remoteIp : remoteIpList)
            {
                if (clientAddress.setAddress(remoteIp) && clientAddress.isGlobal())
                    return clientAddress;
            }

            if (clientAddress.setAddress(remoteIpList[0]))
                return clientAddress;
        }
    }

    return m_env.clientAddress;
}
验证码