커밋 b4a3389 업데이트 후 사용자 IP를 가져오는 방법

업데이트 완료 후

모든 사용자의 마지막 사용 주소가 Docker 게이트웨이(예: 172.17.0.1)로 변경되었습니다.

제가 사용하는 아키텍처는 다음과 같습니다.

Cloudflare → VPS Nginx → Discourse Docker Nginx → Discourse

저와 비슷한 설정을 사용 중인데, 사용자의 IP를 전달하도록 내 호스트 nginx 설정에 추가한 내용은 다음과 같습니다:

location / {
  set_real_ip_from 103.21.244.0/22;
  set_real_ip_from 103.22.200.0/22;
  set_real_ip_from 103.31.4.0/22;
  set_real_ip_from 104.16.0.0/13;
  set_real_ip_from 104.24.0.0/14;
  set_real_ip_from 108.162.192.0/18;
  set_real_ip_from 131.0.72.0/22;
  set_real_ip_from 141.101.64.0/18;
  set_real_ip_from 162.158.0.0/15;
  set_real_ip_from 172.64.0.0/13;
  set_real_ip_from 173.245.48.0/20;
  set_real_ip_from 188.114.96.0/20;
  set_real_ip_from 190.93.240.0/20;
  set_real_ip_from 197.234.240.0/22;
  set_real_ip_from 198.41.128.0/17;
  set_real_ip_from 2400:cb00::/32;
  set_real_ip_from 2405:8100::/32;
  set_real_ip_from 2405:b500::/32;
  set_real_ip_from 2606:4700::/32;
  set_real_ip_from 2803:f800::/32;
  set_real_ip_from 2a06:98c0::/29;
  set_real_ip_from 2c0f:f248::/32;

  real_ip_header X-Forwarded-For;

  proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;

  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Host $http_host;
  proxy_set_header X-Forwarded-Proto $scheme;

  proxy_http_version 1.1;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto https;
}

hello @CLOUD_PHT - Meta에 오신 것을 환영합니다 :slight_smile:

같은 머신 설정에서 웹사이트를 하나 이상 운영 중이신가요? (예: WordPress 사이트 + Discourse)

문제는 Docker의 내부 네트워크(포트 매핑)를 통해 트래픽을 라우팅하고 있어, 모든 수신 요청이 Docker 게이트웨이 IP(172.17.0.1)로 마스킹된다는 점입니다. 내부 nginx가 172.17.0.1을 Cloudflare IP로 인식하지 못하므로 보안상의 이유로 CF-Connecting-IP 헤더를 제거합니다.

이를 해결하려면 설정을 Unix 소켓 사용으로 전환해야 합니다. 이렇게 하면 외부 nginx가 Docker 네트워크가 IP 주소를 망가뜨리지 않고 트래픽(및 헤더)을 Discourse로 직접 전달할 수 있습니다.

공식 가이드를 따르고, 재빌드할 때 app.yml 파일에 cloudflare.template.yml을 유지하는지 확인하세요.

해당 커밋은 여러분이 의존하고 있던 구성 오류를 수정한 것이었지만, 동시에 해당 헤더를 설정하여 최종 사용자가 자신의 IP 주소를 위장할 수 있는 문제를 허용했을 수도 있습니다.

컨테이너에 다른 어떤 프로세스도 통신할 수 없다고 확신한다면, 소켓 사용이 필요 없는 더 쉬운 방법이 실제로 있습니다. 이 방법에 대한 가이드를 방금 작성했습니다.

@CLOUD_PHT 님의 구성에 대해, 컨테이너 정의에 다음을 추가해야 합니다(이미 run 섹션이 존재한다면 해당 지시문들을 그 섹션에 추가하고, 그렇지 않다면 run 섹션을 추가하세요):

run:
  - file:
      path: /etc/nginx/conf.d/outlets/server/real-ip-header.conf
      chmod: 644
      contents: |
        real_ip_header x-forwarded-for;
  - file:
      path: /etc/nginx/conf.d/outlets/server/set-real-ip-from-host.conf
      chmod: 644
      contents: |
        set_real_ip_from 172.17.0.1;
```\n
다음 내용도 필요할 수 있습니다:
```yaml
  - file:
      # 호스트에서 하나, CloudFlare에서 하나이므로 최소 두 개의 항목이 있으므로 재귀적 처리를 켜야 합니다.
      path: /etc/nginx/conf.d/outlets/server/real-ip-recursive.conf
      chmod: 644
      contents: |
        real_ip_recursive on;

이는 서버에서 실행 중인 nginx가 최종 사용자의 실제 IP를 결정하기 위해 Cloudflare 헤더를 자체적으로 처리하는지(권장됨) 아니면 단순히 자신의 헤더를 위에 추가하는지에 따라 달라집니다. 자세한 내용은 https://meta.discourse.org/t/handling-the-chain-of-trust-of-the-end-users-real-ip/406372#p-2001772-more-than-one-proxy-7를 참조하세요.


다른 독자들에게: 이 지시문은

run:
  - file:
      path: /etc/nginx/conf.d/outlets/server/set-real-ip-from-host.conf
      chmod: 644
      contents: |
        set_real_ip_from 172.17.0.1;

모든 구성에 적합하지 않다는 점을 유의하세요. 이 IP에서 Discourse 컨테이너로의 모든 연결이 신뢰할 수 있는 경우에만 이 작업을 수행하십시오.

구체적으로, IPv6 구성의 알려진 문제는 서버로의 IPv6 연결이 docker에 의해 IPv4를 통해 전달된다는 점입니다. 이 방식은 모든 연결이 호스트의 docker0 IP 주소에서 온 것처럼 보이게 만듭니다. 위의 지시문을 구성에 적용하면 IPv6으로 연결하는 모든 사용자가 마음대로 IP 주소를 위장할 수 있게 됩니다.