Index: trunk/phase3/includes/ProxyTools.php |
— | — | @@ -23,7 +23,7 @@ |
24 | 24 | |
25 | 25 | /** Work out the IP address based on various globals */ |
26 | 26 | function wfGetIP() { |
27 | | - global $wgSquidServers, $wgSquidServersNoPurge, $wgIP; |
| 27 | + global $wgIP; |
28 | 28 | |
29 | 29 | # Return cached result |
30 | 30 | if ( !empty( $wgIP ) ) { |
— | — | @@ -40,27 +40,22 @@ |
41 | 41 | } |
42 | 42 | $ip = $ipchain[0]; |
43 | 43 | |
44 | | - # Get list of trusted proxies |
45 | | - # Flipped for quicker access |
46 | | - $trustedProxies = array_flip( array_merge( $wgSquidServers, $wgSquidServersNoPurge ) ); |
47 | | - if ( count( $trustedProxies ) ) { |
48 | | - # Append XFF on to $ipchain |
49 | | - $forwardedFor = wfGetForwardedFor(); |
50 | | - if ( isset( $forwardedFor ) ) { |
51 | | - $xff = array_map( 'trim', explode( ',', $forwardedFor ) ); |
52 | | - $xff = array_reverse( $xff ); |
53 | | - $ipchain = array_merge( $ipchain, $xff ); |
54 | | - } |
55 | | - # Step through XFF list and find the last address in the list which is a trusted server |
56 | | - # Set $ip to the IP address given by that trusted server, unless the address is not sensible (e.g. private) |
57 | | - foreach ( $ipchain as $i => $curIP ) { |
58 | | - if ( array_key_exists( $curIP, $trustedProxies ) ) { |
59 | | - if ( isset( $ipchain[$i + 1] ) && IP::isPublic( $ipchain[$i + 1] ) ) { |
60 | | - $ip = $ipchain[$i + 1]; |
61 | | - } |
62 | | - } else { |
63 | | - break; |
| 44 | + # Append XFF on to $ipchain |
| 45 | + $forwardedFor = wfGetForwardedFor(); |
| 46 | + if ( isset( $forwardedFor ) ) { |
| 47 | + $xff = array_map( 'trim', explode( ',', $forwardedFor ) ); |
| 48 | + $xff = array_reverse( $xff ); |
| 49 | + $ipchain = array_merge( $ipchain, $xff ); |
| 50 | + } |
| 51 | + # Step through XFF list and find the last address in the list which is a trusted server |
| 52 | + # Set $ip to the IP address given by that trusted server, unless the address is not sensible (e.g. private) |
| 53 | + foreach ( $ipchain as $i => $curIP ) { |
| 54 | + if ( wfIsTrustedProxy( $curIP ) ) { |
| 55 | + if ( isset( $ipchain[$i + 1] ) && IP::isPublic( $ipchain[$i + 1] ) ) { |
| 56 | + $ip = $ipchain[$i + 1]; |
64 | 57 | } |
| 58 | + } else { |
| 59 | + break; |
65 | 60 | } |
66 | 61 | } |
67 | 62 | |
— | — | @@ -69,6 +64,21 @@ |
70 | 65 | return $ip; |
71 | 66 | } |
72 | 67 | |
| 68 | +function wfIsTrustedProxy( $ip ) { |
| 69 | + global $wgSquidServers, $wgSquidServersNoPurge; |
| 70 | + |
| 71 | + if ( in_array( $ip, $wgSquidServers ) || |
| 72 | + in_array( $ip, $wgSquidServersNoPurge ) || |
| 73 | + wfIsAOLProxy( $ip ) |
| 74 | + ) { |
| 75 | + $trusted = true; |
| 76 | + } else { |
| 77 | + $trusted = false; |
| 78 | + } |
| 79 | + wfRunHooks( 'IsTrustedProxy', array( &$ip, &$trusted ) ); |
| 80 | + return $trusted; |
| 81 | +} |
| 82 | + |
73 | 83 | /** |
74 | 84 | * Forks processes to scan the originating IP for an open proxy server |
75 | 85 | * MemCached can be used to skip IPs that have already been scanned |
— | — | @@ -154,7 +164,52 @@ |
155 | 165 | return $ret; |
156 | 166 | } |
157 | 167 | |
| 168 | +/** |
| 169 | + * TODO: move this list to the database in a global IP info table incorporating |
| 170 | + * trusted ISP proxies, blocked IP addresses and open proxies. |
| 171 | + */ |
| 172 | +function wfIsAOLProxy( $ip ) { |
| 173 | + $ranges = array( |
| 174 | + '64.12.96.0/19', |
| 175 | + '149.174.160.0/20', |
| 176 | + '152.163.240.0/21', |
| 177 | + '152.163.248.0/22', |
| 178 | + '152.163.252.0/23', |
| 179 | + '152.163.96.0/22', |
| 180 | + '152.163.100.0/23', |
| 181 | + '195.93.32.0/22', |
| 182 | + '195.93.48.0/22', |
| 183 | + '195.93.64.0/19', |
| 184 | + '195.93.96.0/19', |
| 185 | + '195.93.16.0/20', |
| 186 | + '198.81.0.0/22', |
| 187 | + '198.81.16.0/20', |
| 188 | + '198.81.8.0/23', |
| 189 | + '202.67.64.128/25', |
| 190 | + '205.188.192.0/20', |
| 191 | + '205.188.208.0/23', |
| 192 | + '205.188.112.0/20', |
| 193 | + '205.188.146.144/30', |
| 194 | + '207.200.112.0/21', |
| 195 | + ); |
158 | 196 | |
| 197 | + static $parsedRanges; |
| 198 | + if ( is_null( $parsedRanges ) ) { |
| 199 | + $parsedRanges = array(); |
| 200 | + foreach ( $ranges as $range ) { |
| 201 | + $parsedRanges[] = IP::parseRange( $range ); |
| 202 | + } |
| 203 | + } |
159 | 204 | |
| 205 | + $hex = IP::toHex( $ip ); |
| 206 | + foreach ( $parsedRanges as $range ) { |
| 207 | + if ( $hex >= $range[0] && $hex <= $range[1] ) { |
| 208 | + return true; |
| 209 | + } |
| 210 | + } |
| 211 | + return false; |
| 212 | +} |
160 | 213 | |
| 214 | + |
| 215 | + |
161 | 216 | ?> |
Index: trunk/phase3/includes/Block.php |
— | — | @@ -241,10 +241,10 @@ |
242 | 242 | |
243 | 243 | /** |
244 | 244 | * Determine if a given integer IPv4 address is in a given CIDR network |
245 | | - * @deprecated Use wfIsAddressInRange |
| 245 | + * @deprecated Use IP::isAddressInRange |
246 | 246 | */ |
247 | 247 | function isAddressInRange( $addr, $range ) { |
248 | | - return wfIsAddressInRange( $addr, $range ); |
| 248 | + return IP::isAddressInRange( $addr, $range ); |
249 | 249 | } |
250 | 250 | |
251 | 251 | function initFromRow( $row ) |
— | — | @@ -275,9 +275,7 @@ |
276 | 276 | $this->mRangeEnd = ''; |
277 | 277 | |
278 | 278 | if ( $this->mUser == 0 ) { |
279 | | - $startend = wfRangeStartEnd($this->mAddress); |
280 | | - $this->mRangeStart = $startend[0]; |
281 | | - $this->mRangeEnd = $startend[1]; |
| 279 | + list( $this->mRangeStart, $this->mRangeEnd ) = IP::parseCIDR( $this->mAddress ); |
282 | 280 | } |
283 | 281 | } |
284 | 282 | |
— | — | @@ -407,7 +405,7 @@ |
408 | 406 | *@return Whether or not a retroactive autoblock was made. |
409 | 407 | */ |
410 | 408 | function doRetroactiveAutoblock() { |
411 | | - $dbr = wfGetDb( DB_SLAVE ); |
| 409 | + $dbr = wfGetDB( DB_SLAVE ); |
412 | 410 | #If autoblock is enabled, autoblock the LAST IP used |
413 | 411 | # - stolen shamelessly from CheckUser_body.php |
414 | 412 | |
— | — | @@ -435,7 +433,7 @@ |
436 | 434 | */ |
437 | 435 | function doAutoblock( $autoblockip ) { |
438 | 436 | # Check if this IP address is already blocked |
439 | | - $dbw =& wfGetDb( DB_MASTER ); |
| 437 | + $dbw =& wfGetDB( DB_MASTER ); |
440 | 438 | $dbw->begin(); |
441 | 439 | |
442 | 440 | # If autoblocks are disabled, go away. |
— | — | @@ -463,7 +461,7 @@ |
464 | 462 | wfDebug("Checking $wlEntry\n"); |
465 | 463 | |
466 | 464 | # Is the IP in this range? |
467 | | - if (wfIsAddressInRange( $ip, $wlEntry )) { |
| 465 | + if (IP::isInRange( $ip, $wlEntry )) { |
468 | 466 | wfDebug("IP $ip matches $wlEntry, not autoblocking\n"); |
469 | 467 | #$autoblockip = null; # Don't autoblock a whitelisted IP. |
470 | 468 | return; #This /SHOULD/ introduce a dummy block - but |
Index: trunk/phase3/includes/IP.php |
— | — | @@ -206,6 +206,19 @@ |
207 | 207 | } else { |
208 | 208 | return array( $start, $end ); |
209 | 209 | } |
210 | | - } |
| 210 | + } |
| 211 | + |
| 212 | + /** |
| 213 | + * Determine if a given integer IPv4 address is in a given CIDR network |
| 214 | + * @param $addr The address to check against the given range. |
| 215 | + * @param $range The range to check the given address against. |
| 216 | + * @return bool Whether or not the given address is in the given range. |
| 217 | + */ |
| 218 | + function isInRange( $addr, $range ) { |
| 219 | + $unsignedIP = IP::toUnsigned($addr); |
| 220 | + list( $start, $end ) = IP::parseRange($range); |
| 221 | + |
| 222 | + return (($unsignedIP >= $start) && ($unsignedIP <= $end)); |
| 223 | + } |
211 | 224 | } |
212 | 225 | ?> |