Google OAuth 生产环境问题排查与解决方案

项目: cbiu.fun
服务器位置: 中国广州
解决时间: 2026-02-04 ~ 2026-02-05 (约 5 小时)


📋 问题清单

问题 1: UntrustedHost 错误

错误信息:

[auth][error] UntrustedHost: Host must be trusted. URL was: https://cbiu.fun/api/auth/session

原因:
NextAuth.js 在生产环境(特别是 Edge Runtime)中需要明确信任主机。

解决方案:

# docker-compose.yml environment: - AUTH_TRUST_HOST=true - AUTH_URL=https://cbiu.fun - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}

提交: 83cb7f5


问题 2: fetch failed - GFW 阻断

错误信息:

[auth][error] TypeError: fetch failed

原因:
服务器在中国大陆,GFW(防火墙)阻止访问 Google 服务。

诊断过程:

# 测试连接 curl -4 https://accounts.google.com # ❌ Timeout curl -4 https://www.baidu.com # ✅ Success # 确认位置 curl ipinfo.io # country=CN

解决方案: 部署 V2Ray 加密代理

2.1 V2Ray 服务器(美国 VPS)

服务器 IP: 216.40.86.126
端口: 10086
协议: VMess + WebSocket

# 创建配置文件 cat > /root/v2ray/config.json << 'EOF' { "inbounds": [{ "port": 10086, "protocol": "vmess", "settings": { "clients": [{"id": "5ea51ecf-032c-4833-b5ea-33ad501a6b7d", "alterId": 0}] }, "streamSettings": { "network": "ws", "wsSettings": {"path": "/v2ray"} } }], "outbounds": [{"protocol": "freedom"}] } EOF # 运行服务器 docker run -d --name v2ray --restart always \ -v /root/v2ray/config.json:/etc/v2ray/config.json \ -p 10086:10086 \ v2fly/v2fly-core:latest run -c /etc/v2ray/config.json # 开放防火墙端口 ufw allow 10086/tcp

2.2 V2Ray 客户端(中国服务器)

# 下载 V2Ray wget https://ghp.ci/https://github.com/v2fly/v2ray-core/releases/download/v5.22.0/v2ray-linux-64.zip unzip v2ray-linux-64.zip -d /usr/local/v2ray # 创建配置文件 cat > /usr/local/v2ray/config.json << 'EOF' { "inbounds": [{ "port": 10808, "protocol": "http", "listen": "127.0.0.1" }], "outbounds": [{ "protocol": "vmess", "settings": { "vnext": [{ "address": "216.40.86.126", "port": 10086, "users": [{"id": "5ea51ecf-032c-4833-b5ea-33ad501a6b7d", "alterId": 0}] }] }, "streamSettings": { "network": "ws", "wsSettings": {"path": "/v2ray"} } }] } EOF # 启动客户端 nohup /usr/local/v2ray/v2ray run -c /usr/local/v2ray/config.json > /var/log/v2ray.log 2>&1 & # 验证代理 curl -x http://127.0.0.1:10808 https://www.google.com # ✅ Success

问题 3: Proxychains 配置路径错误 ⭐

错误现象:
虽然配置了 proxychains,但数据库连接仍被代理,导致应用无法连接数据库。

诊断过程:

# 测试发现 proxychains 读取了错误的配置 docker exec cbiu-website sh -c "proxychains4 node -e \"...\"" # 输出: [proxychains] Strict chain ... 127.0.0.1:9050 ... timeout # ^ 错误的端口!应该是 10808

根本原因:
Alpine Linux 的 proxychains-ng 默认读取 /etc/proxychains/proxychains.conf,而不是 /etc/proxychains.conf

解决方案:

# Dockerfile # ❌ 错误的路径 COPY proxychains.conf /etc/proxychains.conf # ✅ 正确的路径 RUN mkdir -p /etc/proxychains COPY proxychains.conf /etc/proxychains/proxychains.conf

Proxychains 配置文件 (proxychains.conf):

strict_chain tcp_read_time_out 15000 tcp_connect_time_out 8000 # 排除本地网络,避免数据库连接被代理 localnet 127.0.0.0/255.0.0.0 localnet ::1/128 localnet 172.17.0.0/255.255.0.0 # Docker 默认网桥 localnet 172.18.0.0/255.255.0.0 # 自定义 Docker 网络 [ProxyList] http 127.0.0.1 10808

