diff --git a/CHANGELOG.md b/CHANGELOG.md
index abc14166..19703bcb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@
- [#2755](https://github.com/oauth2-proxy/oauth2-proxy/pull/2755) feat: add X-Envoy-External-Address as supported header (@bjencks)
- [#1985](https://github.com/oauth2-proxy/oauth2-proxy/pull/1985) Add support for systemd socket (@isodude)
- [#2300](https://github.com/oauth2-proxy/oauth2-proxy/pull/2300) Add fix for websocket path rewrite (@rekup)
+- [#2821](https://github.com/oauth2-proxy/oauth2-proxy/pull/2821) feat: add CF-Connecting-IP as supported real ip header
# V7.7.1
diff --git a/docs/docs/configuration/overview.md b/docs/docs/configuration/overview.md
index 32ea71ad..511e2b59 100644
--- a/docs/docs/configuration/overview.md
+++ b/docs/docs/configuration/overview.md
@@ -199,7 +199,7 @@ Provider specific options can be found on their respective subpages.
| flag: `--htpasswd-file`
toml: `htpasswd_file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | |
| flag: `--htpasswd-user-group`
toml: `htpasswd_user_groups` | string \| list | the groups to be set on sessions for htpasswd users | |
| flag: `--proxy-prefix`
toml: `proxy_prefix` | string | the url root path that this proxy should be nested under (e.g. /`/sign_in`) | `"/oauth2"` |
-| flag: `--real-client-ip-header`
toml: `real_client_ip_header` | string | Header used to determine the real IP of the client, requires `--reverse-proxy` to be set (one of: X-Forwarded-For, X-Real-IP, X-ProxyUser-IP, or X-Envoy-External-Address) | X-Real-IP |
+| flag: `--real-client-ip-header`
toml: `real_client_ip_header` | string | Header used to determine the real IP of the client, requires `--reverse-proxy` to be set (one of: X-Forwarded-For, X-Real-IP, X-ProxyUser-IP, X-Envoy-External-Address, or CF-Connecting-IP) | X-Real-IP |
| flag: `--redirect-url`
toml: `redirect_url` | string | the OAuth Redirect URL, e.g. `"https://internalapp.yourcompany.com/oauth2/callback"` | |
| flag: `--relative-redirect-url`
toml: `relative_redirect_url` | bool | allow relative OAuth Redirect URL.` | false |
| flag: `--reverse-proxy`
toml: `reverse_proxy` | bool | are we running behind a reverse proxy, controls whether headers like X-Real-IP are accepted and allows X-Forwarded-\{Proto,Host,Uri\} headers to be used on redirect selection | false |
diff --git a/pkg/apis/options/options.go b/pkg/apis/options/options.go
index 4dff5c62..2982ca74 100644
--- a/pkg/apis/options/options.go
+++ b/pkg/apis/options/options.go
@@ -116,7 +116,7 @@ func NewFlagSet() *pflag.FlagSet {
flagSet := pflag.NewFlagSet("oauth2-proxy", pflag.ExitOnError)
flagSet.Bool("reverse-proxy", false, "are we running behind a reverse proxy, controls whether headers like X-Real-Ip are accepted")
- flagSet.String("real-client-ip-header", "X-Real-IP", "Header used to determine the real IP of the client (one of: X-Forwarded-For, X-Real-IP, X-ProxyUser-IP, or X-Envoy-External-Address)")
+ flagSet.String("real-client-ip-header", "X-Real-IP", "Header used to determine the real IP of the client (one of: X-Forwarded-For, X-Real-IP, X-ProxyUser-IP, X-Envoy-External-Address, or CF-Connecting-IP)")
flagSet.StringSlice("trusted-ip", []string{}, "list of IPs or CIDR ranges to allow to bypass authentication. WARNING: trusting by IP has inherent security flaws, read the configuration documentation for more information.")
flagSet.Bool("force-https", false, "force HTTPS redirect for HTTP requests")
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth2/callback\"")
diff --git a/pkg/ip/realclientip.go b/pkg/ip/realclientip.go
index d2d941dd..8bfc7ea3 100644
--- a/pkg/ip/realclientip.go
+++ b/pkg/ip/realclientip.go
@@ -16,7 +16,9 @@ func GetRealClientIPParser(headerKey string) (ipapi.RealClientIPParser, error) {
case http.CanonicalHeaderKey("X-Forwarded-For"),
http.CanonicalHeaderKey("X-Real-IP"),
http.CanonicalHeaderKey("X-ProxyUser-IP"),
- http.CanonicalHeaderKey("X-Envoy-External-Address"):
+ http.CanonicalHeaderKey("X-Envoy-External-Address"),
+ // Cloudflare specific Real-IP header
+ http.CanonicalHeaderKey("CF-Connecting-IP"):
return &xForwardedForClientIPParser{header: headerKey}, nil
}
diff --git a/pkg/ip/realclientip_test.go b/pkg/ip/realclientip_test.go
index 8e053f97..c56e0170 100644
--- a/pkg/ip/realclientip_test.go
+++ b/pkg/ip/realclientip_test.go
@@ -22,6 +22,7 @@ func TestGetRealClientIPParser(t *testing.T) {
{"X-REAL-IP", "", forwardedForType},
{"x-proxyuser-ip", "", forwardedForType},
{"x-envoy-external-address", "", forwardedForType},
+ {"cf-connecting-ip", "", forwardedForType},
{"", "the http header key () is either invalid or unsupported", nil},
{"Forwarded", "the http header key (Forwarded) is either invalid or unsupported", nil},
{"2#* @##$$:kd", "the http header key (2#* @##$$:kd) is either invalid or unsupported", nil},