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 │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
分析
// 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;
}