방금 내 포럼에서 많은 회원들의 IP 주소가 172.17.0.1로 저장되고 있다는 사실을 알게 되었습니다. 리버스 프록시나 다른 유사한 구성을 사용하지 않고 있으며, 클라이언트와 Discourse의 Docker 컨테이너 사이에 어떤 중개 장치도 없습니다. 혹시 원인을 알 수 있는 분 계신가요?
CloudFlare나 유사한 서비스를 사용하고 계신가요?
DNS에만 해당됩니다(회색 모드). (기술적으로는 www.intfiction.org에 주황색 모드가 설정되어 있지만, 제 서버에 도달하기 전에 apex 도메인인 intfiction.org으로 리다이렉트됩니다.) 제 app.yml에는 다음 내용이 포함되어 있지만, 두 부분 모두 관련이 없을 것이라 생각했습니다:
after_web_config:
- replace:
filename: /etc/nginx/nginx.conf
from: /sendfile.+on;/
to: |
server_names_hash_bucket_size 64;
sendfile on;
- file:
path: /etc/nginx/conf.d/discourse_redirect_1.conf
contents: |
server {
listen 80;
server_name www.intfiction.org;
return 301 $scheme://intfiction.org$request_uri;
}
서버 앞에 프록시가 있는 경우에만 관련이 있는 것 아닌가요?
저도 같은 문제를 겪고 있습니다. Discourse를 새 서버로 마이그레이션한 후 Cloudflare를 사용하지 않기로 결정했거든요.
Discourse를 처음부터 다시 설치한 뒤 백업을 복원했습니다.
app.yml에서 Cloudflare 템플릿 옵션을 다시 추가한 적이 없습니다.
다른 스레드의 코드를 추가해 보기도 했습니다:
- replace:
filename: /etc/nginx/conf.d/discourse.conf
from: "types {"
to: |
set_real_ip_from 10.0.0.0/24;
set_real_ip_from 172.17.0.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
types {
를 app.yml에 추가했지만 문제는 여전히 남아 있습니다:
IPv6 사용자의 마지막 IP가 172.17.0.1로 표시됩니다.
IPv4 사용자 주소는 완벽하게 표시됩니다.
이 서버에는 리버스 프록시나 기타 구성이 없습니다 - 문서에 나와 있는 표준 Discourse 설치 환경 그대로 80/443 포트로 트래픽을 제공하고 있습니다.
이 문제가 발생하는 이유를 알고 있는 것 같습니다.
IPv4의 경우 Docker는 노출된 호스트 주소/포트에서 컨테이너 호스트/포트로 역 NAT를 수행하기 위해 iptables에 방화벽 규칙을 삽입합니다. 이를 통해 컨테이너는 원래의 소스 주소를 확인할 수 있습니다.
IPv6의 경우 Docker는 docker-proxy라는 유저랜드 프록시를 사용하여 단순히 한 포트에서 다른 포트로 트래픽을 전달합니다. 이로 인해 컨테이너는 소스 주소를 로컬호스트(localhost)로 인식하게 됩니다. 이는 HTTP를 인식하는 프록시가 아니라 단순한 포트 포워딩이므로 X-Forwarded-For 헤더를 삽입할 수 없습니다.
Docker 핵심 프로젝트에서는 IPv6에 대한 NAT 지원을 추가하지 않았습니다. 이는 IPv6 NAT를 비효율적이라고 생각하거나 아직 구현하지 못했기 때문일 수 있습니다.
하지만 Docker에서 IPv6를 활성화한 후, 올바른 IPv6 NAT 규칙을 자동으로 삽입하는 컨테이너를 실행하면 이 문제를 해결할 수 있습니다.
설정 방법에 대한 가이드는 https://medium.com/@skleeschulte/how-to-enable-ipv6-for-docker-containers-on-ubuntu-18-04-c68394a219a2 를 참고하세요.
요약: 컨테이너에서 IPv6가 정상적으로 작동하도록 확인한 후 GitHub - robbertkl/docker-ipv6nat: Extend Docker with IPv6 NAT, similar to IPv4 · GitHub 를 실행하세요.
이것이 앱/Docker 컨테이너 내부에서 변경해야 하는 건가요, 외부에서 변경해야 하는 건가요, 아니면 둘 다인가요? 둘 다일 것 같긴 한데… 이건 고급 관리자 수준의 작업처럼 들립니다. 확인된다면, Docker 환경에서 Discourse의 IPv6를 활성화하는 방법을 쉽게 따라 할 수 있는 가이드를 제공해 주시면 감사하겠습니다.
나중에 내 사이트에서 이걸 구현해 보고, 진행 과정을 문서로 정리해 보려고 합니다. 저는 도커 전문가라고 할 수는 없지만, 그렇게 너무 어렵지는 않을 것 같습니다.
불행히도 제 Docker 지식이 제한적이라 예상보다 더 까다로운 문제가 발생했습니다. 현재 이 한계를 우회하기 위해 집에서 실행 중인 nginx를 통해 discourse만 프록시하는 방식으로 실험 중입니다. 만약 다른 모든 시도가 실패한다면 Cloudflare로 돌아가겠지만, 기능적인 사이트를 위해 그들에게 의존하고 싶지는 않습니다.
관심 있는 분들을 위한 간단한 안내: nginx 뒤에 Discourse를 배치하는 것이 이 문제를 해결하는 가장 쉬운 방법입니다. 소켓으로 Discourse를 설정하는 데에는 기본 app.yml 주석에 있는 링크를 사용하세요. 저에게는 재빌드 중에 표시될 커스텀 오류 페이지를 설정할 수 있다는 것도 추가적인 이점이었습니다.