Discourse 세션 쿠키 (400 Request Header Or Cookie Too Large)

왜 Discourse의 쿠키 크기가 이렇게 큰가요? 그럴 만한 이유가 있나요? 크기를 줄이는 방법이 있을까요?

Discourse 관리자 대시보드를 탐색하던 중 /sidekiq/retries에서 갑자기 400 Bad Request 오류가 반환되었습니다.

400 Bad Request
Request Header Or Cookie Too Large

요청을 확인해 보니, 제 브라우저가 Discourse 서버로 거대한 쿠키 헤더를 보내고 있었습니다. 왜일까요?

Cookie: _t=403b8203003bdaf522679e0b6c17605f; rack.session=BAh7C0kiD3Nlc3Npb25faWQGOgZFVG86HVJhY2s6OlNlc3Npb246OlNlc3Np%0Ab25JZAY6D0BwdWJsaWNfaWRJIkU4NjY1Y2Y3MjU4OGYzZjk3MDUyMDdhNzhh%0ANzc4OGZlZTRhNzFkY2JjMzA4NDAyNjY3MWMwNmFhYzc2Zjg0NWIyBjsARkki%0AEF9jc3JmX3Rva2VuBjsARkkiMW9KNk83S1B5ZUVaR0I2WnBxckxISzNxbEla%0AdGRyVXNCUnc3d2JiaVorVmM9BjsARkkiFnNlY3VyZV9zZXNzaW9uX2lkBjsA%0AVEkiJWM3YWJjYTk3OTRlNTExNTllZWUyMTBkYmVkNDgzNDc4BjsARkkiCmZs%0AYXNoBjsAVHsHSSIMZGlzY2FyZAY7AFRbAEkiDGZsYXNoZXMGOwBUewZJIgxy%0AZWZlcmVyBjsAVCJPaHR0cHM6Ly9kaXNjb3Vyc2Uub3BlbnNvdXJjZWVjb2xv%0AZ3kub3JnL3UvbWFsdGZpZWxkMC9tZXNzYWdlcy9ncm91cC9hZG1pbnNJIglj%0Ac3JmBjsARkkiMVRuUHJ6TTMzUHZqcG9oditwdTRyem9HeDUxQnAwL0psci9z%0AYkFZWkpxdkU9BjsARkkiDXRyYWNraW5nBjsARnsGSSIUSFRUUF9VU0VSX0FH%0ARU5UBjsAVEkiLTk3MDJkMjYxMmJlZmM5N2U4YTIzMDVkNjU0Y2IwOThmMmQ4%0AYTI1NTUGOwBG%0A--e602081dddcd88bdb269034e7acb8c582665be0e; _forum_session=V2dWY0FGVGhsMDVtcmdmNVdicXpJVkxnVC9vUWpkeVdpSHRIYWZaVVhVZDUxcFlRdTh4bHFTQVRRcUpGR3pMRGZ1M3NGeENzUloreGdEWEtQS2Z2WDJKNFZUeXRjNXlTTTRHVzJsQzBORzVuSW9NNHg3UHhwNzdUNFlCNGVvcytkSjA1b0d3NlM3czNlTlFxMEloQmNOYzMxTm5mYW4zaWlMSkpxWXZiZDlBRFJnR3dxTkphM0ZtZmk4bGswcUdzYm94b3pkUk0zTG5sMjhqNkxYMnZqMjJPYkhzMGFLM2JWZzBCRXpFa2wyZm1HbUl3REVzd3c5MmhRMG5YMkFJV0t6Z2ZPRlI2bVpOQWJlZWJQd2pyclEvdmVmWUlsYkxyU0EzcDFaZkRpOU14SVptMk01TjZtZlNXa2VUQnFaaGZpNDlaQVBnY0RCS2ZlbVBiQWt3S2lSeHcvY0g2WUlXOTRLejh2dVhhcDFoRXVobUdRMnJvcjhtRTkxZjZCYXM1eDd2NU1rZ3duRy83VVhVSG5Ua3BIOTJoQ1orY2dlMjh2M0Fuc0lwb3p3ckVtaXhxaDkxT2E1YnEvbnBWTVlCaXd4Q2h6eTd5Ty84WUYzeUVFbE9KSXhadXZ4aUw1TmVoSEE0cW9YSHA3VTJoK3NtdktrL09qcDVxMnR5bFhhUmU1dDMzT0ZBUGxBRXBZVHB5WlNtODM2YzBsOVRkc3RpMmFFSW5COEhyRjFTY2ZCZk5VbUpYN2JzYlh6SGNGWEs2dWhQUkJnMmd4K3ZJQUFkQThwa2tOMnI3Vi9qMFo5RE5XWWxxRXFTTTNmRnJKU294aStKZFJ4NHRDTGh4WXR1Z3F5QWU3ZkMxTXBpMzcvYTd5QkRwajNjcDF6SWdFSkdqNDJlMk0vYW1mODNEdDhZSk9jbzRPRHNhZUYzNjVOWkErbVJSNG82VnhRL0FFRUtWbE1uQWFPa0JqQUFmZ21iL0YvSFIrM1dlSDNvPS0tK1pMRzNmRjA4L3c4VTkrVEllYmNQZz09--325ca2e886afaefffeb6174c99776f91fefd4292

위 Discourse 쿠키 문자열은 1,962자 길이를 가집니다!

비교하자면, 제 Mediawiki 사이트로 전송되는 쿠키 헤더는 사용자 이름, 사용자 ID, 세션 ID를 포함하여 122자 길이입니다.

