Skip to content
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

Allow Trusting Multiple Proxy Layers With Wildcards #49168

Closed
wants to merge 3 commits into from

Conversation

kellerjmrtn
Copy link

@kellerjmrtn kellerjmrtn commented Nov 28, 2023

Some Laravel applications are hosted behind multiple layers of proxies that you control. For example, a request may travel through Cloudflare WAF > AWS Load Balancer > Web Server. Currently Laravel allows setting $proxies = '*' to trust all proxies in the TrustProxies middleware: https://laravel.com/docs/10.x/requests#trusting-all-proxies. This only trusts the previous proxy (The AWS Load Balancer in this example), which is probably good default behavior, since trusting more than that would open the application up to IP spoofing.

However, if there are multiple proxies in the chain, this results in the IP of the second-to-last proxy being returned from calls to request()->ip() rather than the client's real IP. You would have X-Forwarded-For: '<Client IP>, <Cloudflare IP>' in your request, and the <Cloudflare IP> would be returned

There used to be a ** option in the fideloper/TrustedProxy package v3, but it was removed in v4 (see fideloper/TrustedProxy#115 (comment) and wintercms/storm@411695b) and was not reintroduced when the package was integrated into the Laravel framework. Presumably, this was removed as it completely removes the point of the trusted proxy system, and allows the user to send whatever they'd like in X-Forwarded-For to spoof their IP, which is no good

This PR allows the wildcard $proxies = '*' to apply to a specified number of proxies, where the default is $layers = 1 (the current default behavior). Using the example, if $layers = 2, both the Load Balancer IP and the Cloudflare IP would be included in the trusted proxies array, allowing request()->ip() to return the true Client IP. This is secure, since you are limiting the trusting to the two proxies which you (presumably) control. I've included tests to verify this behavior

The advantage this provides is allowing applications to be hosted behind multiple proxies without having to use less secure workarounds like $proxies = ['0.0.0.0/0', '2000:0:0:0:0:0:0:0/3'] to correctly track IPs

This change is backwards compatible as it does not change the default behavior of $proxies = '*' trusting only the first proxy. It does, however, remove usages of setTrustedProxyIpAddressesToTheCallingIp. I've left the method in as it's protected, and may be used/called in child classes

@taylorotwell
Copy link
Member

Personally I think if you need something more complicated or robust than what is offered, I would just copy this middleware into your own project and adjust it as needed. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants