公司动态

Dify调用本地API服务报错403?一篇文章帮你彻底排查网络与代理问题

📅 2026/8/25 14:08:04
Dify调用本地API服务报错403?一篇文章帮你彻底排查网络与代理问题
背景最近在Dify平台搭建工作流时需要调用同服务器上的一个本地API服务。本来以为在同一台机器上用localhost或127.0.0.1就能轻松搞定结果却遇到了一连串的网络问题从403 Forbidden到Connection refused再到Temporary failure in name resolution折腾了大半天。今天就把这个完整的排查过程和最终解决方案做个总结。下次再遇到Dify调用本地服务的问题照着这个思路走能少走很多弯路。一、问题现象我的环境是这样的Dify通过docker-compose部署在Linux服务器上本地API服务运行在宿主机的18080端口提供业务接口目标在Dify工作流的HTTP节点中调用这个本地API在Dify的HTTP节点中我最初填写的URL是http://localhost:180x0/api/v1/xx/prompt运行工作流后直接报错[Errno 111] Connection refused改成127.0.0.1、宿主机的局域网IP如172.168.8.43后又出现了各种不同的错误。二、排查与解决过程第一阶段从Connection refused到403 Forbidden1. 问题现象使用http://localhost:18080或http://127.0.0.1:18080时报错 [Errno 111] Connection refused2. 原因分析关键点Dify是运行在Docker容器里的。容器内的localhost指向的是容器自己而不是宿主机我的本地API服务运行在宿主机上容器内根本访问不到所以Connection refused是因为请求根本没到达我的服务。3. 解决步骤第一步改用宿主机IP查看宿主机的局域网IPip addr show | grep inet # 输出inet 172.168.xx.xx/24 brd 172.168.8.255 scope global noprefixroute eno1将Dify HTTP节点的URL改成http://172.168.xx.xx:1080/api/v1/xx/xx这时候报错变了403 Forbidden第二步排查代理问题从Dify的日志中看到请求确实到达了我的服务但返回了403。这时候注意到Dify架构中有一个ssrf_proxy服务基于Squid这是Dify为了防止SSRF攻击而设计的。查看docker-compose.yml中的ssrf_proxy配置ssrf_proxy: image: ubuntu/squid:latest restart: always volumes: - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template解决方法修改Squid配置文件允许访问内网IP段。在./ssrf_proxy/squid.conf.template中添加acl allowed_internal dst 172.168.8.0/24 http_access allow allowed_internal然后重启ssrf_proxy或者在api服务中强制绕过代理仅测试环境api: environment: HTTP_PROXY: HTTPS_PROXY: no_proxy: * NO_PROXY: *但即使这样403依然存在。第二阶段从403 Forbidden到200 OK的终极突破1. 问题现象继续排查后发现在Dify容器内用curl请求我的服务能通在宿主机上用curl请求我的服务也能通但Dify HTTP节点就是返回403这就很奇怪了——同样的URL、同样的Headers、同样的Body为什么curl能通Dify却不行2. 关键发现我进入Dify的api容器用Python脚本模拟Dify的请求方式docker exec -it docker-api-1 /bin/bash python3 -c import requests url http://172.168.xx.xx:xx/api/v1/xx/xx headers { } data {parameters: {...}} response requests.post(url, headersheaders, jsondata) print(fStatus: {response.status_code}) # 输出Status: 200Python脚本能通说明请求本身没问题。3. 根源分析这时我注意到/etc/docker/daemon.json的配置{ bip: 66.65.5.xx/16, default-address-pools: [ { base: 66.66.1.1/16, size: 24 } ] }Docker容器的IP段在66.65.x.x和66.66.x.x。而我的本地API服务可能对请求来源IP有校验比如只允许192.168.x.x网段访问。推断curl和Python脚本可能走了不同的网络路由源IP被转换了但Dify HTTP节点使用的是httpx库走的是Docker默认网络源IP就是容器IP66.65.x.x我的服务拒绝了非192.168.x.x网段的请求 → 返回4034. 最终解决方案修改/etc/docker/daemon.json将Docker的网段改成192.168.x.x{ bip: 192.168.200.1/24, default-address-pools: [ { base: 192.168.201.0/16, size: 28 } ] }重启Docker服务和Dify容器sudo systemctl restart docker cd /home/winning/dify docker-compose up -d修改后Dify容器的IP变成了192.168.200.x进入了服务允许的网段问题解决三、总结Dify调用本地API服务的排查清单以后遇到类似问题按这个顺序排查能快速定位问题步骤检查项说明1️⃣检查URL地址Dify容器内不能使用localhost要用宿主机IP或host.docker.internal2️⃣检查SSRF代理Dify默认有ssrf_proxy需要在Squid配置中允许访问内网IP3️⃣对比curl和Dify请求在容器内用curl/Python模拟请求如果通而Dify不通说明是Dify发送的请求与预期有差异4️⃣检查Docker网段查看/etc/docker/daemon.json中的bip和default-address-pools确保容器IP在目标服务允许的范围内5️⃣检查目标服务的访问控制服务可能有IP白名单、Header校验等需要根据实际情况调整特别提醒修改daemon.json后必须重启Dockersudo systemctl restart docker然后重启所有容器生产环境慎用直接修改Docker网段可能影响其他服务建议优先调整目标服务的白名单配置善用容器内测试进入容器用curl测试是最直接的排查手段四、遇到的问题和解决方法汇总问题1[Errno 111] Connection refused原因使用了localhost或127.0.0.1Dify容器内访问不到宿主机服务。解决方法使用宿主机局域网IP如172.168.8.43或host.docker.internal仅Docker Desktop for Windows/Mac支持。问题2403 ForbiddenSquid拦截原因Dify的ssrf_proxySquid默认拦截对内网IP的访问。解决方法修改ssrf_proxy/squid.conf.template添加允许访问的内网IP段或临时在api服务中清空代理环境变量。问题3Temporary failure in name resolution原因Linux下Docker容器不支持host.docker.internal域名。解决方法改用宿主机的实际IP地址如172.168.8.43。问题4403 Forbidden服务端拒绝原因Docker容器IP不在目标服务的允许范围内如IP白名单。解决方法修改/etc/docker/daemon.json将Docker网段调整到服务允许的IP范围内或调整服务端白名单配置。最后网络问题排查有时候就是这么曲折但只要抓住“请求到底到没到服务”、“服务为什么拒绝”这两个核心一步步拆解总能找到根源。希望这篇文章能帮到遇到类似问题的你