1 (edited by DiggerNZ 09/27/2026 08:51:42 pm)

Topic: Session dropped behind Cloudflare (orange-cloud)

FrontAccounting 2.4.20 on PHP 8.3, site published through Cloudflare with the proxy on (orange cloud).

Problem:
The login was dropped every few screens, and in particular each time a main-menu tab was opened (index.php?application=...). Logging in again worked, until the next tab.

SessionManager stores the client address on the session and, in preventHijacking(), treats a different address as a hijack and wipes the session. Behind Cloudflare, REMOTE_ADDR is a Cloudflare edge address, and that address changes from one request to the next. The visitor has not changed. The next menu click looks like a hijack, and the login is cleared.

Solution:
I enabled a solution that works for all users as it currently does, but also for servers who use Cloudflare Orange.

What I changed:
1. The address stored and compared is the visitor address Cloudflare sends (CF-Connecting-IP), and only when the request also has Cloudflare's CF-RAY header. Both headers are required so a client who simply sends CF-Connecting-IP is not trusted.
Users who are not coming through Cloudflare orange-cloud, or through another proxy that sets those two headers, are not affected. A LAN client, or a WAN client hitting the server directly, has no CF-RAY header, so clientAddress() returns REMOTE_ADDR and the check is the same as before.

2. I removed the 5% random call to regenerateSession() on every request. That path is not specific to Cloudflare. On PHP 8, regenerateSession() (session_regenerate_id, session_write_close, then session_start again) drops the logged-in session on the requests where it runs. A real address mismatch still calls regenerateSession().

Code:
------
Replaced, in sessionStart():
$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];

with:
$_SESSION['IPaddress'] = $this->clientAddress();

------

Removed, immediately after regenerateSession() in that same block:
// Give a 5% chance of the session id changing on any request
}
elseif (rand(1, 100) <= 5)
{
    $this->regenerateSession();
}

------

Replaced, in preventHijacking():
if ($_SESSION['IPaddress'] != $_SERVER['REMOTE_ADDR'])
    return false;

with:

if ($_SESSION['IPaddress'] != $this->clientAddress())
    return false;

------

Added, immediately above preventHijacking():
// Visitor address. Cloudflare's own address changes between requests, so the
// session is kept against CF-Connecting-IP when that request came through Cloudflare.
function clientAddress()
{
    if (!empty($_SERVER['HTTP_CF_CONNECTING_IP']) && !empty($_SERVER['HTTP_CF_RAY']))
        return $_SERVER['HTTP_CF_CONNECTING_IP'];
    return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
}

------
After this, one fresh login stays put across the menu tabs. I'm happy for this to be adjusted if there is a preferred way to handle it in the next release.

Post's attachments

session.inc 18.7 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.