• Welcome to the Chevereto user community!

    Here users from all over the world gather around to learn the latest about Chevereto and contribute with ideas to improve the software.

    Please keep in mind:

  • Chevereto Support CLST

    Support response

    Support checklist

    • Got a Something went wrong message? Read this guide and provide the actual error. Do not skip this.
    • Confirm that the server meets the System Requirements
    • Check for any available Hotfix - your issue could be already reported/fixed
    • Read documentation - It will be required to Debug and understand Errors for a faster support response

Cloudflare in front of a reverse proxy (load balance) will always return the proxy IP, not client.

Status
Not open for further replies.

SlowShip

Chevereto Member
Hello,

After having looked into the source code closely. I think the script ignore Cloudflare settings, and if it sees HTTP_CF_CONNECTING_IP, it will automatically equal REMOTE_ADDR and ignore the X-REAL-IP or X-FORWARDED-FOR header from the load balancer (in my particular case, I append both header from nginx)

Reproducible step:
0. Of course, having a working chevereto up and running.
1. Setup a nginx reverse proxy (or load balance).
2. Make sure the reverse proxy return the true IP of the client while connecting through it (a small php that return REMOTE_ADDR will confirm this)
3. Put everything behind Cloudflare (or enable Cloudflare)
4. Upload something, the app will return the reverse proxy /loadbalance IP instead of the true REMOTE_ADDR

Can you re-write the script so that it will be return value like X-REAL-IP or X-FORWARDED-FOR (if exist) and not just HTTP_CF_CONNECTING_IP ?
Even better yet, have a setting so that we can disable this behavior as a proper webserver config wouldn't need chevereto to intervene like this and will just return REMOTE_ADDR
 
You are right, the script used to rely on basic conditionals to overwrite REMOTE_ADDR:

Code:
// Fix CloudFlare REMOTE_ADDR
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
^ This one turns REMOTE_ADDR = HTTP_CF_CONNECTING_IP

Code:
    // Cloudflare REMOTE_ADDR workaround
    if (Settings::get('cloudflare') or isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
            $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
        }
    }
^ This one does the same thing.

If you comment the codes above, you should get the real IP under your setup.

Since long ago the system now uses G\get_client_ip() to return the real IP. That function looks like this:

Code:
    function get_client_ip()
    {
        $client_ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : (!empty($_ENV['REMOTE_ADDR']) ? $_ENV['REMOTE_ADDR'] : null);

        if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER) && $_SERVER['HTTP_CF_CONNECTING_IP'] == $_SERVER['REMOTE_ADDR']) {
            return $_SERVER['HTTP_CF_CONNECTING_IP'];
        }

        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $entries = preg_split('/[\s,]/', $_SERVER['HTTP_X_FORWARDED_FOR'], -1, PREG_SPLIT_NO_EMPTY);

            reset($entries);

            foreach ($entries as $entry) {
                $entry = trim($entry);
                if (preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/', $entry, $ip_list)) {
                    $private_ip = array(
                          '/^0\./',
                          '/^127\.0\.0\.1/',
                          '/^192\.168\..*/',
                          '/^172\.((1[6-9])|(2[0-9])|(3[0-1]))\..*/',
                          '/^10\..*/');

                    $found_ip = preg_replace($private_ip, $client_ip, $ip_list[1]);
                    if ($client_ip != $found_ip) { //  and !isset($_SERVER['HTTP_CF_CONNECTING_IP']
                        $client_ip = $found_ip;
                        break;
                    }
                }
            }
        }

        return $client_ip;
    }

^ This one addresses the HTTP_X_FORWARDED_FOR, but since the other code changed REMOTE_ADDR, the rest of the code never gets executed.

I will patch this in the next revision.
 
Last edited:
Status
Not open for further replies.
Back
Top