elsloo closed pull request #2184: Anonymous IP TR Implementation
URL: https://github.com/apache/incubator-trafficcontrol/pull/2184
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/config/ConfigHandler.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/config/ConfigHandler.java
index ea17db058..2c33409e1 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/config/ConfigHandler.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/config/ConfigHandler.java
@@ -60,6 +60,9 @@
 import com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker;
 import com.comcast.cdn.traffic_control.traffic_router.geolocation.Geolocation;
 import com.comcast.cdn.traffic_control.traffic_router.core.request.HTTPRequest;
+import com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIp;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpConfigUpdater;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpDatabaseUpdater;
 
 @SuppressWarnings("PMD.TooManyFields")
 public class ConfigHandler {
@@ -80,6 +83,8 @@
        private DeepNetworkUpdater deepNetworkUpdater;
        private FederationsWatcher federationsWatcher;
        private RegionalGeoUpdater regionalGeoUpdater;
+       private AnonymousIpConfigUpdater anonymousIpConfigUpdater;
+       private AnonymousIpDatabaseUpdater anonymousIpDatabaseUpdater;
        private SteeringWatcher steeringWatcher;
        private CertificatesPoller certificatesPoller;
        private CertificatesPublisher certificatesPublisher;
@@ -112,6 +117,14 @@ public RegionalGeoUpdater getRegionalGeoUpdater() {
                return regionalGeoUpdater;
        }
 
+       public AnonymousIpConfigUpdater getAnonymousIpConfigUpdater() {
+               return anonymousIpConfigUpdater;
+       }
+
+       public AnonymousIpDatabaseUpdater getAnonymousIpDatabaseUpdater() {
+               return anonymousIpDatabaseUpdater;
+       }
+
        @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", 
"PMD.AvoidCatchingThrowable"})
        public boolean processConfig(final String jsonStr) throws 
