Dify 에서 내부망 API 403/Connection Refused 오류 해결 완전 정리

Dify 1.7.1을 Docker Compose로 배포하고, 워크플로우 HTTP 요청 노드를 통해 내부망 Tomcat 서버(http://192.168.100.106:90)를 호출할 때 발생하는 403 및 Connection refused 오류의 원인과 해결 방법을 단계별로 설명한다.

1. 문제 상황

가장 혼란스러운 점은 컨테이너 내부에서 curl 명령어로는 정상 응답(200)을 받지만, Dify 웹 인터페이스를 통한 호출은 실패한다는 것이다. 주요 오류 메시지는 다음과 같다.

  • Squid 403 Access Denied: The requested URL could not be retrieved Access Denied.
  • Connection refused: [Errno 111] Connection refused

2. 시도했던 (효과 없는) 방법들

다음과 같은 방법들은 문제 해결에 전혀 도움이 되지 않았다.

  • 환경 변수 추가: docker-compose.ymlHTTP_PROXY, HTTPS_PROXY, NO_PROXY 등을 설정했지만 Dify 워크플로우는 이를 무시한다.
  • 호스트 시스템 프록시 설정 변경: /etc/profile이나 Docker 데몬의 프록시 설정을 변경해도 동일하게 동작하지 않는다.
  • ssrf_proxy 컨테이너 삭제: docker-compose rm -f -s -v ssrf_proxy 명령어로 컨테이너를 제거하면 오류가 403에서 Connection refused로 바뀌며 근본적인 해결이 되지 않는다.
  • 호스트의 템플릿 파일만 수정: squid.conf.template을 수정하고 down/up만 하면 컨테이너 내부 설정이 업데이트되지 않는다.

3. 403 오류의 진짜 원인

ssrf_proxy 컨테이너 내부의 Squid 설정 파일을 직접 확인(docker exec -it docker-ssrf_proxy-1 cat /etc/squid/squid.conf)하여 원인을 찾았다.

# 기본 설정 (앞부분)
http_access deny all    # 모든 요청을 먼저 거부

# 사용자가 추가한 허용 규칙 (뒷부분)
http_access allow localnet
http_access allow all   # deny all 때문에 실행되지 않음

Squid는 규칙을 순차적으로 평가한다. http_access deny all이 먼저 매칭되면 이후의 allow 규칙은 실행되지 않는다. 따라서 내부망 접속이 기본적으로 차단된다.

4. 문제의 근본 원인 요약

  • Dify 워크플로우의 HTTP 요청 노드는 항상 내장 ssrf_proxy(Squid)를 경유한다.
  • Squid는 기본적으로 내부망 접속을 차단하도록 설정되어 있다.
  • 허용 규칙(allow)이 거부 규칙(deny)보다 뒤에 위치하여 동작하지 않는다.
  • 호스트의 템플릿 파일을 수정해도 컨테이너가 재시작되지 않으면 적용되지 않는다.
  • ssrf_proxy를 삭제하면 Dify가 프록시를 찾지 못해 Connection refused 오류가 발생한다.

5. 해결 방법

방법 A: 영구적인 해결 (권장)

  1. ssrf_proxy 컨테이너 복구
    cd /data/dify-1.7.1/docker
    docker-compose up -d ssrf_proxy
  2. 호스트의 squid.conf.template 파일 수정
    ################################## Reverse Proxy To Sandbox ################################
    http_port ${REVERSE_PROXY_PORT} accel vhost
    cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver
    
    http_access allow all
    always_direct allow all
    
    acl localnet src 192.168.0.0/16
    acl localnet src 172.16.0.0/12
    acl localnet src 10.0.0.0/8
    
    client_request_buffer_max_size 100 MB
  3. 컨테이너 완전 재생성
    docker-compose down -v
    docker-compose up -d

방법 B: 빠른 테스트용 (컨테이너 재시작 불필요)

docker exec -it docker-ssrf_proxy-1 sh -c '
cat > /etc/squid/squid.conf << "EOF"
http_access allow all
always_direct allow all

http_port 8194 accel vhost
cache_peer sandbox parent 8194 0 no-query originserver

client_request_buffer_max_size 100 MB
EOF
squid -k reconfigure
'

6. 핵심 결론

  1. Dify HTTP 요청 노드는 항상 Squid 프록시를 경유한다.
  2. Squid는 기본적으로 내부망 접근을 차단하므로 별도 허용 설정이 필요하다.
  3. Squid 설정은 allow 규칙을 deny 규칙보다 먼저 배치해야 한다.
  4. 문제 진단 시 호스트의 템플릿 파일이 아닌 컨테이너 내부 설정 파일을 직접 확인해야 한다.
  5. ssrf_proxy 컨테이너를 삭제하는 것은 문제 해결이 아닌 오류 유형만 변경하는 행위다.

태그: Dify Docker Compose Squid SSRF Proxy HTTP 403

6월 9일 19:29에 게시됨