Piwik Proxy Hide URL behind reverse proxy not reporting actual user IP


I’m using a CDN service that acts as a reverse proxy. It provides 2 http headers: X-Real-Forwarded-For and X-Forwarded-For. According to the server access log, the CDN server ip appears in the cip parameter. I’m not sure how proxy_client_headers[] in the config.inc.php works. Is there an officially supported way to make Piwik hide url proxy log the actual user IP? Or can I use js/ proxy?

(Matthieu Aubry) #2

Thanks for message. This is a known bug / feature request: When running piwik proxy php to hide footprint, IP address is not set correctly when the website being tracked is behind proxy · Issue #2900 · matomo-org/matomo · GitHub

please comment on this comment to make your voice heard!


You’re welcome, matt. I should have searched the forum and trac before opening the topic…
I’ve googled a bit about proxy_client_headers[], but can’t find detailed documentation. Can I put both X-Real-Forwarded-For and X-Forwarded-For headers in the config? Then what would happen if neither headers are present in the request?

(Matthieu Aubry) #4

that’s the bug, that this ticket is about to fix.

The problem lies at this line: https://github.com/piwik/piwik/blob/master/misc/proxy-hide-piwik-url/piwik.php#L64

replace @$_SERVER[‘REMOTE_ADDR’]
with the right value, eg.



Thanks for pointing that out. I’ll grep proxy_client_headers in the code to find out how it works.
By the way, @$_SERVER[‘HTTP_X_REAL_FORWARDED_FOR’] worked for me.

(Matthieu Aubry) #6

i think the way it should work for piwik.php proxy is: try all known _SERVER keys, that could contain IPs, and get the first one from it.


Well, that’s sort of what I’m doing right now. My CDN provider provided a modified ip detection function for phpwind in their support forum: 知道云安全都提供哪些客户支持方式 – 知道创宇云安全 – 帮助与文档 .

I simplified it as follow:

if (isset($_SERVER['HTTP_X_REAL_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_REAL_FORWARDED_FOR'])) {
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $User_IP = $_SERVER['HTTP_X_FORWARDED_FOR'];
elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
        $User_IP = $_SERVER['HTTP_CLIENT_IP'];

And added the above code to piwik.php, so @$_SERVER[] becomes $User_IP. It works… I didn’t mention it earlier because I wasn’t sure about the code’s license.

(Matthieu Aubry) #8

Thank you, I fixed it in git Fixes #2900 Now reading 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'H… · matomo-org/matomo@300d3c2 · GitHub