JsonUtilsException, IOException  {
                isProcessing.set(true);
@@ -148,6 +161,7 @@ public boolean processConfig(final String jsonStr) throws 
JsonUtilsException, IO
                                parseCoverageZoneNetworkConfig(config);
                                parseDeepCoverageZoneNetworkConfig(config);
                                parseRegionalGeoConfig(jo);
+                               parseAnonymousIpConfig(jo);
 
                                final CacheRegister cacheRegister = new 
CacheRegister();
                                final JsonNode deliveryServicesJson = 
JsonUtils.getJsonNode(jo, "deliveryServices");
@@ -270,6 +284,14 @@ public void setRegionalGeoUpdater(final RegionalGeoUpdater 
regionalGeoUpdater) {
                this.regionalGeoUpdater = regionalGeoUpdater;
        }
 
+       public void setAnonymousIpConfigUpdater(final AnonymousIpConfigUpdater 
anonymousIpConfigUpdater) {
+               this.anonymousIpConfigUpdater = anonymousIpConfigUpdater;
+       }
+       
+       public void setAnonymousIpDatabaseUpdater(final 
AnonymousIpDatabaseUpdater anonymousIpDatabaseUpdater) {
+               this.anonymousIpDatabaseUpdater = anonymousIpDatabaseUpdater;
+       }
+
        /**
         * Parses the Traffic Ops config
         * @param config
@@ -540,6 +562,52 @@ private void parseCertificatesConfig(final JsonNode 
config) {
                }
        }
 
+       private void parseAnonymousIpConfig(final JsonNode jo) throws 
JsonUtilsException {
+               final String anonymousPollingUrl = "anonymousip.polling.url";
+               final String anonymousPollingInterval = 
"anonymousip.polling.interval";
+               final String anonymousPolicyConfiguration = 
"anonymousip.policy.configuration";
+
+               final JsonNode config = JsonUtils.getJsonNode(jo,"config");
+               final String configUrl = JsonUtils.optString(config, 
anonymousPolicyConfiguration, null);
+               final String databaseUrl = JsonUtils.optString(config, 
anonymousPollingUrl, null);
+
+               if (configUrl == null) {
+                       LOGGER.info(anonymousPolicyConfiguration + " not 
configured; stopping service updater and disabling feature");
+                       getAnonymousIpConfigUpdater().stopServiceUpdater();
+                       AnonymousIp.getCurrentConfig().enabled = false;
+                       return;
+               }
+               
+               if (databaseUrl == null) {
+                       LOGGER.info(anonymousPollingUrl + " not configured; 
stopping service updater and disabling feature");
+                       getAnonymousIpDatabaseUpdater().stopServiceUpdater();
+                       AnonymousIp.getCurrentConfig().enabled = false;
+                       return;
+               }
+
+               if (jo.has(deliveryServicesKey)) {
+                       final JsonNode dss = JsonUtils.getJsonNode(jo, 
deliveryServicesKey);
+                       final Iterator<String> dsNames = dss.fieldNames();
+                       while (dsNames.hasNext()) {
+                               final String ds = dsNames.next();
+                               final JsonNode dsNode = 
JsonUtils.getJsonNode(dss, ds);
+                               if (JsonUtils.optString(dsNode, 
"anonymousBlockingEnabled").equals("true")) {
+                                       final long interval = 
JsonUtils.optLong(config, anonymousPollingInterval);
+                                       
getAnonymousIpConfigUpdater().setDataBaseURL(configUrl, interval);
+                                       
getAnonymousIpDatabaseUpdater().setDataBaseURL(databaseUrl, interval);
+                                       AnonymousIp.getCurrentConfig().enabled 
= true;
+                                       LOGGER.debug("Anonymous Blocking in 
use, scheduling service updaters and enabling feature");
+                                       return;
+                               }
+                       }
+               }
+
+               LOGGER.debug("No DS using anonymous ip blocking - disabling 
feature");
+               getAnonymousIpConfigUpdater().cancelServiceUpdater();
+               getAnonymousIpDatabaseUpdater().cancelServiceUpdater();
+               AnonymousIp.getCurrentConfig().enabled = false;
+       }
+
        /**
         * Parses the ConverageZoneNetwork database configuration and updates 
the database if the URL has
         * changed.
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/ds/DeliveryService.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/ds/DeliveryService.java
index 4aadd70d2..441378c16 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/ds/DeliveryService.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/ds/DeliveryService.java
@@ -33,8 +33,6 @@
 import java.util.Iterator;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtils;
-import 
com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtilsException;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.databind.JsonNode;
 import org.apache.log4j.Logger;
@@ -49,9 +47,11 @@
 import 
com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker.Track;
 import 
com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker.Track.ResultType;
 import 
com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker.Track.ResultDetails;
+import com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtils;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtilsException;
 import 
com.comcast.cdn.traffic_control.traffic_router.core.util.StringProtector;
 
-@SuppressWarnings({"PMD.TooManyFields","PMD.CyclomaticComplexity"})
+@SuppressWarnings({"PMD.TooManyFields","PMD.CyclomaticComplexity", 
"PMD.AvoidDuplicateLiterals"})
 public class DeliveryService {
        protected static final Logger LOGGER = 
Logger.getLogger(DeliveryService.class);
        private final String id;
@@ -86,6 +86,7 @@
        private final Set<String> requestHeaders = new HashSet<String>();
        private final boolean regionalGeoEnabled;
        private final String geolocationProvider;
+       private final boolean anonymousIpEnabled;
        private final boolean sslEnabled;
        private static final int STANDARD_HTTP_PORT = 80;
        private static final int STANDARD_HTTPS_PORT = 443;
@@ -145,6 +146,7 @@ public DeliveryService(final String id, final JsonNode 
dsJo) throws JsonUtilsExc
                        LOGGER.info("DeliveryService '" + id + "' will use 
default geolocation provider Maxmind");
                }
                sslEnabled = JsonUtils.optBoolean(dsJo, "sslEnabled");
+               this.anonymousIpEnabled = JsonUtils.optBoolean(dsJo, 
"anonymousBlockingEnabled");
 
                final JsonNode protocol = dsJo.get("protocol");
                acceptHttp = JsonUtils.optBoolean(protocol, "acceptHttp", true);
@@ -617,6 +619,10 @@ public String getGeolocationProvider() {
                return geolocationProvider;
        }
 
+       public boolean isAnonymousIpEnabled() {
+               return anonymousIpEnabled;
+       }
+
        public List<CacheLocation> filterAvailableLocations(final 
Collection<CacheLocation> cacheLocations) {
                final List<CacheLocation> locations = new 
ArrayList<CacheLocation>();
 
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIp.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIp.java
new file mode 100644
index 000000000..26f8fe9bd
--- /dev/null
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIp.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.net.InetAddresses;
+import com.maxmind.geoip2.model.AnonymousIpResponse;
+import org.apache.log4j.Logger;
+
+import com.comcast.cdn.traffic_control.traffic_router.core.cache.Cache;
+import com.comcast.cdn.traffic_control.traffic_router.core.ds.DeliveryService;
+import com.comcast.cdn.traffic_control.traffic_router.core.request.HTTPRequest;
+import com.comcast.cdn.traffic_control.traffic_router.core.request.Request;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.router.HTTPRouteResult;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker.Track;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker.Track.ResultType;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.router.TrafficRouter;
+import com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtils;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtilsException;
+
+public final class AnonymousIp {
+
+       private static final Logger LOGGER = 
Logger.getLogger(AnonymousIp.class);
+
+       private static AnonymousIp currentConfig = new AnonymousIp();
+
+       // Feature flipper
+       // This is set to true if the CRConfig parameters containing the MMDB 
URL
+       // and the config url are present AND any delivery service has the 
feature
+       // enabled
+       public boolean enabled = false;
+
+       private boolean blockAnonymousIp = true;
+       private boolean blockHostingProvider = true;
+       private boolean blockPublicProxy = true;
+       private boolean blockTorExitNode = true;
+
+       private AnonymousIpWhitelist ipv4Whitelist;
+       private AnonymousIpWhitelist ipv6Whitelist;
+
+       private String redirectUrl;
+
+       public final static int BLOCK_CODE = 403;
+       public final static String WHITE_LIST_LOC = "w";
+
+       private AnonymousIp() {
+               try {
+                       ipv4Whitelist = new AnonymousIpWhitelist();
+                       ipv6Whitelist = new AnonymousIpWhitelist();
+               } catch (NetworkNodeException e) {
+                       LOGGER.error("AnonymousIp ERR: Network node exception 
", e);
+               }
+       }
+
+       /*
+        * Returns the current anonymous ip object
+        */
+       public static AnonymousIp getCurrentConfig() {
+               return currentConfig;
+       }
+
+       /*
+        * Returns the list of subnets in the IPv4 whitelist
+        */
+       public AnonymousIpWhitelist getIPv4Whitelist() {
+               return ipv4Whitelist;
+       }
+
+       /*
+        * Returns the list of subnets in the IPv6 whitelist
+        */
+       public AnonymousIpWhitelist getIPv6Whitelist() {
+               return ipv6Whitelist;
+       }
+
+       private static void parseIPv4Whitelist(final JsonNode config, final 
AnonymousIp anonymousIp) throws JsonUtilsException {
+               if (config.has("ip4Whitelist")) {
+                       try {
+                               anonymousIp.ipv4Whitelist = new 
AnonymousIpWhitelist();
+                               
anonymousIp.ipv4Whitelist.init(JsonUtils.getJsonNode(config, "ip4Whitelist"));
+                       } catch (NetworkNodeException e) {
+                               LOGGER.error("Anonymous Ip ERR: Network node 
err ", e);
+                       }
+               }
+       }
+
+       private static void parseIPv6Whitelist(final JsonNode config, final 
AnonymousIp anonymousIp) throws JsonUtilsException {
+               if (config.has("ip6Whitelist")) {
+                       try {
+                               anonymousIp.ipv4Whitelist = new 
AnonymousIpWhitelist();
+                               
anonymousIp.ipv4Whitelist.init(JsonUtils.getJsonNode(config, "ip6Whitelist"));
+                       } catch (NetworkNodeException e) {
+                               LOGGER.error("Anonymous Ip ERR: Network node 
err ", e);
+                       }
+               }
+       }
+
+       @SuppressWarnings({ "PMD.NPathComplexity", "PMD.CyclomaticComplexity" })
+       private static AnonymousIp parseConfigJson(final JsonNode config) {
+               final AnonymousIp anonymousIp = new AnonymousIp();
+               try {
+                       final JsonNode blockingTypes = 
JsonUtils.getJsonNode(config, "anonymousIp");
+
+                       anonymousIp.blockAnonymousIp = 
JsonUtils.getBoolean(blockingTypes, "blockAnonymousVPN");
+                       anonymousIp.blockHostingProvider = 
JsonUtils.getBoolean(blockingTypes, "blockHostingProvider");
+                       anonymousIp.blockPublicProxy = 
JsonUtils.getBoolean(blockingTypes, "blockPublicProxy");
+                       anonymousIp.blockTorExitNode = 
JsonUtils.getBoolean(blockingTypes, "blockTorExitNode");
+
+                       anonymousIp.enabled = AnonymousIp.currentConfig.enabled;
+
+                       parseIPv4Whitelist(config, anonymousIp);
+                       parseIPv6Whitelist(config, anonymousIp);
+
+                       if (config.has("redirectUrl")) {
+                               anonymousIp.redirectUrl = 
JsonUtils.getString(config, "redirectUrl");
+                       }
+
+                       return anonymousIp;
+               } catch (Exception e) {
+                       LOGGER.error("AnonymousIp ERR: parsing config file 
failed", e);
+               }
+
+               return null;
+       }
+
+       @SuppressWarnings({ "PMD.NPathComplexity" })
+       public static boolean parseConfigFile(final File f, final boolean 
verifyOnly) {
+               JsonNode json = null;
+               try {
+                       final ObjectMapper mapper = new ObjectMapper();
+                       json = mapper.readTree(f);
+               } catch (Exception e) {
+                       LOGGER.error("AnonymousIp ERR: json file exception " + 
f, e);
+                       return false;
+               }
+
+               final AnonymousIp anonymousIp = parseConfigJson(json);
+
+               if (anonymousIp == null) {
+                       return false;
+               }
+
+               if (!verifyOnly) {
+                       currentConfig = anonymousIp; // point to the new parsed 
object
+               }
+
+               return true;
+       }
+
+       private static boolean inWhitelist(final String address) {
+               // If the address is ipv4 check against the ipv4whitelist
+               if (address.indexOf(':') == -1) {
+                       if (currentConfig.ipv4Whitelist.contains(address)) {
+                               return true;
+                       }
+               }
+
+               // If the address is ipv6 check against the ipv6whitelist
+               else {
+                       if (currentConfig.ipv6Whitelist.contains(address)) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+       @SuppressWarnings({ "PMD.CyclomaticComplexity", "PMD.NPathComplexity" })
+       public static boolean enforce(final TrafficRouter trafficRouter, final 
String dsvcId, final String url, final String ip) {
+
+               final InetAddress address = InetAddresses.forString(ip);
+
+               if (inWhitelist(ip)) {
+                       return false;
+               }
+
+               final AnonymousIpResponse response = 
trafficRouter.getAnonymousIpDatabaseService().lookupIp(address);
+
+               if (response == null) {
+                       return false;
+               }
+
+               // Check if the ip should be blocked by checking if the ip 
falls into a
+               // specific policy
+               if (AnonymousIp.getCurrentConfig().blockAnonymousIp && 
response.isAnonymousVpn()) {
+                       return true;
+               }
+
+               if (AnonymousIp.getCurrentConfig().blockHostingProvider && 
response.isHostingProvider()) {
+                       return true;
+               }
+
+               if (AnonymousIp.getCurrentConfig().blockPublicProxy && 
response.isPublicProxy()) {
+                       return true;
+               }
+
+               if (AnonymousIp.getCurrentConfig().blockTorExitNode && 
response.isTorExitNode()) {
+                       return true;
+               }
+
+               return false;
+       }
+
+       @SuppressWarnings({ "PMD.CyclomaticComplexity" })
+       /*
+        * Enforces the anonymous ip blocking policies
+        * 
+        * If the Delivery Service has anonymous ip blocking enabled And the ip 
is
+        * in the anonymous ip database The ip will be blocked if it matches a
+        * policy defined in the config file
+        */
+       public static void enforce(final TrafficRouter trafficRouter, final 
Request request, final DeliveryService deliveryService, final Cache cache, 
+               final HTTPRouteResult routeResult, final Track track) throws 
MalformedURLException {
+
+               final HTTPRequest httpRequest = HTTPRequest.class.cast(request);
+
+               // If the database isn't initialized dont block
+               if 
(!trafficRouter.getAnonymousIpDatabaseService().isInitialized()) {
+                       return;
+               }
+
+               // Check if the ip is allowed
+               final boolean block = enforce(trafficRouter, 
deliveryService.getId(), httpRequest.getRequestedUrl(), 
httpRequest.getClientIP());
+
+               // Block the ip if it is not allowed
+               if (block) {
+                       routeResult.setResponseCode(AnonymousIp.BLOCK_CODE);
+                       track.setResult(ResultType.ANON_BLOCK);
+                       if (AnonymousIp.getCurrentConfig().redirectUrl != null) 
{
+                               routeResult.setUrl(new 
URL(AnonymousIp.getCurrentConfig().redirectUrl));
+                       }
+               }
+       }
+}
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpConfigUpdater.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpConfigUpdater.java
new file mode 100644
index 000000000..ede90bc4e
--- /dev/null
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpConfigUpdater.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+
+public class AnonymousIpConfigUpdater extends AbstractServiceUpdater {
+    private static final Logger LOGGER = 
Logger.getLogger(AnonymousIpConfigUpdater.class);
+
+    public AnonymousIpConfigUpdater() {
+        LOGGER.debug("init...");
+        sourceCompressed = false;
+        tmpPrefix = "anonymousip";
+        tmpSuffix = ".json";
+    }
+    
+    @Override
+    /*
+     * Loads the anonymous ip config file
+     */
+    public boolean loadDatabase() throws IOException {
+       LOGGER.debug("AnonymousIpConfigUodater loading config");
+        final File existingDB = 
databasesDirectory.resolve(databaseName).toFile();
+        return AnonymousIp.parseConfigFile(existingDB, false);
+    }
+
+    @Override
+    /*
+     * Verifies the anonymous ip config file
+     */
+    public boolean verifyDatabase(final File dbFile) throws IOException {
+       LOGGER.debug("AnonymousIpConfigUpdater verifying config");
+        return AnonymousIp.parseConfigFile(dbFile, true);
+    }
+
+}
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseService.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseService.java
new file mode 100644
index 000000000..b70846b46
--- /dev/null
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseService.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+
+import org.apache.log4j.Logger;
+
+import com.maxmind.geoip2.DatabaseReader;
+import com.maxmind.geoip2.exception.GeoIp2Exception;
+import com.maxmind.geoip2.model.AnonymousIpResponse;
+
+@SuppressWarnings({ "PMD.AvoidDuplicateLiterals" })
+public class AnonymousIpDatabaseService {
+       private static final Logger LOGGER = 
Logger.getLogger(AnonymousIpDatabaseService.class);
+
+       private boolean initialized = false;
+       private File databaseFile;
+       private DatabaseReader databaseReader;
+
+       /*
+        * Reloads the anonymous ip database
+        */
+       public void reloadDatabase() throws IOException {
+               if (databaseReader != null) {
+                       databaseReader.close();
+               }
+
+               if (databaseFile != null) {
+                       final DatabaseReader reader = 
createDatabaseReader(databaseFile);
+                       if (reader != null) {
+                               databaseReader = reader;
+                               initialized = true;
+                       } else {
+                               throw new IOException("Could not create 
database reader");
+                       }
+               }
+       }
+
+       public void setDatabaseFile(final File databaseFile) {
+               this.databaseFile = databaseFile;
+       }
+
+       /*
+        * Verifies the database by attempting to recreate it
+        */
+       public boolean verifyDatabase(final File databaseFile) throws 
IOException {
+               return createDatabaseReader(databaseFile) != null;
+       }
+
+       /*
+        * Creates a DatabaseReader object using an input database file
+        */
+       private DatabaseReader createDatabaseReader(final File databaseFile) 
throws IOException {
+               if (!databaseFile.exists()) {
+                       LOGGER.warn(databaseFile.getAbsolutePath() + " does not 
exist yet!");
+                       return null;
+               }
+
+               if (databaseFile.isDirectory()) {
+                       LOGGER.error(databaseFile + " is a directory, need a 
file");
+                       return null;
+               }
+
+               LOGGER.info("Loading Anonymous IP db: " + 
databaseFile.getAbsolutePath());
+
+               try {
+                       final DatabaseReader reader = new 
DatabaseReader.Builder(databaseFile).build();
+                       return reader;
+               } catch (Exception e) {
+                       LOGGER.error(databaseFile.getAbsolutePath() + " is not 
a valid Anonymous IP data file", e);
+                       return null;
+               }
+       }
+
+       /*
+        * Returns an AnonymousIpResponse from looking an ip up in the database
+        */
+       public AnonymousIpResponse lookupIp(final InetAddress ipAddress) {
+               if (initialized) {
+                       // Return an anonymousIp object after looking up the ip 
in the
+                       // database
+                       try {
+                               return databaseReader.anonymousIp(ipAddress);
+                       } catch (GeoIp2Exception e) {
+                               LOGGER.debug(String.format("AnonymousIP: IP %s 
not found in anonymous ip database", ipAddress.getHostAddress()));
+                               return null;
+                       } catch (IOException e) {
+                               LOGGER.error("AnonymousIp ERR: IO Error during 
lookup of ip in anonymous ip database", e);
+                               return null;
+                       }
+               } else {
+                       return null;
+               }
+       }
+
+       public boolean isInitialized() {
+               return initialized;
+       }
+
+       /*
+        * Closes the database when the object is destroyed
+        */
+       @Override
+       protected void finalize() throws Throwable {
+               if (databaseReader != null) {
+                       try {
+                               databaseReader.close();
+                               databaseReader = null;
+                       } catch (IOException e) {
+                               LOGGER.warn("Caught exception while trying to 
close anonymous ip database reader: ", e);
+                       }
+               }
+               super.finalize();
+       }
+
+}
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseUpdater.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseUpdater.java
new file mode 100644
index 000000000..2d63f2d19
--- /dev/null
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseUpdater.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings({ "PMD.AvoidDuplicateLiterals" })
+public class AnonymousIpDatabaseUpdater extends AbstractServiceUpdater {
+    private static final Logger LOGGER = 
Logger.getLogger(AnonymousIpDatabaseUpdater.class);
+
+       private AnonymousIpDatabaseService anonymousIpDatabaseService;
+
+       @Override
+       /*
+        * Verifies the anonymous ip database
+        */
+       public boolean verifyDatabase(final File dbFile) throws IOException {
+               LOGGER.debug("Verifying Anonymous IP Database");
+               return anonymousIpDatabaseService.verifyDatabase(dbFile);
+       }
+
+       /*
+        * Sets the anonymous ip database file and reloads the database
+        */
+       public boolean loadDatabase() throws IOException {
+               LOGGER.debug("Loading Anonymous IP Database");
+               
anonymousIpDatabaseService.setDatabaseFile(databasesDirectory.resolve(databaseName).toFile());
+               anonymousIpDatabaseService.reloadDatabase();
+               return true;
+       }
+
+       @Override
+       /*
+        * Returns a boolean with the initialization state of the database
+        */
+       public boolean isLoaded() {
+               if (anonymousIpDatabaseService != null) {
+                       return anonymousIpDatabaseService.isInitialized();
+               }
+
+               return loaded;
+       }
+       
+       public void setAnonymousIpDatabaseService(final 
AnonymousIpDatabaseService anonymousIpDatabaseService) {
+               this.anonymousIpDatabaseService = anonymousIpDatabaseService;
+       }
+
+}
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpWhitelist.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpWhitelist.java
new file mode 100644
index 000000000..b05aaafc4
--- /dev/null
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpWhitelist.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import org.apache.log4j.Logger;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtilsException;
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class AnonymousIpWhitelist {
+       private static final Logger LOGGER = 
Logger.getLogger(AnonymousIpWhitelist.class);
+
+       final private NetworkNode.SuperNode whitelist;
+
+       public AnonymousIpWhitelist() throws NetworkNodeException {
+               whitelist = new NetworkNode.SuperNode();
+       }
+
+       public void init(final JsonNode config) throws JsonUtilsException, 
NetworkNodeException {
+               if (config.isArray()) {
+                       for (final JsonNode node : config) {
+                               final String network = node.asText();
+                               this.add(network);
+                       }
+               }
+       }
+
+       public void add(final String network) throws NetworkNodeException {
+               final NetworkNode node = new NetworkNode(network, 
AnonymousIp.WHITE_LIST_LOC);
+               if (network.indexOf(':') == -1) {
+                       whitelist.add(node);
+               } else {
+                       whitelist.add6(node);
+               }
+       }
+
+       public boolean contains(final String address) {
+               if (whitelist == null) {
+                       return false;
+               }
+
+               try {
+                       final NetworkNode nn = whitelist.getNetwork(address);
+                       if (nn.getLoc() == AnonymousIp.WHITE_LIST_LOC) {
+                               return true;
+                       }
+               } catch (NetworkNodeException e) {
+                       LOGGER.warn("AnonymousIp: exception", e);
+               }
+
+               return false;
+       }
+}
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/StatTracker.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/StatTracker.java
index b444cd82a..ccc675cb9 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/StatTracker.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/StatTracker.java
@@ -111,7 +111,7 @@ public void setRegionalAlternateCount(final int 
regionalAlternateCount) {
                }
 
                public static enum ResultType {
-                       ERROR, CZ, GEO, MISS, STATIC_ROUTE, DS_REDIRECT, 
DS_MISS, INIT, FED, RGDENY, RGALT, GEO_REDIRECT, DEEP_CZ
+                       ERROR, CZ, GEO, MISS, STATIC_ROUTE, DS_REDIRECT, 
DS_MISS, INIT, FED, RGDENY, RGALT, GEO_REDIRECT, DEEP_CZ, ANON_BLOCK
                }
 
                public enum ResultDetails {
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
index 9662fd8ca..78ec478a8 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouter.java
@@ -67,6 +67,8 @@
 import 
com.comcast.cdn.traffic_control.traffic_router.core.util.TrafficOpsUtils;
 import com.comcast.cdn.traffic_control.traffic_router.core.util.CidrAddress;
 import 
com.comcast.cdn.traffic_control.traffic_router.core.router.StatTracker.Track.ResultDetails;
+import com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIp;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpDatabaseService;
 
 public class TrafficRouter {
        public static final Logger LOGGER = 
Logger.getLogger(TrafficRouter.class);
@@ -76,6 +78,7 @@
        private final ZoneManager zoneManager;
        private final GeolocationService geolocationService;
        private final GeolocationService geolocationService6;
+       private final AnonymousIpDatabaseService anonymousIpService;
        private final FederationRegistry federationRegistry;
        private final boolean consistentDNSRouting;
 
@@ -91,7 +94,8 @@
 
        public TrafficRouter(final CacheRegister cr, 
                        final GeolocationService geolocationService, 
-                       final GeolocationService geolocationService6, 
+                       final GeolocationService geolocationService6,
+                       final AnonymousIpDatabaseService anonymousIpService,
                        final StatTracker statTracker,
                        final TrafficOpsUtils trafficOpsUtils,
                        final FederationRegistry federationRegistry,
@@ -99,6 +103,7 @@ public TrafficRouter(final CacheRegister cr,
                this.cacheRegister = cr;
                this.geolocationService = geolocationService;
                this.geolocationService6 = geolocationService6;
+               this.anonymousIpService = anonymousIpService;
                this.federationRegistry = federationRegistry;
                this.consistentDNSRouting = 
JsonUtils.optBoolean(cr.getConfig(), "consistent.dns.routing");
                this.zoneManager = new ZoneManager(this, statTracker, 
trafficOpsUtils, trafficRouterManager);
@@ -199,6 +204,10 @@ public GeolocationService getGeolocationService() {
                return geolocationService;
        }
 
+       public AnonymousIpDatabaseService getAnonymousIpDatabaseService() {
+               return anonymousIpService;
+       }
+
        public Geolocation getLocation(final String clientIP) throws 
GeolocationException {
                return clientIP.contains(":") ? 
geolocationService6.location(clientIP) : geolocationService.location(clientIP);
        }
@@ -532,6 +541,7 @@ public HTTPRouteResult multiRoute(final HTTPRequest 
request, final Track track)
                return routeResult;
        }
 
+       @SuppressWarnings({ "PMD.CyclomaticComplexity", "PMD.NPathComplexity" })
        public HTTPRouteResult route(final HTTPRequest request, final Track 
track) throws MalformedURLException, GeolocationException {
                track.setRouteType(RouteType.HTTP, request.getHostname());
 
@@ -542,6 +552,7 @@ public HTTPRouteResult route(final HTTPRequest request, 
final Track track) throw
                }
        }
 
+       @SuppressWarnings({ "PMD.CyclomaticComplexity", "PMD.NPathComplexity" })
        public HTTPRouteResult singleRoute(final HTTPRequest request, final 
Track track) throws MalformedURLException, GeolocationException {
                final DeliveryService deliveryService = 
getDeliveryService(request, track);
 
@@ -574,6 +585,16 @@ public HTTPRouteResult singleRoute(final HTTPRequest 
request, final Track track)
 
                final Cache cache = consistentHasher.selectHashable(caches, 
deliveryService.getDispersion(), request.getPath());
 
+               // Enforce anonymous IP blocking if a DS has anonymous blocking 
enabled
+               // and the feature is enabled
+               if (deliveryService.isAnonymousIpEnabled() && 
AnonymousIp.getCurrentConfig().enabled) {
+                       AnonymousIp.enforce(this, request, deliveryService, 
cache, routeResult, track);
+
+                       if (routeResult.getResponseCode() == 
AnonymousIp.BLOCK_CODE) {
+                               return routeResult;
+                       }
+               }
+
                if (deliveryService.isRegionalGeoEnabled()) {
                        RegionalGeo.enforce(this, request, deliveryService, 
cache, routeResult, track);
                        return routeResult;
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
index 26b20c250..941ba5125 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
@@ -32,6 +32,7 @@
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.ContextRefreshedEvent;
+import 
com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpDatabaseService;
 
 public class TrafficRouterManager implements 
ApplicationListener<ContextRefreshedEvent> {
        private static final Logger LOGGER = 
Logger.getLogger(TrafficRouterManager.class);
@@ -42,6 +43,7 @@
        private TrafficRouter trafficRouter;
        private GeolocationService geolocationService;
        private GeolocationService geolocationService6;
+       private AnonymousIpDatabaseService anonymousIpService;
        private StatTracker statTracker;
        private static final Map<String, Long> timeTracker = new 
ConcurrentHashMap<String, Long>();
        private NameServer nameServer;
@@ -98,7 +100,7 @@ public void setCacheRegister(final CacheRegister 
cacheRegister) throws IOExcepti
                        return;
                }
 
-               final TrafficRouter tr = new TrafficRouter(cacheRegister, 
geolocationService, geolocationService6, statTracker, trafficOpsUtils, 
federationRegistry, this);
+               final TrafficRouter tr = new TrafficRouter(cacheRegister, 
geolocationService, geolocationService6, anonymousIpService, statTracker, 
trafficOpsUtils, federationRegistry, this);
                tr.setSteeringRegistry(steeringRegistry);
                synchronized(this) {
                        if (state != null) {
@@ -126,6 +128,10 @@ public void setGeolocationService6(final 
GeolocationService geolocationService)
                this.geolocationService6 = geolocationService;
        }
 
+       public void setAnonymousIpService(final AnonymousIpDatabaseService 
anonymousIpService) {
+               this.anonymousIpService = anonymousIpService;
+       }
+
        public void setStatTracker(final StatTracker statTracker) {
                this.statTracker = statTracker;
        }
diff --git a/traffic_router/core/src/main/webapp/WEB-INF/applicationContext.xml 
b/traffic_router/core/src/main/webapp/WEB-INF/applicationContext.xml
index fb5cca3b2..a46fdf729 100644
--- a/traffic_router/core/src/main/webapp/WEB-INF/applicationContext.xml
+++ b/traffic_router/core/src/main/webapp/WEB-INF/applicationContext.xml
@@ -62,6 +62,7 @@
                <property name="federationRegistry" ref="federationsRegistry" />
                <property name="geolocationService" 
ref="maxmindGeolocationService" />
                <property name="geolocationService6" 
ref="maxmindGeolocationService" />
+               <property name="anonymousIpService" 
ref="anonymousIpDatabaseService" />
                <property name="steeringRegistry" ref="steeringRegistry" />
        </bean>
 
@@ -111,6 +112,8 @@
                <property name="networkUpdater" ref="networkUpdater" />
                <property name="deepNetworkUpdater" ref="deepNetworkUpdater" />
                <property name="regionalGeoUpdater" ref="regionalGeoUpdater" />
+               <property name="anonymousIpConfigUpdater" 
ref="anonymousIpConfigUpdater" />
+               <property name="anonymousIpDatabaseUpdater" 
ref="anonymousIpDatabaseUpdater" />
                <property name="statTracker" ref="statTracker" />
                <property name="configDir" value="/opt/traffic_router/conf" />
                <property name="federationsWatcher" ref="federationsWatcher" />
@@ -127,6 +130,7 @@
        </bean>
 
        <bean id="maxmindGeolocationService" 
class="com.comcast.cdn.traffic_control.traffic_router.core.loc.MaxmindGeolocationService"/>
+       <bean id="anonymousIpDatabaseService" 
class="com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpDatabaseService"/>
        
        <bean id="geolocationDatabaseUpdater" 
class="com.comcast.cdn.traffic_control.traffic_router.core.loc.GeolocationDatabaseUpdater"
 init-method="init">
                <property name="databasesDirectory" ref="databasesDir"/>
@@ -162,6 +166,25 @@
                <property name="trafficRouterManager" 
ref="trafficRouterManager" />
        </bean>
 
+       <bean id="anonymousIpConfigUpdater" 
class="com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpConfigUpdater"
+               init-method="init">
+               <property name="executorService" ref="ScheduledExecutorService" 
/>
+               <property name="databasesDirectory" ref="databasesDir" />
+               <property name="databaseName" 
value="$[cache.anonymousip.database:anonymous_ip.json]" />
+               <property name="pollingInterval" 
value="$[cache.anonymousip.database.refresh.period:10800000]" />
+               <property name="trafficRouterManager" 
ref="trafficRouterManager" />
+       </bean>
+
+       <bean id="anonymousIpDatabaseUpdater" 
class="com.comcast.cdn.traffic_control.traffic_router.core.loc.AnonymousIpDatabaseUpdater"
+               init-method="init">
+               <property name="executorService" ref="ScheduledExecutorService" 
/>
+               <property name="databasesDirectory" ref="databasesDir" />
+               <property name="databaseName" 
value="$[cache.anonymousip.database:GeoIP2-Anonymous-IP.mmdb]" />
+               <property name="pollingInterval" 
value="$[cache.anonymousip.database.refresh.period:10800000]" />
+               <property name="trafficRouterManager" 
ref="trafficRouterManager" />
+               <property name="anonymousIpDatabaseService" 
ref="anonymousIpDatabaseService" />
+       </bean>
+
        <bean id="ScheduledExecutorService" 
class="java.util.concurrent.Executors"
                factory-method="newSingleThreadScheduledExecutor" />
 
diff --git 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseServiceTest.java
 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseServiceTest.java
new file mode 100644
index 000000000..c68276094
--- /dev/null
+++ 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpDatabaseServiceTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.maxmind.geoip2.exception.GeoIp2Exception;
+
+public class AnonymousIpDatabaseServiceTest {
+
+       private AnonymousIpDatabaseService anonymousIpService;
+       private final static String mmdb = 
"src/test/resources/GeoIP2-Anonymous-IP.mmdb";
+
+       @Before
+       public void setup() throws Exception {
+               // ignore the test if there is no mmdb file
+               File mmdbFile = new File(mmdb);
+               org.junit.Assume.assumeTrue(mmdbFile.exists());
+
+               anonymousIpService = new AnonymousIpDatabaseService();
+               File databaseFile = new File(mmdb);
+               anonymousIpService.setDatabaseFile(databaseFile);
+               anonymousIpService.reloadDatabase();
+               assert anonymousIpService.isInitialized();
+       }
+
+       @Test
+       public void testIpInDatabase() throws Exception {
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("223.26.48.248")), 
notNullValue());
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("223.26.48.248")), 
notNullValue());
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("1.1.205.152")), 
notNullValue());
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("18.85.22.204")), 
notNullValue());
+       }
+
+       @Test
+       public void testIpNotInDatabase() throws Exception {
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("192.168.0.1")), 
equalTo(null));
+       }
+
+       @Test
+       public void testDatabaseNotLoaded() throws UnknownHostException, 
IOException, GeoIp2Exception {
+               AnonymousIpDatabaseService anonymousIpService = new 
AnonymousIpDatabaseService();
+               assertThat(anonymousIpService.isInitialized(), equalTo(false));
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("223.26.48.248")), 
equalTo(null));
+               
assertThat(anonymousIpService.lookupIp(InetAddress.getByName("192.168.0.1")), 
equalTo(null));
+       }
+
+       @Test
+       public void testLookupTime() throws IOException {
+               final InetAddress ipAddress = 
InetAddress.getByName("223.26.48.248");
+               final long start = System.nanoTime();
+
+               long total = 100000;
+
+               for (int i = 0; i <= total; i++) {
+                       anonymousIpService.lookupIp(ipAddress);
+               }
+
+               long duration = System.nanoTime() - start;
+               
+               System.out.println(String.format("Anonymous IP database average 
lookup: %s nanoseconds", Long.toString(duration / total)));
+       }
+
+       @After
+       public void tearDown() throws Exception {
+               try {
+                       anonymousIpService.finalize();
+               } catch (Throwable e) {
+               }
+       }
+
+}
diff --git 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpTest.java
 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpTest.java
new file mode 100644
index 000000000..7fe97f7ec
--- /dev/null
+++ 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpTest.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import 
com.comcast.cdn.traffic_control.traffic_router.core.router.TrafficRouter;
+
+public class AnonymousIpTest {
+       private TrafficRouter trafficRouter;
+
+       final File configFile = new 
File("src/test/resources/anonymous_ip.json");
+       final File configNoWhitelist = new 
File("src/test/resources/anonymous_ip_no_whitelist.json");
+
+       final String mmdb = "src/test/resources/GeoIP2-Anonymous-IP.mmdb";
+       File databaseFile = new File(mmdb);
+
+       @Before
+       public void setUp() throws Exception {
+               // ignore the test if there is no mmdb file
+               File mmdbFile = new File(mmdb);
+               org.junit.Assume.assumeTrue(mmdbFile.exists());
+
+               AnonymousIp.parseConfigFile(configFile, false);
+               assert (AnonymousIp.getCurrentConfig().getIPv4Whitelist() != 
null);
+               assert (AnonymousIp.getCurrentConfig().getIPv6Whitelist() != 
null);
+
+               // Set up a mock traffic router with real database
+               AnonymousIpDatabaseService anonymousIpService = new 
AnonymousIpDatabaseService();
+               anonymousIpService.setDatabaseFile(databaseFile);
+               anonymousIpService.reloadDatabase();
+               assert anonymousIpService.isInitialized();
+               trafficRouter = mock(TrafficRouter.class);
+               
when(trafficRouter.getAnonymousIpDatabaseService()).thenReturn(anonymousIpService);
+               assert (trafficRouter.getAnonymousIpDatabaseService() != null);
+       }
+
+       @Test
+       public void testConfigFileParsingIpv4() {
+               AnonymousIp currentConfig = AnonymousIp.getCurrentConfig();
+               assertThat(currentConfig, notNullValue());
+               AnonymousIpWhitelist whitelist = 
currentConfig.getIPv4Whitelist();
+               assertThat(whitelist, notNullValue());
+       }
+
+       @Test
+       public void testConfigFileParsingIpv6() {
+               AnonymousIp currentConfig = AnonymousIp.getCurrentConfig();
+               assertThat(currentConfig, notNullValue());
+               AnonymousIpWhitelist whitelist = 
currentConfig.getIPv6Whitelist();
+               assertThat(whitelist, notNullValue());
+       }
+
+       @Test
+       public void testIpInWhitelistIsAllowed() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "5.34.32.79";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testFallsUnderManyPolicies() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2.38.158.142";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(true));
+       }
+
+       @Test
+       public void testAllowNotCheckingPolicy() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2.36.248.52";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testEnforceAllowed() throws IOException {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "10.0.0.1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testEnforceAllowedIpInWhitelist() throws IOException {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "10.0.2.1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testEnforceBlocked() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "223.26.48.248";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(true));
+       }
+
+       @Test
+       public void testEnforceNotInWhitelistNotInDB() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "192.168.0.1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+
+               assertThat(result, equalTo(false));
+       }
+
+       /* IPv4 no whitelist */
+
+       @Test
+       public void testEnforceNoWhitelistAllowed() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "192.168.0.1";
+               AnonymousIp.parseConfigFile(configNoWhitelist, false);
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testEnforceNoWhitelistBlocked() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "223.26.48.248";
+               AnonymousIp.parseConfigFile(configNoWhitelist, false);
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(true));
+       }
+
+       @Test
+       public void testEnforceNoWhitelistNotEnforcePolicy() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2.36.248.52";
+               AnonymousIp.parseConfigFile(configNoWhitelist, false);
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(false));
+       }
+
+       /* IPv6 Testing */
+
+       @Test
+       public void testIpv6EnforceBlock() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2001:418:9807::1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(true));
+       }
+
+       @Test
+       public void testIpv6EnforceNotBlock() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2001:418::1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testIpv6EnforceNotBlockWhitelisted() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2001:550:90a:0:0:0:0:1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testIpv6EnforceNotBlockOnWhitelist() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "::1";
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(false));
+       }
+
+       /* IPv6 tests no whitelist */
+
+       @Test
+       public void testIpv6NoWhitelistEnforceBlock() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2001:418:9807::1";
+               AnonymousIp.parseConfigFile(configNoWhitelist, false);
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(true));
+       }
+
+       @Test
+       public void testIpv6NoWhitelistNoBlock() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "::1";
+               AnonymousIp.parseConfigFile(configNoWhitelist, false);
+
+               final boolean result = AnonymousIp.enforce(trafficRouter, 
dsvcId, url, ip);
+               assertThat(result, equalTo(false));
+       }
+
+       @Test
+       public void testAnonymousIpPerformance() {
+               final String dsvcId = "dsID";
+               final String url = "http://ds1.example.com/live1";;
+               final String ip = "2.36.248.52";
+
+               long total = 100000;
+
+               long start = System.nanoTime();
+
+               for (int i = 0; i <= total; i++) {
+                       final boolean result = 
AnonymousIp.enforce(trafficRouter, dsvcId, url, ip);
+               }
+
+               long duration = System.nanoTime() - start;
+
+               System.out.println(String.format("Anonymous IP blocking average 
took %s nanoseconds", Long.toString(duration / total)));
+       }
+}
diff --git 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpWhitelistTest.java
 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpWhitelistTest.java
new file mode 100644
index 000000000..2a80bdc16
--- /dev/null
+++ 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/loc/AnonymousIpWhitelistTest.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.core.loc;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import 
com.comcast.cdn.traffic_control.traffic_router.core.util.JsonUtilsException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class AnonymousIpWhitelistTest {
+
+       AnonymousIpWhitelist ip4whitelist;
+       AnonymousIpWhitelist ip6whitelist;
+
+       @Before
+       public void setup() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+
+               ip4whitelist = new AnonymousIpWhitelist();
+               ip4whitelist.init(mapper.readTree("[\"192.168.30.0/24\", 
\"10.0.2.0/24\", \"10.0.0.0/16\"]"));
+
+               ip6whitelist = new AnonymousIpWhitelist();
+               ip6whitelist.init(mapper.readTree("[\"::1/32\", 
\"2001::/64\"]"));
+       }
+
+       @Test
+       public void testAnonymousIpWhitelistConstructor() {
+               // final InetAddress address = 
InetAddresses.forString("192.168.30.1");
+               assertThat(ip4whitelist.contains("192.168.30.1"), 
equalTo(true));
+       }
+
+       @Test
+       public void testIPsInWhitelist() {
+               assertThat(ip4whitelist.contains("192.168.30.1"), 
equalTo(true));
+
+               assertThat(ip4whitelist.contains("192.168.30.254"), 
equalTo(true));
+
+               assertThat(ip4whitelist.contains("10.0.2.1"), equalTo(true));
+
+               assertThat(ip4whitelist.contains("10.0.2.254"), equalTo(true));
+
+               assertThat(ip4whitelist.contains("10.0.1.1"), equalTo(true));
+
+               assertThat(ip4whitelist.contains("10.0.254.254"), 
equalTo(true));
+       }
+
+       @Test
+       public void testIPsNotInWhitelist() {
+               assertThat(ip4whitelist.contains("192.168.31.1"), 
equalTo(false));
+
+               assertThat(ip4whitelist.contains("192.167.30.1"), 
equalTo(false));
+
+               assertThat(ip4whitelist.contains("10.1.1.1"), equalTo(false));
+
+               assertThat(ip4whitelist.contains("10.10.1.1"), equalTo(false));
+       }
+
+       /* IPv6 Testing */
+
+       @Test
+       public void testIPv6AddressInWhitelist() {
+               assertThat(ip6whitelist.contains("::1"), equalTo(true));
+       }
+
+       @Test
+       public void testIPv6AddressInWhitelistInSubnet() {
+               assertThat(ip6whitelist.contains("2001::"), equalTo(true));
+
+               assertThat(ip6whitelist.contains("2001:0:0:0:0:0:0:1"), 
equalTo(true));
+
+               assertThat(ip6whitelist.contains("2001:0:0:0:0:0:1:1"), 
equalTo(true));
+
+               assertThat(ip6whitelist.contains("2001:0:0:0:a:a:a:a"), 
equalTo(true));
+
+               
assertThat(ip6whitelist.contains("2001:0:0:0:ffff:ffff:ffff:ffff"), 
equalTo(true));
+       }
+
+       @Test
+       public void testIpv6AddressNotInWhitelist() {
+               assertThat(ip6whitelist.contains("2001:1:0:0:0:0:0:0"), 
equalTo(false));
+
+               assertThat(ip6whitelist.contains("2001:0:1::"), equalTo(false));
+
+               assertThat(ip6whitelist.contains("2002:0:0:0:0:0:0:1"), 
equalTo(false));
+
+               
assertThat(ip6whitelist.contains("2001:0:0:1:ffff:ffff:ffff:ffff"), 
equalTo(false));
+       }
+
+       @Test
+       public void testWhitelistCreationLeafFirst() throws IOException, 
JsonUtilsException, NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+
+               ip4whitelist.init(mapper.readTree("[\"10.0.2.0/24\", 
\"10.0.0.0/16\"]"));
+
+               assertThat(ip4whitelist.contains("10.0.2.1"), equalTo(true));
+
+               assertThat(ip4whitelist.contains("10.0.10.1"), equalTo(true));
+       }
+
+       @Test
+       public void testWhitelistCreationParentFirst() throws IOException, 
JsonUtilsException, NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+
+               ip4whitelist.init(mapper.readTree("[\"10.0.0.0/16\"], 
\"10.0.2.0/24\""));
+
+               assertThat(ip4whitelist.contains("10.0.2.1"), equalTo(true));
+
+               assertThat(ip4whitelist.contains("10.0.10.1"), equalTo(true));
+       }
+
+       /* IPv4 validation */
+
+       @Test(expected = IOException.class)
+       public void badIPv4Input1() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"192.168.1/24\"]"));
+               assertThat(badlist.contains("192.168.0.1"), equalTo(false));
+       }
+
+       @Test(expected = IOException.class)
+       public void badIPv4Input2() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"256.168.0.1/24\"]"));
+               assertThat(badlist.contains("192.168.0.1"), equalTo(false));
+       }
+
+       @Test(expected = IOException.class)
+       public void badNetmaskInput1() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"192.168.0.1/33\"]"));
+               assertThat(badlist.contains("192.168.0.1"), equalTo(false));
+       }
+
+       @Test(expected = IOException.class)
+       public void badNetmaskInput2() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"::1/129\"]"));
+               assertThat(badlist.contains("::1"), equalTo(false));
+       }
+
+       @Test(expected = IOException.class)
+       public void badNetmaskInput3() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"192.168.0.1/-1\"]"));
+               assertThat(badlist.contains("192.168.0.1"), equalTo(false));
+       }
+
+       @Test(expected = IOException.class)
+       public void validIPv4Input() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"192.168.0.1/32\"]"));
+               assertThat(badlist.contains("192.168.0.1"), equalTo(false));
+       }
+
+       @Test(expected = IOException.class)
+       public void validIPv6Input() throws IOException, JsonUtilsException, 
NetworkNodeException {
+               final ObjectMapper mapper = new ObjectMapper();
+               AnonymousIpWhitelist badlist = new AnonymousIpWhitelist();
+               badlist.init(mapper.readTree("[\"\"::1/128\"]"));
+               assertThat(badlist.contains("::1"), equalTo(false));
+       }
+
+       /* NetworkNode takes forever to create Tree - commented out until it is 
needed
+       @Test
+       public void testAnonymousIpWhitelistPerformance65000() throws 
NetworkNodeException {
+               AnonymousIpWhitelist whitelist = new AnonymousIpWhitelist();
+               List<String> tempList = new ArrayList<>();
+               // add a bunch of ips to the whitelist
+
+               for (int i = 0; i < 255; i++) {
+                       for (int j = 0; j < 255; j++) {
+                               int a = ThreadLocalRandom.current().nextInt(1, 
254 + 1);
+                               int b = ThreadLocalRandom.current().nextInt(1, 
254 + 1);
+                               int c = ThreadLocalRandom.current().nextInt(1, 
254 + 1);
+                               int d = ThreadLocalRandom.current().nextInt(1, 
254 + 1);
+                               tempList.add(String.format("%s.%s.%s.%s", a, b, 
c, d));
+                       }
+               }
+
+               long startTime = System.nanoTime();
+
+               for (int i = 0; i < tempList.size(); i++) {
+                       whitelist.add(tempList.get(i) + "/32");
+               }
+
+               long durationTime = System.nanoTime() - startTime;
+
+               System.out.println(String.format("Anonymous IP Whitelist 
creation took %s nanoseconds to create tree of %d subnets", 
Long.toString(durationTime),
+                               tempList.size()));
+
+               int total = 1000;
+
+               long start = System.nanoTime();
+
+               for (int i = 0; i <= total; i++) {
+                       whitelist.contains("192.168.30.1");
+               }
+
+               long duration = System.nanoTime() - start;
+
+               System.out.println(
+                               String.format("Anonymous IP Whitelist average 
lookup took %s nanoseconds for %d ips", Long.toString(duration / total), 
tempList.size()));
+       }
+       */
+       @Test
+       public void testAddSubnets() throws NetworkNodeException {
+               AnonymousIpWhitelist whitelist = new AnonymousIpWhitelist();
+
+               whitelist.add("192.168.1.1/32");
+               assertThat(whitelist.contains("192.168.1.1"), equalTo(true));
+
+               whitelist.add("192.168.1.0/24");
+               assertThat(whitelist.contains("192.168.1.255"), equalTo(true));
+               assertThat(whitelist.contains("192.168.1.167"), equalTo(true));
+
+               whitelist.add("192.168.1.0/27");
+               assertThat(whitelist.contains("192.168.1.255"), equalTo(true));
+               assertThat(whitelist.contains("192.168.1.167"), equalTo(true));
+
+               whitelist.add("10.0.0.1/32");
+               assertThat(whitelist.contains("10.0.0.1"), equalTo(true));
+               assertThat(whitelist.contains("10.0.0.2"), equalTo(false));
+               assertThat(whitelist.contains("192.168.2.1"), equalTo(false));
+               assertThat(whitelist.contains("192.168.2.255"), equalTo(false));
+               assertThat(whitelist.contains("192.167.1.1"), equalTo(false));
+               assertThat(whitelist.contains("192.169.1.1"), equalTo(false));
+               assertThat(whitelist.contains("10.0.0.0"), equalTo(false));
+       }
+}
diff --git a/traffic_router/core/src/test/resources/anonymous_ip.json 
b/traffic_router/core/src/test/resources/anonymous_ip.json
new file mode 100644
index 000000000..05f686aa1
--- /dev/null
+++ b/traffic_router/core/src/test/resources/anonymous_ip.json
@@ -0,0 +1,18 @@
+{
+
+   "customer": "Cisco",
+   "version": "1",
+   "date" : "2017-05-23 03:28:25",
+   "name": "Anonymous IP Blocking Policy",
+
+   "anonymousIp": { "blockAnonymousVPN": true,
+                    "blockHostingProvider": true, 
+                    "blockPublicProxy": true,
+                    "blockTorExitNode": false},
+                    
+   "ip4Whitelist": ["192.168.30.0/24", "10.0.2.0/24", "5.34.32.0/24"],
+   
+   "ip6Whitelist": ["2001:550:90a::/48", "::1/128"],
+   
+   "redirectUrl": "http://youvebeenblocked.com";
+}
\ No newline at end of file
diff --git 
a/traffic_router/core/src/test/resources/anonymous_ip_no_whitelist.json 
b/traffic_router/core/src/test/resources/anonymous_ip_no_whitelist.json
new file mode 100644
index 000000000..1e0ba93b9
--- /dev/null
+++ b/traffic_router/core/src/test/resources/anonymous_ip_no_whitelist.json
@@ -0,0 +1,13 @@
+{
+
+   "customer": "Cisco",
+   "version": "1",
+   "date" : "2017-05-23 03:28:25",
+   "name": "Anonymous IP Blocking Policy",
+
+   "anonymousIp": { "blockAnonymousVPN": true,
+                    "blockHostingProvider": true, 
+                    "blockPublicProxy": true,
+                    "blockTorExitNode": false},
+   "redirectUrl": "http://youvebeenblocked.com";
+}
\ No newline at end of file


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to