serversideup / docker-php

🐳 Production-ready Docker images for PHP. Optimized for Laravel, WordPress, and more!
https://serversideup.net/open-source/docker-php/
GNU General Public License v3.0
1.74k stars 119 forks source link

Nginx realip module breaks Laravel's TrustProxies middleware #288

Closed balthild closed 5 months ago

balthild commented 8 months ago

Affected Docker Images

serversideup/php:beta-8.3-fpm-nginx

However, I think the issue may affects all images because the nginx configuration entry causing this has not changed for years.

Docker Labels of the affected images

{"org.opencontainers.image.authors":"Jay Rogers (@jaydrogers)","org.opencontainers.image.description":"Supercharge your PHP experience. Based off the offical PHP images, serversideup/php includes pre-configured PHP extensions and settings for enhanced performance and security. Optimized for Laravel and WordPress.","org.opencontainers.image.documentation":"https://serversideup.net/open-source/docker-php/docs/","org.opencontainers.image.licenses":"GPL-3.0-or-later","org.opencontainers.image.source":"https://github.com/serversideup/docker-php","org.opencontainers.image.title":"serversideup/php ()","org.opencontainers.image.url":"https://serversideup.net/open-source/docker-php/","org.opencontainers.image.vendor":"ServerSideUp","org.opencontainers.image.version":"git-12a4960-7869052174"}

Current Behavior

Since this is a docker image, and the docker network is not configured to host mode most of the time, the nginx in docker will see every requests from the docker network (for example, from 172.22.0.1) and consider it as trusted. After that, PHP's $_SERVER['REMOTE_ADDR'] will be set to the CF-Connecting-IP header. This breaks Laravel's trusted proxies feature (it is actually from Symfony, see symfony/symfony#26006). Some possible results are:

Expected Behavior

If nginx needs to trust the docker network, CF-Connecting-IP should not be used.

Steps To Reproduce

  1. Create a Laravel project and run it with serversideup/php:beta-8.3-fpm-nginx

  2. Create a route to the function:

    function test()
    {
    echo json_encode(
        [
            ...collect($_SERVER)->only([
                'HTTP_CF_CONNECTING_IP',
                'HTTP_X_FORWARDED_FOR',
                'REMOTE_ADDR',
            ]),
            'isFromTrustedProxy' => request()->isFromTrustedProxy(),
        ],
        JSON_PRETTY_PRINT,
    );
    die;
    }
  3. curl http://localhost:9000/test

    {
    "REMOTE_ADDR": "172.22.0.1",
    "isFromTrustedProxy": true
    }
  4. curl --header "CF-Connecting-IP: 1.2.3.4" http://localhost:9000/test

    {
    "HTTP_CF_CONNECTING_IP": "1.2.3.4",
    "REMOTE_ADDR": "1.2.3.4",
    "isFromTrustedProxy": false
    }

Host Operating System

Debian 12

Docker Version

Client: Docker Engine - Community
 Version:           25.0.3
 API version:       1.44
 Go version:        go1.21.6
 Git commit:        4debf41
 Built:             Tue Feb  6 21:14:25 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          25.0.3
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.6
  Git commit:       f417435
  Built:            Tue Feb  6 21:14:25 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.28
  GitCommit:        ae07eda36dd25f8a1b98dfbf587313b99c0190bb
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Anything else?

No response

jaydrogers commented 6 months ago

Thanks for your patience! Last month, my wife and I had our first child so life was a bit crazy 🤪

I think I am following a bit of what you're saying here. I'm not too familiar with the Laravel trusted proxy and may need to loop @danpastori on this to review as well.

@balthild: Do you have a proposed solution on how to resolve this?

jaydrogers commented 5 months ago

Closing for inactivity. Please comment again if this issue still persists.

alex-uxify commented 1 month ago

Our team stuck on the same place. Laravel receives real ip of the user and doesn't consider the request comming from trusted proxy, which breaks the scheme and protocol in our case causing serving of a mixed content.

However proposing a solution on this topic is tricky because it really depends on the case and desired outcome. We might patch the issue with wildcard for trustedProxies but that's not the ideal solution.

jaydrogers commented 1 month ago

Thanks for chiming in. I understand proposed solutions can be tricky, but if there is a default that is causing headache let me know. I am all ears if the community has a good approach to resolving this 👍