diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php
index 765f109fdb3b1ea7a4f6b72eb4777a52fd63641e..73a27b677b08a215c61a824bf3479a48d5f89d8b 100644
--- a/lib/private/Security/Bruteforce/Throttler.php
+++ b/lib/private/Security/Bruteforce/Throttler.php
@@ -185,6 +185,67 @@ class Throttler {
 		$qb->execute();
 	}
 
+	/**
+	 * Check if the IP is whitelisted
+	 *
+	 * @param string $ip
+	 * @return bool
+	 */
+	private function isIPWhitelisted($ip) {
+		$keys = $this->config->getAppKeys('bruteForce');
+		$keys = array_filter($keys, function($key) {
+			$regex = '/^whitelist_/S';
+			return preg_match($regex, $key) === 1;
+		});
+
+		if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+			$type = 4;
+		} else if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
+			$type = 6;
+		} else {
+			return false;
+		}
+
+		$ip = inet_pton($ip);
+
+		foreach ($keys as $key) {
+			$cidr = $this->config->getAppValue('bruteForce', $key, null);
+
+			$cx = explode('/', $cidr);
+			$addr = $cx[0];
+			$mask = (int)$cx[1];
+
+			// Do not compare ipv4 to ipv6
+			if (($type === 4 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) ||
+				($type === 6 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))) {
+				continue;
+			}
+
+			$addr = inet_pton($addr);
+
+			$valid = true;
+			for($i = 0; $i < $mask; $i++) {
+				$part = ord($addr[(int)($i/8)]);
+				$orig = ord($ip[(int)($i/8)]);
+
+				$part = $part & (15 << (1 - ($i % 2)));
+				$orig = $orig & (15 << (1 - ($i % 2)));
+
+				if ($part !== $orig) {
+					$valid = false;
+					break;
+				}
+			}
+
+			if ($valid === true) {
+				return true;
+			}
+		}
+
+		return false;
+
+	}
+
 	/**
 	 * Get the throttling delay (in milliseconds)
 	 *
@@ -193,6 +254,10 @@ class Throttler {
 	 * @return int
 	 */
 	public function getDelay($ip, $action = '') {
+		if ($this->isIPWhitelisted($ip)) {
+			return 0;
+		}
+
 		$cutoffTime = (new \DateTime())
 			->sub($this->getCutoff(43200))
 			->getTimestamp();
diff --git a/tests/lib/Security/Bruteforce/ThrottlerTest.php b/tests/lib/Security/Bruteforce/ThrottlerTest.php
index 604aecd3a65b1aa6d9887bd24d1068d006f47c38..02d5b701679b455b5be885a5cc9d41424c028684 100644
--- a/tests/lib/Security/Bruteforce/ThrottlerTest.php
+++ b/tests/lib/Security/Bruteforce/ThrottlerTest.php
@@ -40,7 +40,7 @@ class ThrottlerTest extends TestCase {
 	private $dbConnection;
 	/** @var ILogger */
 	private $logger;
-	/** @var IConfig */
+	/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
 	private $config;
 
 	public function setUp() {
@@ -120,4 +120,92 @@ class ThrottlerTest extends TestCase {
 			$this->invokePrivate($this->throttler, 'getIPv6Subnet', ['2001:0db8:85a3:0000:0000:8a2e:0370:7334', 40])
 		);
 	}
+
+	public function dataIsIPWhitelisted() {
+		return [
+			[
+				'10.10.10.10',
+				[
+					'whitelist_0' => '10.10.10.0/24',
+				],
+				true,
+			],
+			[
+				'10.10.10.10',
+				[
+					'whitelist_0' => '192.168.0.0/16',
+				],
+				false,
+			],
+			[
+				'10.10.10.10',
+				[
+					'whitelist_0' => '192.168.0.0/16',
+					'whitelist_1' => '10.10.10.0/24',
+				],
+				true,
+			],
+			[
+				'dead:beef:cafe::1',
+				[
+					'whitelist_0' => '192.168.0.0/16',
+					'whitelist_1' => '10.10.10.0/24',
+					'whitelist_2' => 'deaf:beef:cafe:1234::/64'
+				],
+				false,
+			],
+			[
+				'dead:beef:cafe::1',
+				[
+					'whitelist_0' => '192.168.0.0/16',
+					'whitelist_1' => '10.10.10.0/24',
+					'whitelist_2' => 'deaf:beef::/64'
+				],
+				false,
+			],
+			[
+				'dead:beef:cafe::1',
+				[
+					'whitelist_0' => '192.168.0.0/16',
+					'whitelist_1' => '10.10.10.0/24',
+					'whitelist_2' => 'deaf:cafe::/8'
+				],
+				true,
+			],
+			[
+				'invalid',
+				[],
+				false,
+			],
+		];
+	}
+
+	/**
+	 * @dataProvider dataIsIPWhitelisted
+	 *
+	 * @param string $ip
+	 * @param string[] $whitelists
+	 * @param bool $isWhiteListed
+	 */
+	public function testIsIPWhitelisted($ip, $whitelists, $isWhiteListed) {
+		$this->config->method('getAppKeys')
+			->with($this->equalTo('bruteForce'))
+			->willReturn(array_keys($whitelists));
+
+		$this->config->method('getAppValue')
+			->will($this->returnCallback(function($app, $key, $default) use ($whitelists) {
+				if ($app !== 'bruteForce') {
+					return $default;
+				}
+				if (isset($whitelists[$key])) {
+					return $whitelists[$key];
+				}
+				return $default;
+			}));
+
+		$this->assertSame(
+			$isWhiteListed,
+			$this->invokePrivate($this->throttler, 'isIPWhitelisted', [$ip])
+		);
+	}
 }