Skip to content

v0.4.17

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:31
· 14 commits to master since this release
9238562

修正(セキュリティ)

  • 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 の名前など)を、どのルートでもリクエストの最初に消します。認証のないルートに偽の身元が届かなくなります。
  • 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)

  • http rules now normalise the path and Host before choosing a route (#320). Matching used the raw path, so /%61dmin, //admin, /x/../admin or a Host with a trailing dot could bypass per-path authentication (basic_auth, oidc, forward_auth) and ip_allow.
    • Only unreserved percent-encodings are decoded (%2F is 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 to raw_path in 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: true turns normalisation off; http.strict_path: true refuses 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.
  • 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). Pointing oidc.client_secret_file at /proc/self/environ to send out the environment (including the DB password), or using another certificate's key past allow_certs, no longer works. Tokens with allow_certs can'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/ or http://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: true if 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 in oidc.issuer or 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