Mediawiki의 세션 ID는 32자 길이인데, Discourse에는 두 개의 세션 ID가 있는 것으로 보입니다. rack.session은 813자, _forum_session은 1,075자 길이입니다. 단순한 uid가 왜 이렇게 길어야 하는지 이해하는 데 도움을 주십시오. Discourse를 더 짧은 세션 uid를 사용하도록 구성할 수 있나요? 그런 요청이 합리적인가요?

그 문자열에는 무엇이 저장되어 있나요? 더 작게 만드는 것이 가능한가요?

구체적으로, Discourse 소프트웨어의 어떤 구성 요소에서 rack.session이 사용되나요? 그리고 _forum_session은 무엇에 사용되나요?

물론 nginx 설정 한도를 높이는 것만으로도 해결할 수 있지만, 증가시킬 강력한 요구 사항이 없는 한 한도를 합리적으로 낮게 유지하고 싶습니다.

세션 쿠키 감사(auditing)를 지원하며, 가능하면 기본적으로 자동 만료되는 Redis 기반 세션을 사용하는 것으로 전환하는 것을 제안합니다. 어쨌든 그것이 더 나은 방법입니다. @david, 이 부분에 대해 어떤 의견이 있으신가요?

공식 설치 버전을 사용하는 사용자라면 문제가 되지 않아야 하며, 잘못 구성된 프록시를 사용하는 사람들에게만 해당되는 문제일까요?

또한 HTTP/2 헤더 압축 기능 덕분에 이 헤더들은 사용자의 전체 방문 기간 동안 단 한 번만 업로드됩니다.

상황에 따라 다릅니다. 세션을 많이 사용하는 플러그인은 영향을 받을 수 있으며, 이는 위생적인 측면도 중요합니다. 이러한 비밀 정보를 클라이언트에 암호화해서 저장하는 것보다 서버에 보관하는 것이 더 좋습니다.

이 조정(security)은 의도적으로 수행된 것입니다. “잘못 구성된” 프록시 때문이 아닙니다. 다음 nginx 지시어들을 낮추는 조정은 nginx 강화(hardening) 작업의 일환으로(가용성, 레이트 리미팅, DOS 등 대응을 위해) 흔히 수행됩니다:

limit_conn_zone
limit_conn
limit_req_zone
client_body_timeout
client-header_timeout
ssl_*
add_header # SAMEORIGIN/XSS-Protection/CORS/CSP
client_body_buffer_size
client_header_buffer_size
large_client_header_buffers
client_max_body_size

우리가 nginx 설정에서 사용하는 설정은 기존 모든 사이트에서 정상적으로 작동합니다. 여기서는 Discourse가 불필요한 클라이언트 데이터를 쿠키에 저장하고 있는 것으로 보입니다. 제 생각에는 쿠키에는 서버가 서버 측에서 해당 데이터에 액세스할 수 있도록 사용하는 고유 식별자 몇 개만 저장되어야 합니다.

Sam, 감사합니다. "기본적으로 redis 사용을 전환"한다고 하셨는데, 이는 현재 설정 변경만으로 세션 쿠키에 저장된 데이터를 redis로 옮길 수 있다는 제안인가요? 아니면 이 데이터를 세션 쿠키에서 서버로 옮기는 것은 반드시 코드 변경이 필요하다는 의미인가요?

아니요, 코드 변경이 필요합니다.

헤더 10KB가 왜 문제가 되나요? 압축되어 있지 않나요? 헤더 10KB가 문제라면 HTML 페이로드 10KB는 왜 허용되나요?

참고: Discourse를 정상적으로 작동시키기 위해 강화된 nginx 설정의 large_client_header_buffers 지시문을 오버라이드해야 했습니다.

구체적으로, 다른 사이트들의 nginx 설정에는 모두 large_client_header_buffers 2 1k를 사용하고 있습니다. 그러나 이 설정은 /admin/reports/bulk?XYZ 경로에서 414 Request-URI Too Large 오류를 유발합니다 – 여기서 XYZ는 실제로 1,019자 길이의 문자열입니다!

이 문제는 Discourse nginx 설정의 server{} 블록에 large_client_header_buffers 4 8k;를 설정하여 수정했습니다. 이 설정은 전역 지시문을 오버라이드하여 Discourse에 대해 해당 지시문의 기본값으로 복원합니다.

강화된 웹 서버, 네트워크 방화벽, 웹 애플리케이션 방화벽을 통한 Discourse 설치 간의 상호 운용성을 개선하기 위해, Discourse 개발팀에게 이러한 긴 쿼리 스트링에 대해 POST 메서드 사용을 고려해 주시기를 촉구합니다.

매우, 매우 제한적인 사용 사례입니다. 관리자 전용이죠.

백엔드 엔지니어가 아닌 사람이 이 문제를 해결하려면 어떻게 해야 하나요?

지난 한 달간 Webflow 포럼에서 이 오류에 대한 보고가 많이 접수되고 있습니다. 방문자에게 쿠키/캐시를 지우거나 시크릿 모드를 사용하도록 권유하는 방법은 효과가 있었지만, 이상적이라고 보기는 어렵습니다.

저희 Discourse 인스턴스에서 이 문제를 수정하는 방법에 대한 조언을 주시면 감사하겠습니다.

예시를 링크해 주실 수 있나요? OP의 문제는 Discourse를 자체 호스팅하는 것에 관한 것이므로, 링크하신 호스팅된 인스턴스에 어떻게 영향을 미칠 수 있는지 이해가 되지 않습니다.