Cloudflare와 함께 Discourse 사용: 모범 사례

Cloudflare를 사용한 Discourse 설정

:bookmark: 이 가이드는 Cloudflare를 사용하여 Discourse를 구성하는 방법, 보안 모범 사례 및 문제 해결 팁을 설명합니다.

:person_raising_hand: 필요한 사용자 권한: 관리자

:information_source: 자체 호스팅 설치 환경에서는 콘솔 접근 권한이 필요합니다

요약

Cloudflare는 CDN을 통한 성능 향상, DDoS 보호와 같은 추가 보안 계층, 그리고 HTTPS 지원으로 Discourse 인스턴스를 강화할 수 있습니다. 이 가이드는 최적의 구성을 위한 설정 과정과 모범 사례를 다룹니다.

왜 Discourse에 Cloudflare를 사용해야 하는가

Discourse 인스턴스에 Cloudflare를 사용하면 다음과 같은 주요 이점이 있습니다:

  • 성능: Cloudflare의 CDN은 일반 자산에 대한 전 세계 접근성을 향상시켜 전역적으로 사용자 경험을 개선합니다 (출처)
  • 보안: 다음과 같은 추가 보호 계층을 제공합니다:

:warning: 자체 호스팅 설치 환경의 경우, Cloudflare가 이러한 이점을 제공하지만 설정에 복잡성을 더합니다.

Cloudflare 설정

  1. Cloudflare 기본 개념을 숙지합니다
  2. 설치 지침을 따라 도메인에 Cloudflare를 구성하고 보안, 성능, 신뢰성 이점을 얻습니다

구성 모범 사례

DNS 설정

  • Discourse 인스턴스로 가리키는 DNS 기록이 프록시되도록 확인합니다
  • dash.cloudflare.com/?to=/:account/:zone/dns에서 DNS 설정에 액세스합니다

SSL/TLS 구성

  • 암호화 모드를 "Full (strict)"로 설정합니다
  • dash.cloudflare.com/?to=/:account/:zone/ssl-tls에서 SSL/TLS 설정에 액세스합니다

:warning: SSL/TLS 구성이 올바르지 않으면 리다이렉트 루프가 발생할 수 있습니다

캐싱 구성

  • 캐싱 수준을 "Standard"로 설정합니다
  • dash.cloudflare.com/?to=/:account/:zone/caching/configuration에서 캐싱 설정에 액세스합니다

캐시 규칙

Cloudflare는 최신 Rules 시스템을 권장하기 위해 Page Rules를 중단했습니다. dash.cloudflare.com/?to=/:account/:zone/rules에서 Cache Rules을 사용하여 다음을 생성합니다:

  • community.example.com/session/*에 대해 캐시 수준을 "Bypass"로 설정합니다
  • 수신 URL을 정규화하도록 URL 정규화 설정을 구성합니다

네트워크 설정

dash.cloudflare.com/?to=/:account/:zone/network의 네트워크 설정은 일반적으로 Discourse 기능에 영향을 미치지 않습니다. Discourse는 WebSockets, gRPC 또는 CF-IPCountry / True-Client-IP 헤더를 사용하지 않습니다. 동일한 도메인의 다른 소프트웨어가 특정 구성을 요구하지 않는 한 이러한 설정은 기본값으로 유지할 수 있습니다.

WAF(웹 애플리케이션 방화벽) 설정

Cloudflare 플랜에서 Managed Rules를 지원하는 경우, 다음을 생성합니다:

  1. 게시글 생성/수정 시 WAF 건너뛰기:
(starts_with(http.request.uri.path, "/posts") and http.request.method in {"POST" "PUT"})
  1. Data Explorer 플러그인 사용자의 경우, 관리자 쿼리 시 WAF 건너뛰기:
((http.request.uri.path contains "/admin/plugins/explorer/queries/" or http.request.uri.path contains "/admin/plugins/discourse-data-explorer/queries/") and http.request.method eq "PUT")

두 규칙 모두에 대해:

  • "Skip all remaining rules"를 선택합니다
  • "Log matching requests"를 활성화합니다

:information_source: Business 플랜 이상을 사용 중인 경우, 더 정확한 매칭을 위해 matches 정규식 연산자를 사용할 수 있습니다. 위에서 사용된 starts_withcontains 연산자는 Free와 Pro를 포함한 모든 플랜에서 작동합니다.

dash.cloudflare.com/?to=/:account/:zone/firewall/managed-rules에서 WAF 설정에 액세스합니다

콘텐츠 최적화

dash.cloudflare.com/?to=/:account/:zone/speed/optimization에서 다음을 구성합니다:

  • Brotli 활성화
  • Rocket Loader™ 비활성화

:warning: Rocket Loader™이 활성화되어 있어 사이트 다운 보고가 자주 접수되고 있습니다

자체 호스팅 설치 환경용 추가 구성

IP 주소 전달이 올바르게 이루어지도록 containers/app.yml의 templates 섹션에 다음을 추가합니다:

- "templates/cloudflare.template.yml"

:warning: 템플릿을 추가한 후, 변경 사항이 적용되도록 ./launcher rebuild app으로 컨테이너를 재빌드해야 합니다.

관련 항목: Cloudflare를 어떻게 설정하나요?

지원 리소스

문제 해결

콘텐츠 보안 정책(CSP) 문제

CSP 오류가 발생하는 경우:

  • Rocket Loader가 비활성화되어 있는지 확인합니다
  • 스크립트가 content security policy script src 사이트 설정에 올바르게 추가되었는지 확인합니다

OneBox 기능

OneBox가 차단되는 경우:

  • Super Bot Fight Mode가 활성화되어 있는지 확인합니다
  • “Definitely automated” 설정이 “Managed” 또는 "Block"으로 설정되어 있다면 조정합니다
  • OneBox 사용자 에이전트를 위한 사용자 지정 WAF 규칙 생성을 고려해 봅니다
30개의 좋아요

Good morning,

Thank you for this guide which I followed to the letter but I encounter a problem, each time I activate Cloudflare in my console I get an error with the CSP which displays to me (Refused to execute inline script because it violates the following Content Security Policy directive: "script-src) and after having indicated to me the urls present in my CSP: (Either the ‘unsafe-inline’ keyword, a hash (‘sha256-VCiGKEA…=’), or a nonce (‘nonce-…’) is required to enable inline execution.

I tried looking everywhere but I can’t find a solution other than disabling the proxy which solves my problem?

THANKS.

Can you check if rocket loader is turned off?

Another thing is to check that the scripts are appropriately added to content security policy script src site setting.

If none of these are working out, I suggest reaching out to Cloudflare @ https://community.cloudflare.com/t/using-discourse-with-cloudflare-best-practices/602890.

1개의 좋아요

Thanks for this @nat and @tcloonan

This has been on my list of things to do for a year or two, but I’ve been put off by the age of some of the older threads on this subject :smiley:

Any issues or special things for people using AWS S3 for storage and for backups? :thinking:

Do you still need the cloudflare template in app.yml for true IP addresses or has that changed over the years?

1개의 좋아요

Yes. You do need the cloudflare template. Without it, all traffic will appear to come from cloudflare’s servers rather than the user’s browser IP.

I don’t see it mentioned in the OP, which seems like a glaring omission. How did you infer that you needed it?

2개의 좋아요

Hi! Been around since 2014 (some years mostly silent) but have been working our getting our community migrated over since 2020 with a custom importer, and we are working on the second version of our in-house plugin to insert and enable bbob as a bbcode engine into Discourse. You can follow our progress here: GitHub - RpNation/bbcode: RpNation's Official BBCode Implementation for Discourse · GitHub

I’ve been breathing this software for a bit now. We do use Cloudflare, so I’ve been re-researching what if any issues it has with discourse, since we are now at the stage where I can start worrying about less vital things that are not considered blockers.

@nat Could you add an edit about the template for self-hosted instances!

4개의 좋아요

Done, thank you both for pointing this out!

4개의 좋아요

Thank you very much! That was probably also the reason why my site was suddenly no longer accessible. I must have played with the Cloudflare settings a bit too much.

Since my old domain provider only supported DNSSec inadequately & incorrectly, I had to look for something new. That’s when Cloudflare came to mind. The free plan is completely sufficient for me. It’s a shame that the tariffs don’t even scale reasonably to the requirements.

2개의 좋아요

Is it adding to this location?

1개의 좋아요

Just for accuracy, the query for the WAF exclusion is:

(http.request.uri.path eq "/posts(/[0-9]+)?" and http.request.method in {"POST" "PUT"})

You can copy-paste it if you click on the Edit expression on the left instead of using the form selection.

Noticed today as I updated and suddenly half the forum wasn’t working due to Auto Minify :weary:

Edit: just noticed this is a wiki post. Silly me, I have edited the initial post.

4개의 좋아요

SSL/TLS encryption mode Full (strict). Will there be a problem if it is not closed? Won’t automatic SSL be defined anyway?

Just to add to this, seems the OneBox functionality is being blocked when Super Bot Fight Mode is on and the setting Definitely automated is set to Managed or block..

You can get around this by setting up a custom WAF rule for the Onebox user agent but perhaps there is a more secure way of doing this?

Related to

this part might need some better wording:

@supermathie Suggestion:

you will want to add the following line to the end of your templates section in containers/app.yml.

as illustrated in Using Discourse with Cloudflare: Best Practices - #11 by shawa

At best, a link to a general how-to about templates in server configuration could be provided also, which I was not able to find at first sight.

Cloudflare에서 AI 봇을 차단하는 것을 권장합니다. 보안 → 봇 → AI 봇 차단 경로에서 이 설정을 찾을 수 있습니다.

AI 봇들이 매일 3만~4만 페이지뷰로 제 사이트를 마구잡이로 공격하고 있었습니다. 이 필터를 활성화한 후 AI 봇 트래픽이 크게 감소했습니다.

5개의 좋아요

위의 코드는 다음과 같이 변경되어야 합니다:

 - "templates/cloudflare.template.yml"

감사합니다,
Major

2개의 좋아요

클라우드플레어에서 WebSocket 지원을 활성화해야 한다는 말이 정말 사실인가요?

저희는 몇 년 동안 WebSocket를 사용하지 않고도 잘 운영해 왔습니다. 그리고 포럼에서 찾을 수 있는 정보에 따르면, Discourse는 WebSocket를 전혀 사용하지 않는 것으로 보입니다.

이걸 해야 하는지 모르겠어요

맞습니다. 우리는 Websockets를 사용하지 않는다고 생각합니다.

해당 부분을 제거했으며, 위 사용자의 템플릿 스니펫도 업데이트했습니다.

2개의 좋아요

이와 관련하여, 전체 네트워크 설정은 Discourse에 대해 관련이 없다고 생각합니다:

  • IPv6 호환성은 더 이상 비활성화할 수 없으며, 물론 Discourse는 이에 의존하지 않고 IPv4 전용 시스템에서도 완벽하게 실행될 수 있습니다.
  • IP Geolocation은 요청에 CF-IPCountry 헤더를 추가하지만, 이는 Discourse에서 사용되지 않습니다. Discourse는 자체의 (선택 사항인) MaxMind 기능을 사용합니다.
  • Network Error Logging은 브라우저가 오류를 보고할 수 있는 Report-To 응답 헤더를 추가합니다. 그러나 이 기능은 비추천(deprecated) 상태이며, 모든 Cloudflare 플랜에서 이 기능을 활성화할 수 있지만 실제 보고서를 확인하기 위한 대시보드 요소는 Enterprise 플랜에서만 사용할 수 있습니다. 따라서 이 경우 일부 구형 브라우저에 대해서는 단순히 프라이버시 퇴보와 네트워크 오버헤드만 초래할 수 있습니다.
  • Onion Routing은 Tor 네트워크에서 오는 요청의 프라이버시를 강화합니다. Discourse는 이를 신경 쓰거나 인식하지도 않습니다.
  • Pseudo IPv4 기능은 IPv4 주소만 지원하는 소프트웨어(예: 오래된 분석 도구 등)를 호스트가 실행하는 경우 필요할 수 있습니다. Cloudflare의 프록시 헤더(예: Cf-Connecting-IP 또는 구성에 따라 다른 헤더)를 조정하여 클라이언트의 실제 IPv6 주소 대신 더 고유한 IPv4 주소를 사용할 수 있으며, 이는 클라이언트->Cloudflare 요청에 대한 IPv6 지원이 더 이상 비활성화될 수 없다는 사실을 우회하기 위한 것입니다. 다시 말하지만, Discourse는 이를 신경 쓰지 않습니다. 예를 들어 GeoIP 감지에 문제가 될 수는 있지만, 이 기능은 기본적으로 비활성화되어 있으며, 관리자는 실행 중인 소프트웨어가 엄격하게 요구하는 경우에만 이 기능을 활성화하고, 실제 클라이언트 IP가 아닌 부작용을 받아들여야 합니다. 또한 이 기능을 가짜 IPv4 주소만 포함하는 새 헤더를 추가하도록 구성할 수도 있으며, 이 경우 분석(또는 기타) 요청은 필요한 곳에서 클라이언트 IP 헤더를 다시 작성할 수 있고, Discourse에 대한 요청은 영향을 받지 않습니다. 어쨌든, 일반적인 Discourse 기능 측면에서 이 기능은 관련이 없습니다.
  • True-Client-IP 헤더는 CF-Connecting-IPX-Forwarded-For 외에 이 헤더만 추가합니다. Discourse는 이를 사용하지 않으며, Discourse 설정 템플릿도 CF-Connecting-IP를 대신 사용합니다. 따라서 효과는 없습니다.
  • gRPC는 Discourse에서 사용되지 않지만, Cloudflare를 통해 gRPC 요청을 전달하도록 활성화하는 것이 해가 되지는 않으며, WebSockets와 마찬가지입니다. 둘 다 동일한 Cloudflare 도메인에서 실행되는 다른 소프트웨어에 필요할 수 있습니다.
  • 최대 업로드 크기 100 MB는 기본값이자 최소값입니다. 더 큰 업로드 크기는 Business 또는 Enterprise 플랜이 필요하며, Cloudflare가 더 큰 업로드를 허용하더라도 Discourse가 깨지지 않습니다.

효과가 있을지 확신이 없는 유일한 것은 Response Buffering입니다. 그리고 이는 Enterprise 전용 기능이므로 테스트할 수 없습니다. 하지만 클라이언트가 패킷이 CF 엣지에서 도착하는 대로 스트리밍되는지, 아니면 엣지에서 완료된 후 한 번에 전송되는지 신경 쓸 것이라고는 상상할 수 없습니다. 캐시된 데이터(Cloudflare에서 캐시된 것을 의미)의 경우, 이는 어쨌든 항상 수행되며, 적어도 문제는 발생하지 않습니다. 이 기능은 캐시되지 않은 데이터에만 영향을 미칩니다.

결론적으로, 저는 이 전체 “Network settings” 섹션을 Cloudflare 기능에 관련이 없는 것으로 제거하겠습니다. 다만 다른 소프트웨어가 특정 설정을 요구하거나 관리자가 특정 방식으로 선호할 수 있으므로, Discourse는 어떤 경우에도 기능이 유지됨을 알아두어야 합니다.

1개의 좋아요