Docker 启动命令:

# Dockerfile CMD ["proxychains4", "-q", "node", "server.js"]

提交: 2142bbc


问题 4: 数据库连接配置

问题:
容器使用 host network mode,但数据库在 Docker bridge 网络,无法通过 localhost 访问。

解决方案:

# 获取 Docker 网络网关 IP docker network inspect cbiu-website_cbiu-network | grep Gateway # 输出: "Gateway": "172.18.0.1" # 更新 .env 文件 DATABASE_URL=mysql://root:123456@172.18.0.1:3306/cbiu_webside

docker-compose.yml 环境变量:

environment: - HTTP_PROXY=http://127.0.0.1:10808 - HTTPS_PROXY=http://127.0.0.1:10808 - NO_PROXY=localhost,127.0.0.1,db,172.17.0.1,172.18.0.1,172.17.0.0/16,172.18.0.0/16

提交: ea41ef6


问题 5: 缺少 NextAuth 数据库表

错误信息:

The table `accounts` does not exist in the current database.

原因:
生产数据库没有运行 Prisma migrations,缺少 NextAuth 所需的表。

解决方案:

# 手动创建表 docker-compose exec -T db mysql -uroot -p123456 cbiu_webside << 'EOF' CREATE TABLE `accounts` ( `id` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `type` VARCHAR(191) NOT NULL, `provider` VARCHAR(191) NOT NULL, `provider_account_id` VARCHAR(191) NOT NULL, `refresh_token` TEXT NULL, `access_token` TEXT NULL, `expires_at` INT NULL, `token_type` VARCHAR(191) NULL, `scope` VARCHAR(191) NULL, `id_token` TEXT NULL, `session_state` VARCHAR(191) NULL, PRIMARY KEY (`id`), UNIQUE KEY `provider_provider_account_id` (`provider`, `provider_account_id`), KEY `user_id` (`user_id`), CONSTRAINT `accounts_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `sessions` ( `id` VARCHAR(191) NOT NULL, `session_token` VARCHAR(191) NOT NULL, `user_id` VARCHAR(191) NOT NULL, `expires` DATETIME(3) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `session_token` (`session_token`), KEY `user_id` (`user_id`), CONSTRAINT `sessions_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `verification_tokens` ( `identifier` VARCHAR(191) NOT NULL, `token` VARCHAR(191) NOT NULL, `expires` DATETIME(3) NOT NULL, UNIQUE KEY `token` (`token`), UNIQUE KEY `identifier_token` (`identifier`, `token`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; EOF

问题 6: users 表结构不完整

错误信息:

The column `cbiu_webside.users.name` does not exist in the current database. Null constraint violation on the fields: (`username`)

原因:

  1. 缺少 NextAuth 所需的列:name, email_verified, image
  2. usernamepassword_hash 设置为 NOT NULL,但 Google OAuth 不提供这些字段

解决方案:

# 添加缺失的列 docker-compose exec -T db mysql -uroot -p123456 cbiu_webside << 'EOF' ALTER TABLE users ADD COLUMN name VARCHAR(191) NULL AFTER id, ADD COLUMN email_verified DATETIME(3) NULL AFTER email, ADD COLUMN image VARCHAR(191) NULL AFTER email_verified; EOF # 修改为可选字段 docker-compose exec -T db mysql -uroot -p123456 cbiu_webside << 'EOF' ALTER TABLE users MODIFY COLUMN username VARCHAR(191) NULL; ALTER TABLE users MODIFY COLUMN password_hash VARCHAR(191) NULL; EOF # 重启容器刷新 Prisma 缓存 docker-compose restart app

🏗️ 最终架构

中国服务器 (cbiu.fun) 美国 VPS (216.40.86.126) ┌──────────────────────────┐ ┌──────────────────┐ │ Docker Container │ │ │ │ ┌────────────────────┐ │ │ V2Ray Server │ │ │ Next.js App │ │ │ (port 10086) │ │ │ ↓ │ │ │ VMess+WebSocket │ │ │ proxychains4 │──┼─Host──┼─>│ ↓ │ │ └────────────────────┘ │ Mode │ Google APIs │ │ │ │ │ │ V2Ray Client (Host) │ └──────────────────┘ │ HTTP Proxy :10808 │ │ │ │ MySQL Database │ │ IP: 172.18.0.1:3306 │ │ (Docker bridge network) │ └──────────────────────────┘

