Allow Trusting Multiple Proxy Layers With Wildcards #49168
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 theTrustProxies
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 haveX-Forwarded-For: '<Client IP>, <Cloudflare IP>'
in your request, and the<Cloudflare IP>
would be returnedThere 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 inX-Forwarded-For
to spoof their IP, which is no goodThis 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, allowingrequest()->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 behaviorThe 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 IPsThis change is backwards compatible as it does not change the default behavior of
$proxies = '*'
trusting only the first proxy. It does, however, remove usages ofsetTrustedProxyIpAddressesToTheCallingIp
. I've left the method in as it's protected, and may be used/called in child classes