Skip to content

Allow quotas to be keyed by proxy-forwarded IP address; add support for PROXY protocol#17707

Merged
alexey-milovidov merged 15 commits intomasterfrom
quota-by-x-forwarded-for
Dec 8, 2020
Merged

Allow quotas to be keyed by proxy-forwarded IP address; add support for PROXY protocol#17707
alexey-milovidov merged 15 commits intomasterfrom
quota-by-x-forwarded-for

Conversation

@alexey-milovidov
Copy link
Copy Markdown
Member

@alexey-milovidov alexey-milovidov commented Dec 1, 2020

Changelog category (leave one):

  • New Feature

Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Add support for PROXYv1 protocol to wrap native TCP interface. Allow quotas to be keyed by proxy-forwarded IP address (applied for PROXYv1 address and for X-Forwarded-For from HTTP interface). This is useful when you provide access to ClickHouse only via trusted proxy (e.g. CloudFlare) but want to account user resources by their original IP addresses. This fixes #17268.

@robot-clickhouse robot-clickhouse added doc-alert pr-feature Pull request with new product feature labels Dec 1, 2020
@alexey-milovidov alexey-milovidov force-pushed the quota-by-x-forwarded-for branch from 7c1b810 to c9aa412 Compare December 1, 2020 21:09
@alexey-milovidov
Copy link
Copy Markdown
Member Author

It is similar to keyed quotas, but for key, the last element of X-Forwarded-For is used instead of X-ClickHouse-Quota.

@vitlibar vitlibar self-assigned this Dec 2, 2020
params.quota_key = client_info.quota_key;

/// Extract the last entry from comma separated list of X-Forwarded-For addresses.
/// Only the last proxy can be trusted (if any).
Copy link
Copy Markdown
Member

@vitlibar vitlibar Dec 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still it seems to be more correct to get the first address from X-Forwarded-For if we want to count quota usage for each client IP separately because the client IP is the first address in X-Forwarded-For.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will allow clients to sent arbitrary quota keys (by forging X-Forwarded-For header)... but the purpose of this feature is to ensure per-IP limits similar to keyed_by_ip but with presense of proxy.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the goal is to "unwrap" one level of proxy.

params.quota_key = client_info.quota_key;

/// Extract the last entry from comma separated list of X-Forwarded-For addresses.
/// Only the last proxy can be trusted (if any).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only the last proxy can be trusted?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the last proxy can be trusted, because we can limit access from that proxy with the list of IP networks.
Otherwise user can manually send request with any X-Forwarded-For.

For example, I will limit the list of IP networks for user with this: https://www.cloudflare.com/ips/ and then make quota keyed by X-Forwarded-For.

NONE, /// All users share the same quota.
USER_NAME, /// Connections with the same user name share the same quota.
IP_ADDRESS, /// Connections from the same IP share the same quota.
FORWARDED_IP_ADDRESS, /// Use X-Forwarded-For HTTP header instead of IP address.
Copy link
Copy Markdown
Member

@vitlibar vitlibar Dec 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name FORWARDED_IP_ADDRESS doesn't seem to be clear enough. Maybe it's better to rename it into something like PROXY_ORIGIN_IP_ADDRESS?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The address that proxy server forwards to us... also the analogy with X-Forwarded-For HTTP header.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understood, it just seems that the name FORWARDED_IP_ADDRESS is not very good because it requires to know that HTTP header and doesn't even contain the word PROXY.

@alexey-milovidov alexey-milovidov changed the title Allow quotas to be keyed by proxy-forwarded IP address Allow quotas to be keyed by proxy-forwarded IP address; add support for PROXY protocol Dec 2, 2020
@robot-clickhouse robot-clickhouse added the submodule changed At least one submodule changed in this PR. label Dec 7, 2020
@alexey-milovidov alexey-milovidov merged commit ab10cb4 into master Dec 8, 2020
@alexey-milovidov alexey-milovidov deleted the quota-by-x-forwarded-for branch December 8, 2020 11:48
@azat
Copy link
Copy Markdown
Member

azat commented Dec 8, 2020

Looks like this breaks perf tests (due to port conflict for tcp_with_proxy_port), will fix it in #17907 (and you don't see this in the report since clickhouse-server from upstream does not interpret this new setting)

@azat azat mentioned this pull request Dec 9, 2020
@filimonov filimonov mentioned this pull request May 31, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-feature Pull request with new product feature submodule changed At least one submodule changed in this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support PROXY protocol

4 participants