Last modified: 2011-09-06 23:21:05 UTC

Wikimedia Bugzilla is closed!

Wikimedia migrated from Bugzilla to Phabricator. Bug reports are handled in Wikimedia Phabricator.
This static website is read-only and for historical purposes. It is not possible to log in and except for displaying bug reports and their history, links might be broken. See T32739, the corresponding Phabricator task for complete and up-to-date bug report information.
Bug 30739 - IPv6 addresses not obtained successfully from X-Forwarded-For on Squid 3.1.15
IPv6 addresses not obtained successfully from X-Forwarded-For on Squid 3.1.15
Status: RESOLVED FIXED
Product: MediaWiki
Classification: Unclassified
Interface (Other open bugs)
1.20.x
PC Linux
: Unprioritized normal (vote)
: ---
Assigned To: Brion Vibber
: ipv6
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2011-09-04 03:54 UTC by Carl Austin Bennett
Modified: 2011-09-06 23:21 UTC (History)
3 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Attachments

Description Carl Austin Bennett 2011-09-04 03:54:47 UTC
I'm running Mediawiki 1.17 and 1.19-alpha behind a Squid 3.1.15 server. 

On what appears to be a valid configuration if the user is IPv4, MediaWiki can't get user IPv6 addresses out of X-Forwarded-For header and into the wiki.

I've compiled the latest Squid from source and my /usr/local/squid/etc/squid.conf looks something like:

http_port 96.45.180.93:80 vhost 
http_port [2605:ac00:f000:102:230:48ff:fece:ce12]:80 vhost 
cache_peer 127.0.0.1 parent 80 0 no-query originserver round-robin

Sure enough, if I attempt to access this box from elsewhere on the same subnet, I can see the "remote" IPv6 address recorded in Squid's access.log:

1315105640.362    874 2605:ac00:f000:102:217:3fff:fece:e23d
TCP_MISS/301 550 GET http://oscar6/wiki/special:mypage - ROUNDROBIN_PARENT/127.0
.0.1 text/html
1315105642.781    409 2605:ac00:f000:102:217:3fff:fece:e23d TCP_MISS/302 527 GET
 http://oscar6/wiki/Kerfiss%C3%AD%C3%B0a:Notandas%C3%AD%C3%B0a_m%C3%ADn - ROUNDR
OBIN_PARENT/127.0.0.1 text/html
1315105644.791      0 2605:ac00:f000:102:217:3fff:fece:e23d TCP_NEGATIVE_HIT/404
 12740 GET http://oscar6/index.php? - NONE/- text/html

but that request for [[special:mypage]] just sent me to [[user:127.0.0.1]] instead of [[user:2605:ac00:f000:102:217:3fff:fece:e23d]]?

If I try to edit, even though I'm on an IPv6 link from some other box (Squid is on the same box as MediaWiki, web browser is not) IPv6 anon-edits are attributed to 127.0.0.1 (Apache's internal IPv4 address, behind the Squid 3 server) while IPv4 anon-edits are attributed correctly. CheckUser logs also show the same pattern of all IPv6 users being "127.0.0.1" for want of XFF data.

Is there an easy way to check where the XFF is getting clobbered? I see Squid's bugtracker lists XFF under IPv6 as having supposedly been fixed a year ago, but I can't allow Squid 3 to monitor both IPv4/IPv6 if (for want of XFF) all the IPv6 anon-IP activity yields in the wiki is the IPv4 address of Apache itself.
Comment 1 Brion Vibber 2011-09-06 18:29:28 UTC
1) What's the X-Forwarded-For header actually look like?

2) What's the REMOTE_ADDR seen from Apache? Is it the same for IPv4 and IPv6 visits?

3) Note that any untrusted X-Forwarded-For entries are automatically ignored to avoid spoofing; only entries provided by a trusted proxy host will be taken into account.

Make sure that your proxy server is listed in $wgSquidServers or $wgSquidServersNoPurge -- if things come in through a different address on the IPv6 path it might actually not be seeing it as coming from a trusted server.

http://www.mediawiki.org/wiki/Manual:$wgSquidServers
Comment 2 Carl Austin Bennett 2011-09-06 22:17:59 UTC
This is what Squid/Apache is feeding to ProxyTools.php::wfGetForwardedFor()

Host=ipv6.example.org
User-Agent=Mozilla/5.0 (Windows NT 5.1; rv:6.0.1) Gecko/20100101 Firefox/6.0.1
Accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language=en-GB,en;q=0.9,en-US;q=0.7,en-ca;q=0.6,fr-FR;q=0.4,fr;q=0.3,en;q=0.1
Accept-Encoding=gzip, deflate
Accept-Charset=ISO-8859-1,utf-8;q=0.7,*;q=0.7
Referer=http://ipv6.example.org/wiki/User:127.0.0.1
DNT=1
Pragma=no-cache
Via=1.1 server.example.org (squid/3.1.15)
X-Forwarded-For=2001:5c0:1000:a::133
Cache-Control=no-cache


