maltfield
(Michael Altfield)
2019 年 12 月 28 日午後 4:48
1
Discourse のクッキーがなぜこれほど大きいのでしょうか?何か理由があるのでしょうか?サイズを縮小する方法はありますか?
Discourse の管理ダッシュボードを調べていたら、突然 /sidekiq/retries から 400 Bad Request エラーが返ってきました。
400 Bad Request
Request Header Or Cookie Too Large
リクエストを確認すると、確かにブラウザが Discourse サーバーに非常に巨大な Cookie ヘッダーを送信していました。なぜでしょうか?
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 には 2 つのセッション ID のようです:rack.session は 813 文字、_forum_session は 1,075 文字です。単純な uid がなぜこれほど長くする必要があるのか、理解を手伝っていただけますか?Discourse を設定してより短いセッション uid を使用することは可能でしょうか?そのようなリクエストは意味がありますか?
その文字列には何が格納されているのでしょうか?小さくすることは可能でしょうか?
具体的に、Discourse ソフトウェアのどのコンポーネントが rack.session を使用しているのでしょうか?また、_forum_session は何に使用されるのでしょうか?
もちろん nginx の設定制限を引き上げることはできますが、強く必要とされない限り、可能な限り低く保ちたいと考えています。
sam
(Sam Saffron)
2019 年 12 月 30 日午前 2:52
2
セッションクッキーの監査を検討し、より良い自動有効期限付きの Redis ベースのセッションをデフォルトで使用する移行を提案します。@david についてのご意見はありますか?
# frozen_string_literal: true
# session that is not stored in cookie, expires after 1.hour unconditionally
class SecureSession
def initialize(prefix)
@prefix = prefix
end
def self.expiry
@expiry ||= 1.hour.to_i
end
def self.expiry=(val)
@expiry = val
end
def set(key, val, expires: nil)
expires ||= SecureSession.expiry
Discourse.redis.setex(prefixed_key(key), expires.to_i, val.to_s)
true
This file has been truncated. show original
Falco
(Falco)
2019 年 12 月 30 日午前 3:41
3
公式のインストール方法を利用している方であれば問題ないはずです。設定が不適切なプロキシを利用している方のみが対象ですね?
また、HTTP/2 のヘッダー圧縮により、これらのヘッダーはユーザーの訪問全体を通じて一度だけ送信されます。
sam
(Sam Saffron)
2019 年 12 月 30 日午前 3:48
4
状況によります。セッションを多用するプラグインは影響を受ける可能性があります。また、これはセキュリティ上の衛生面に関わる問題でもあります。暗号化してクライアント側に保存するよりも、サーバー側に機密情報を保持する方が望ましいからです。
maltfield
(Michael Altfield)
2019 年 12 月 30 日午前 8:35
6
ええと、このチューニングはセキュリティ目的で意図的に行われたものであり、「設定が不適切な」プロキシの問題ではありません。nginx のハードニング(可用性、レート制限、DoS 対策などに対応するため)の一環として、以下の nginx ディレクティブの値を下げることが一般的に行われています:
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 が不要なクライアントデータをクッキーに保存している点です。個人的には、クッキーに保存されるべきは、サーバー側でそのデータにアクセスするために必要な少数の一意の識別子だけであるべきだと考えています。
サム、ありがとうございます。「デフォルトで Redis を使用する」というのは、セッションクッキーに保存されているデータを設定変更だけで Redis へ移行できることを意味しているのでしょうか?それとも、セッションクッキーからサーバー側へデータを移行するには、コード変更が必須になるのでしょうか?
sam
(Sam Saffron)
2019 年 12 月 30 日午前 9:29
7
いいえ、コードの変更が必要です
10k のヘッダーがなぜ問題なのでしょうか?それらは圧縮されています。10k のヘッダーが問題なら、なぜ 10k の HTML ペイロードは許容されるのでしょうか?
maltfield
(Michael Altfield)
2020 年 4 月 23 日午前 9:49
9
maltfield:
以下の nginx ディレクティブの値を下げることは、nginx の強化(可用性、レート制限、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
注:Discourse を動作させるために、強化済みの nginx 設定の large_client_header_buffers ディレクティブをオーバーライドする必要がありました。
具体的には、他のすべてのサイトの nginx 設定では large_client_header_buffers 2 1k を使用しています。しかし、これにより /admin/reports/bulk?XYZ(ここで XYZ は実際には 1,019 文字の長さです)から 414 Request-URI Too Large エラーが発生しました。
これは、Discourse の nginx 設定の server{} ブロック内で large_client_header_buffers 4 8k; と設定することで解決しました。これによりグローバルディレクティブがオーバーライドされ、Discourse に対してディレクティブがデフォルト値に戻されました。
一般的な強化済み Web サーバー、ネットワークファイアウォール、Web アプリケーションファイアウォールを介した Discourse インストールの相互運用性を向上させるため、Discourse 開発者には、このような長いクエリ文字列に対して POST を使用することを検討することを強く推奨します。
maltfield:
/admin/reports/bulk?XYZ
それは非常に限定的なユースケースです。管理者に特化したものです。
バックエンドエンジニアではないのですが、この修正方法はどのようなものでしょうか?
過去1ヶ月間、Webflowフォーラム でこのエラーに関する多くの報告を受けています。訪問者にCookie/キャッシュをクリアするか、シークレットモードを使用するように推奨することで解決していますが、理想的ではありません。
Discourseのインスタンスでこれを修正するためのアドバイスをいただけると幸いです。
Falco
(Falco)
2022 年 10 月 20 日午後 11:14
12
例をリンクしていただけますか?OPの問題はDiscourseのセルフホスティングに関するものなので、あなたがリンクしたようなホスティングインスタンスにどのように影響するか理解できません。