#n8n #docker #http-proxy #https-proxy #telegram #xray #v2ray ## 问题描述 n8n 运行在 Docker 容器内,宿主机已有代理(xray/v2ray 监听 `10808` 端口),但 n8n 的 Telegram 节点无法连接 `api.telegram.org`。 --- ## 排查过程 ### 1. 宿主机可以访问,容器不行 宿主机用 proxychains 可以正常访问 Telegram API: ```bash proxychains4 curl https://api.telegram.org/bot/getMe # ✅ 返回 bot 信息 ``` 容器内用 Node.js fetch 测试: ```bash node -e "fetch('https://api.telegram.org/...').then(r=>r.text()).then(console.log).catch(console.error)" # ❌ ETIMEDOUT ``` ### 2. 发现 docker-compose.yml 中代理地址错误 ```yaml # ❌ 错误:容器内的 127.0.0.1 是容器自身,不是宿主机 HTTP_PROXY: http://127.0.0.1:10808 HTTPS_PROXY: http://127.0.0.1:10808 ``` ### 3. 修正为 host.docker.internal ```yaml # ✅ 正确:通过 host.docker.internal 访问宿主机 HTTP_PROXY: http://host.docker.internal:10808 HTTPS_PROXY: http://host.docker.internal:10808 ``` `host.docker.internal` 能工作的前提是 `docker-compose.yml` 中已有: ```yaml extra_hosts: - "host.docker.internal:host-gateway" ``` ### 4. 确认代理端口可达 在容器内验证连通性: ```bash node -e " const net = require('net'); const s = net.createConnection(10808, 'host.docker.internal', () => { console.log('✅ 代理端口可达'); s.destroy(); }); s.on('error', e => console.log('❌ 失败:', e.message)); " # ✅ 代理端口可达 ``` 宿主机确认代理监听地址: ```bash ss -tlnp | grep 10808 # LISTEN *:10808 ← 监听 0.0.0.0,容器可以访问 ✅ ``` ### 5. Node.js 原生 fetch 不读代理环境变量 `node fetch` 不会自动使用 `HTTP_PROXY`/`HTTPS_PROXY`,所以容器内的测试命令显示 ETIMEDOUT 是**测试方法有误**,并非代理没生效。 **n8n 使用 axios**,axios 会自动读取代理环境变量,所以 n8n 节点内是正常工作的。 验证方法:直接在 n8n 里用 **HTTP Request 节点** 访问: ``` https://api.telegram.org/bot/getMe ``` 能返回 bot 信息即代理生效 ✅ --- ## 最终解决方案 ### docker-compose.yml 关键配置 ```yaml services: n8n: environment: HTTP_PROXY: http://host.docker.internal:10808 # 指向宿主机代理 HTTPS_PROXY: http://host.docker.internal:10808 NO_PROXY: localhost,127.0.0.1 # 内网地址不走代理 extra_hosts: - "host.docker.internal:host-gateway" # 必须!映射宿主机 IP ``` ### 前提条件 |条件|检查命令| |---|---| |宿主机代理监听 `0.0.0.0`(非 `127.0.0.1`)|`ss -tlnp \| grep 10808`| |docker-compose 有 `extra_hosts` 配置|查看 yml 文件| ### 重启生效 ```bash docker compose down && docker compose up -d ``` --- ## 总结 |问题|原因|解决| |---|---|---| |代理不生效|`127.0.0.1` 在容器内指向容器本身|改为 `host.docker.internal`| |测试误报 ETIMEDOUT|Node.js 原生 `fetch` 不读代理环境变量|用 n8n HTTP Request 节点直接测试|