Add trusted IPs in config and try to ban forwarded IP on failed login
* Add a new settings (which needs to be manually set): `security.trusted_proxies` * On login failure, if the `REMOTE_ADDR` is in the trusted proxies, try to retrieve the forwarded IP in headers. * If found, the client address is added in ipbans, else we do nothing. Fixes #409
This commit is contained in:
parent
c7a42ab1d9
commit
50d1791838
3 changed files with 94 additions and 1 deletions
|
@ -215,3 +215,29 @@ function page_url($server)
|
||||||
}
|
}
|
||||||
return index_url($server);
|
return index_url($server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the initial IP forwarded by the reverse proxy.
|
||||||
|
*
|
||||||
|
* Inspired from: https://github.com/zendframework/zend-http/blob/master/src/PhpEnvironment/RemoteAddress.php
|
||||||
|
*
|
||||||
|
* @param array $server $_SERVER array which contains HTTP headers.
|
||||||
|
* @param array $trustedIps List of trusted IP from the configuration.
|
||||||
|
*
|
||||||
|
* @return string|bool The forwarded IP, or false if none could be extracted.
|
||||||
|
*/
|
||||||
|
function getIpAddressFromProxy($server, $trustedIps)
|
||||||
|
{
|
||||||
|
$forwardedIpHeader = 'HTTP_X_FORWARDED_FOR';
|
||||||
|
if (empty($server[$forwardedIpHeader])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ips = preg_split('/\s*,\s*/', $server[$forwardedIpHeader]);
|
||||||
|
$ips = array_diff($ips, $trustedIps);
|
||||||
|
if (empty($ips)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_pop($ips);
|
||||||
|
}
|
||||||
|
|
11
index.php
11
index.php
|
@ -318,8 +318,17 @@ function logout() {
|
||||||
function ban_loginFailed($conf)
|
function ban_loginFailed($conf)
|
||||||
{
|
{
|
||||||
$ip = $_SERVER['REMOTE_ADDR'];
|
$ip = $_SERVER['REMOTE_ADDR'];
|
||||||
|
$trusted = $conf->get('security.trusted_proxies', array());
|
||||||
|
if (in_array($ip, $trusted)) {
|
||||||
|
$ip = getIpAddressFromProxy($_SERVER, $trusted);
|
||||||
|
if (!$ip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
$gb = $GLOBALS['IPBANS'];
|
$gb = $GLOBALS['IPBANS'];
|
||||||
if (!isset($gb['FAILURES'][$ip])) $gb['FAILURES'][$ip]=0;
|
if (! isset($gb['FAILURES'][$ip])) {
|
||||||
|
$gb['FAILURES'][$ip]=0;
|
||||||
|
}
|
||||||
$gb['FAILURES'][$ip]++;
|
$gb['FAILURES'][$ip]++;
|
||||||
if ($gb['FAILURES'][$ip] > ($conf->get('security.ban_after') - 1))
|
if ($gb['FAILURES'][$ip] > ($conf->get('security.ban_after') - 1))
|
||||||
{
|
{
|
||||||
|
|
58
tests/HttpUtils/GetIpAdressFromProxyTest.php
Normal file
58
tests/HttpUtils/GetIpAdressFromProxyTest.php
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'application/HttpUtils.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unitary tests for getIpAddressFromProxy()
|
||||||
|
*/
|
||||||
|
class GetIpAdressFromProxyTest extends PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test without proxy
|
||||||
|
*/
|
||||||
|
public function testWithoutProxy()
|
||||||
|
{
|
||||||
|
$this->assertFalse(getIpAddressFromProxy(array(), array()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test with a single IP in proxy header.
|
||||||
|
*/
|
||||||
|
public function testWithOneForwardedIp()
|
||||||
|
{
|
||||||
|
$ip = '1.1.1.1';
|
||||||
|
$server = array('HTTP_X_FORWARDED_FOR' => $ip);
|
||||||
|
$this->assertEquals($ip, getIpAddressFromProxy($server, array()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test with a multiple IPs in proxy header.
|
||||||
|
*/
|
||||||
|
public function testWithMultipleForwardedIp()
|
||||||
|
{
|
||||||
|
$ip = '1.1.1.1';
|
||||||
|
$ip2 = '2.2.2.2';
|
||||||
|
|
||||||
|
$server = array('HTTP_X_FORWARDED_FOR' => $ip .','. $ip2);
|
||||||
|
$this->assertEquals($ip2, getIpAddressFromProxy($server, array()));
|
||||||
|
|
||||||
|
$server = array('HTTP_X_FORWARDED_FOR' => $ip .' , '. $ip2);
|
||||||
|
$this->assertEquals($ip2, getIpAddressFromProxy($server, array()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test with a trusted IP address.
|
||||||
|
*/
|
||||||
|
public function testWithTrustedIp()
|
||||||
|
{
|
||||||
|
$ip = '1.1.1.1';
|
||||||
|
$ip2 = '2.2.2.2';
|
||||||
|
|
||||||
|
$server = array('HTTP_X_FORWARDED_FOR' => $ip);
|
||||||
|
$this->assertFalse(getIpAddressFromProxy($server, array($ip)));
|
||||||
|
|
||||||
|
$server = array('HTTP_X_FORWARDED_FOR' => $ip .','. $ip2);
|
||||||
|
$this->assertEquals($ip2, getIpAddressFromProxy($server, array($ip)));
|
||||||
|
$this->assertFalse(getIpAddressFromProxy($server, array($ip, $ip2)));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue