docker-php icon indicating copy to clipboard operation
docker-php copied to clipboard

Nginx realip module breaks Laravel's TrustProxies middleware

Open balthild opened this issue 1 year ago • 0 comments

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:

  • Breaks Laravel's URL generation if TLS is configured outside this docker image (for example, [user] --https-- [caddy] --http-- [nginx in docker]). All generated URLs will be with http:// rather than https://.
  • If the website is not using Cloudflare, users may send a fake IP with CF-Connecting-IP header to spoof PHP.

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;
}
  1. curl http://localhost:9000/test
{
    "REMOTE_ADDR": "172.22.0.1",
    "isFromTrustedProxy": true
}
  1. 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

balthild avatar Mar 02 '24 03:03 balthild