-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trust X-Forwarded-For from the right to the left #162
Conversation
In modosc#149 we got the extremely helpful `Request#cloudflare?` method which can assist with checking if a request has been proxied through Cloudflare. The method checks that there's an unbroken chain of trust from the `REMOTE_ADDR` (if it exists) through forwarded IPs that only includes trusted internal proxies and Cloudflare IP addresses. Each proxy in the chain is supposed to append the IP of the traffic it received to the *right side* of `X-Forwarded-For`. This means that after evaluating `REMOTE_ADDR` we should be looking at addresses in `X-Forwarded-For` starting on the right side, not on the left. https://github.com/modosc/cloudflare-rails/blob/311875eef57862ecf050fb87415c56ea4823486a/lib/cloudflare_rails/check_trusted_proxies.rb#L23-L25 This ordering means that if a request has the original client as the first address in `X-Forwarded-For` that we'll incorrectly reject it. It also means that an attacker could craft a forged `X-Forwarded-For` that starts with a Cloudflare IP and smuggle in a request that appears to be valid to the method's logic. The fix here is to continue to look at `REMOTE_ADDR` first but then to look at `X-Forwarded-For` in right-to-left order until we run out of trusted IP addresses (whether internal proxies or Cloudflare IPs). Fix modosc#161
```ruby | ||
config.cloudflare.expires_in = 12.hours # default value | ||
config.cloudflare.timeout = 5.seconds # default value | ||
``` | ||
|
||
## Blocking non-Cloudflare traffic | ||
You can use the `#cloudfront?` method from this gem to block all non-Cloudflare traffic to your application. Here's an example of doing this with [`Rack::Attack`](https://github.com/rack/rack-attack): | ||
|
||
You can use the `#cloudflare?` method from this gem to block all non-Cloudflare traffic to your application. Here's an example of doing this with [`Rack::Attack`](https://github.com/rack/rack-attack): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo here.
- `REMOTE_ADDR: CloudFlare` | ||
- `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: CloudFlare` | ||
- `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: CloudFlare,trusted_proxy2` | ||
- `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: untrusted,CloudFlare` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to show the expectations.
@@ -139,11 +144,6 @@ | |||
it 'returns false if the request has a trusted REMOTE_ADDR but did not originate from CloudFlare' do | |||
expect(Rack::Request.new('REMOTE_ADDR' => '10.1.1.1', 'HTTP_X_FORWARDED_FOR' => '1.2.3.4')).not_to be_cloudflare | |||
end | |||
|
|||
it 'returns false if the request has a trusted REMOTE_ADDR and an untrusted proxy before CloudFlare' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This spec should be true, moved it up and reworded.
@@ -122,9 +122,14 @@ | |||
'HTTP_X_FORWARDED_FOR' => '10.2.2.2,197.234.240.1')).to be_cloudflare | |||
end | |||
|
|||
it 'returns true if the request originated from CloudFlare via one trusted proxy and one untrusted upstream IP' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This spec should be false, reworded and moved it down.
Thanks for the quick review and merge @modosc! |
In #149 we got the extremely helpful
Request#cloudflare?
method which can assist with checking if a request has been proxied through Cloudflare. The method checks that there's an unbroken chain of trust from theREMOTE_ADDR
(if it exists) through forwarded IPs that only includes trusted internal proxies and Cloudflare IP addresses.Each proxy in the chain is supposed to append the IP of the traffic it received to the right side of
X-Forwarded-For
. This means that after evaluatingREMOTE_ADDR
we should be looking at addresses inX-Forwarded-For
starting on the right side, not on the left.cloudflare-rails/lib/cloudflare_rails/check_trusted_proxies.rb
Lines 23 to 25 in 311875e
This ordering means that if a request has the original client as the first address in
X-Forwarded-For
that we'll incorrectly reject it. It also means that an attacker could craft a forgedX-Forwarded-For
that starts with a Cloudflare IP and smuggle in a request that appears to be valid to the method's logic.The fix here is to continue to look at
REMOTE_ADDR
first but then to look atX-Forwarded-For
in right-to-left order until we run out of trusted IP addresses (whether internal proxies or Cloudflare IPs).Fix #161