网络流程:

  1. Next.js App 通过 proxychains 启动
  2. 对 Google API 的请求 → proxychains → V2Ray Client (127.0.0.1:10808)
  3. V2Ray Client → V2Ray Server (美国) → Google
  4. 对数据库的请求 → 被 localnet 排除 → 直接访问 172.18.0.1:3306

📝 关键配置文件

Dockerfile

# 安装 proxychains RUN apk add --no-cache proxychains-ng # 复制配置到正确路径 RUN mkdir -p /etc/proxychains COPY proxychains.conf /etc/proxychains/proxychains.conf # 使用 proxychains 包装启动命令 CMD ["proxychains4", "-q", "node", "server.js"]

docker-compose.yml

services: app: network_mode: "host" environment: - DATABASE_URL=mysql://root:123456@172.18.0.1:3306/cbiu_webside - AUTH_TRUST_HOST=true - AUTH_URL=https://cbiu.fun - HTTP_PROXY=http://127.0.0.1:10808 - HTTPS_PROXY=http://127.0.0.1:10808 - NO_PROXY=localhost,127.0.0.1,db,172.17.0.1,172.18.0.1,172.17.0.0/16,172.18.0.0/16

🔧 维护命令

V2Ray 管理

# 检查 V2Ray 客户端状态 ps aux | grep v2ray # 查看日志 tail -f /var/log/v2ray.log # 重启 V2Ray 客户端 pkill v2ray nohup /usr/local/v2ray/v2ray run -c /usr/local/v2ray/config.json > /var/log/v2ray.log 2>&1 & # 测试代理 curl -x http://127.0.0.1:10808 https://www.google.com

数据库管理

# 查看表结构 docker-compose exec db mysql -uroot -p123456 cbiu_webside -e "SHOW TABLES;" docker-compose exec db mysql -uroot -p123456 cbiu_webside -e "DESCRIBE users;" # 查看用户 docker-compose exec db mysql -uroot -p123456 cbiu_webside -e "SELECT id, name, email, role FROM users;"

应用调试

# 查看日志 docker-compose logs -f app # 检查容器内配置 docker exec cbiu-website cat /etc/proxychains/proxychains.conf docker exec cbiu-website env | grep -E 'DATABASE|PROXY' # 测试数据库连接 docker exec cbiu-website sh -c "nc -zv 172.18.0.1 3306"

💡 经验总结

1. GFW 绕过

  • ❌ 简单 HTTP 代理容易被 DPI 检测
  • ✅ VMess + WebSocket 加密协议成功绕过

2. Proxychains 配置

  • ⚠️ Alpine Linux 的默认路径是 /etc/proxychains/proxychains.conf
  • ✅ 必须配置 localnet 排除内网流量
  • ✅ Docker 网络段(172.17.0.0/16, 172.18.0.0/16)也要排除

3. Docker 网络

  • ⚠️ Host network mode 不能直接访问 bridge 网络容器的 localhost
  • ✅ 使用 Docker 网络网关 IP(如 172.18.0.1)

4. NextAuth Schema

  • ✅ 生产数据库必须包含:accounts, sessions, verification_tokens
  • ✅ users 表必须有:name, email_verified, image
  • ⚠️ username 和 password_hash 必须为可选(Google OAuth 不提供)

5. Prisma 客户端缓存

  • ⚠️ Schema 修改后需要重启容器刷新 Prisma 客户端

✅ 验证清单

  • V2Ray 客户端运行正常
  • 代理可以访问 Google (curl -x http://127.0.0.1:10808 https://www.google.com)
  • Proxychains 配置路径正确 (/etc/proxychains/proxychains.conf)
  • 数据库连接正常(应用无错误日志)
  • 所有 NextAuth 表已创建
  • users 表 schema 完整
  • Google OAuth 登录流程成功
  • 用户数据正确保存到数据库

📚 参考资料

Comments(0)

Please login to comment

No comments yet. Be the first to comment!