obtained by inserting a 'print' statement as:

function wfGetForwardedFor() {
        if( function_exists( 'apache_request_headers' ) ) {
                // More reliable than $_SERVER due to case and -/_ folding
                $set = array ();
                foreach ( apache_request_headers() as $tempName => $tempValue )
{
                       $set[ strtoupper( $tempName ) ] = $tempValue;
                       print $tempName . "=" . $tempValue . ", \n";
                }

According to ProxyTools.php::wfGetIP() 
REMOTE_ADDR = 127.0.0.1 

and, according to the config files, 127.0.0.1 is in $wgSquidServersNoPurge (as it must, or IPv4 traffic would also be in [[special:recentchanges]] as coming from localhost - and some random admin would've tried to ban the address by now)

So, clearly $set['X-Forwarded-For'] = '2001:5c0:1000:a::133' is done in wfGetForwardedFor() and it's somewhere after this point that it doesn't like an IPv6 address.
Comment 3 Carl Austin Bennett 2011-09-06 22:31:34 UTC
This is weird, wfGetIP correctly determines $ipchain = {127.0.0.1 , 2001:5c0:1000:a::133 } and recognises 127.0.0.1 as a trusted proxy (localhost4) but then fails to recognise the IPv6 as compliant with IP::isPublic()

Set $wgUsePrivateIPs = 1 and suddenly [[special:mypage]] indeed does go to [[User:2001:5C0:1000:A:0:0:0:133]] (or whatever dynamic IP I'm browsing from).
Comment 4 Brion Vibber 2011-09-06 22:38:29 UTC
Curious! IP::isPublic6() only lists fc:: - fdff:ffff.....ffff and 0:0:0:0:0:0:0:1 as private ranges, so the 2001:... one should come through ok.


Aho, looks like that should be 'fc00::' not 'fc::' ... http://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses
Comment 5 Brion Vibber 2011-09-06 22:39:32 UTC
Adding need-unittest keyword; a prime candidate for adding to unit tests. :)
Comment 6 Carl Austin Bennett 2011-09-06 22:41:32 UTC
The problem would appear to be IP.php:isPublic( $ip ) which fails IPv6 addresses on this test:

   // ip2long accepts incomplete addresses, as well as some addresses
   // followed by garbage characters. Check that it's really valid.
   if( $ip != long2ip( $n ) ) {
       return false;
   }
Comment 7 Carl Austin Bennett 2011-09-06 22:47:17 UTC
I tried disabling the " $1p != long2ip ( $n ) " and going to http://ipv6.uncyclomedia.org/wiki/Special:Mypage - it successfully comes back at me now as http://ipv6.uncyclomedia.org/wiki/User:2001:5C0:1000:A:0:0:0:133

Clearly it's doing something that doesn't like IPv6 (for instance, if a 'long' is defined as 32-bits, as a machine word or as anything smaller than 128 bits this would ensure 'long2ip' to not be IPv6 friendly no matter what else takes place).

This is based on the MediaWiki 1.17alpha but I believe the same issue is in 1.19
Comment 8 Brion Vibber 2011-09-06 22:51:14 UTC
The code never gets that far -- there's a check for isIPv6() right at the top which diverts execution into isPublic6. :)

Problem is simply that the range list it's checking against is incorrect, so the vast majority of potential network addresses are miscategorized as private.
Comment 9 Carl Austin Bennett 2011-09-06 22:54:26 UTC
The diversion to isPublic6 appears to exist in the 1.19alpha but not the 1.17alpha

I still have quite a few sites on the old code as some extensions break on the upgrade - I shall have to see what's up with the new (1.19) version of IP.php
Comment 10 Carl Austin Bennett 2011-09-06 23:01:45 UTC
Brion, I can confirm your "Aho, looks like that should be 'fc00::' not 'fc::'"

Indeed 00fc: to fdff:/16 is huge, but change this to:

if ( !$privateRanges ) {
   $privateRanges = array(
       array( 'fc00::', 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' ), # RFC 4193 (local)
       array( '0:0:0:0:0:0:0:1', '0:0:0:0:0:0:0:1' ), # loopback
    );
}

to flag just fc00: to fdff:/16 as local and the code starts working.

This makes sense as global IPv6 addresses are prefixed 2xxx: or 3xxx: - thanks.
Comment 11 Brion Vibber 2011-09-06 23:03:28 UTC
Awesome, good to confirm that fixes it in practice for you. :D I'm adjusting the tests and patching...
Comment 12 Brion Vibber 2011-09-06 23:20:48 UTC
Perfect timing -- Aaron fixed it on trunk in r96386 and committed just before me. :)

It's marked for backport to 1.18 and 1.17 so should be in the next bug-fix and feature releases.

Note You need to log in before you can comment on or make changes to this bug.


Navigation
Links