Repository navigation
v0.4.17
修正(セキュリティ)
httpのルールで、ルートを選ぶ前にパスと Host を正規化するようにしました(#320)。これまでは生のパスで照合していたので、/%61dmin・//admin・/x/../adminや末尾にドットの付いた Host で、パスごとに付けた認証(basic_auth・oidc・forward_auth)やip_allowを素通りできました。- unreserved の文字のパーセント符号化だけを戻し(
%2Fは区切りにしない)、.・..を解き、//をまとめます。壊れた符号化は 400 です。照合・ミドルウェア・転送先・アクセスログは正規化したパスを使います(変わったときはアクセスログのraw_pathに元のパス)。HTTP/1.1・HTTP/2・HTTP/3 で同じです。 - Host は照合のときだけ小文字にして末尾のドットを落とします(転送先へは送られたまま)。
- 正規化を止める
http.raw_path: true、%2F・%5C・;などを含むパスを断るhttp.strict_path: trueを足しました。 - 認証のミドルウェアが付ける身元のヘッダ(
X-Forwarded-User・oauth2-proxy・Authelia・Authentik の名前など)を、どのルートでもリクエストの最初に消します。認証のないルートに偽の身元が届かなくなります。
- unreserved の文字のパーセント符号化だけを戻し(
- HTTP の接続に待ち時間の上限を付けました(#320、
global.http.timeouts):最初のバイトまで 10 秒、ヘッダまで 30 秒、HTTP/2・HTTP/3 の処理のない接続 180 秒、本文が止まったとき 60 秒(応答の後と gRPC には効かない)。何も送らない接続でファイル記述子を使い切られなくなります。 - API で作るルールが指すファイルを、証明書のストア・ACME の保存先・global の秘密(トークン・制御 API の鍵・CrowdSec・ACME の秘密)・カーネルのファイルシステム(
/proc・/sys・/dev)から分けました(#319、403 protected_file)。/proc/self/environなどをoidc.client_secret_fileに指して、DB のパスワードを含む環境変数を外へ送らせることや、allow_certsの制限を越えてほかの証明書の鍵を使うことができなくなります。allow_certsのあるトークンはファイルのパスを書けません(403 file_not_allowed)。OIDC の client secret のファイルは同じ issuer・client_id でしか使えません(409 secret_reuse)。 - L7 などの URL のポート・ホストが不正なら断るようにしました(#324)。
http://host:65536/やhttp://127.0.0.1:8a/は、これまでポートのない URL として 80/443 につながり、前段の確かめをすり抜けられました。サービス・forward_auth・oidc・CrowdSec・ACME・自動更新の URL を、作るときとつなぐときに同じ規則で読みます。OIDC の discovery が返すエンドポイントも確かめます。
変更(更新の前に確かめてください)
- 正規化していないパスは、正規化してから転送先へ送ります。転送先が生のパスを要るときは
http.raw_path: true(パスでの認証と一緒に使うのは危険です)。 - 認証のミドルウェアのあるルールでは、信頼する前段の認証プロキシが付けた同じ名前の身元のヘッダも消えます。
- 何も送らない接続、ヘッダの遅い接続、処理のない HTTP/2・HTTP/3 の接続、本文が 60 秒止まったリクエストを閉じるようになります(既定を変えたので、設定を省いたときの動きが前の版と違います)。
- OIDC のセッションの cookie を issuer と client_id に結びつけたので、更新の後に OIDC のルールの利用者は一度サインインし直します。
- ポートが不正・userinfo つき・
127.1のような IPv4・空白や\を含む URL、クエリつきのoidc.issuerや CrowdSec の URL を書いた設定は、起動・再読み込み・--check-configで誤りになります(もともと書いたとおりには動いていませんでした)。 - 前の版で API から作った、守るファイルを指すルールは止めずに動かし、
rule.protected_file(warn)を出します。次に変えるときは断られます。
UI: TCP-UDP-rproxy-ui v0.4.9 · Kubernetes: rproxy-gateway v0.4.16
Fixed (security)
httprules now normalise the path and Host before choosing a route (#320). Matching used the raw path, so/%61dmin,//admin,/x/../adminor a Host with a trailing dot could bypass per-path authentication (basic_auth,oidc,forward_auth) andip_allow.- Only unreserved percent-encodings are decoded (
%2Fis not a separator),.and..are resolved and//collapsed; broken encodings get 400. Matching, middlewares, backends and the access log use the normalised path (the original goes toraw_pathin the access log when it differed). The same over HTTP/1.1, HTTP/2 and HTTP/3. - The Host is lowercased and loses a trailing dot for matching only (sent to the backend as received).
- New
http.raw_path: trueturns normalisation off;http.strict_path: truerefuses paths with%2F,%5C,;and similar. - Identity headers that auth middlewares set (
X-Forwarded-User, oauth2-proxy, Authelia and Authentik names, …) are removed at the start of every request on every route, so routes without authentication can no longer receive spoofed identities.
- Only unreserved percent-encodings are decoded (
- HTTP connections have time limits (#320,
global.http.timeouts): 10 s to the first byte, 30 s for the headers, 180 s for idle HTTP/2 and HTTP/3 connections, 60 s for a stalled request body (not after the response started, not for gRPC). Silent connections can no longer exhaust file descriptors. - Files named by API-created rules are kept apart from the certificate store, ACME storage, global secrets (token file, control API key, CrowdSec, ACME secrets) and kernel file systems (
/proc,/sys,/dev) (#319,403 protected_file). Pointingoidc.client_secret_fileat/proc/self/environto send out the environment (including the DB password), or using another certificate's key pastallow_certs, no longer works. Tokens withallow_certscan't name file paths (403 file_not_allowed); an OIDC client secret file can only be used by the same issuer and client_id (409 secret_reuse). - URLs with an invalid port or host are refused (#324).
http://host:65536/orhttp://127.0.0.1:8a/used to be read as URLs without a port and connect to 80/443, slipping past checks in front. Service,forward_auth,oidc, CrowdSec, ACME and self-update URLs are read with the same rules when created and when connecting; endpoints returned by OIDC discovery are checked too.
Changed (check before updating)
- Paths are now normalised before being sent to backends. Use
http.raw_path: trueif a backend needs the raw path (unsafe together with path-based authentication). - On rules with auth middlewares, identity headers with the same names set by a trusted upstream auth proxy are removed too.
- Silent connections, slow headers, idle HTTP/2 and HTTP/3 connections and request bodies stalled for 60 s are now closed (defaults changed, so leaving the settings out behaves differently from the previous release).
- OIDC session cookies are now bound to the issuer and client_id; users of OIDC rules sign in once again after the update.
- Settings with URLs that have an invalid port, userinfo, IPv4 forms like
127.1, spaces or\, or a query inoidc.issueror CrowdSec URLs, now fail at startup, reload and--check-config(they never worked as written). - API rules from earlier releases that point at protected files keep running and log
rule.protected_file(warn); the next change to them is refused.
UI: TCP-UDP-rproxy-ui v0.4.9 · Kubernetes: rproxy-gateway v0.4.16