Introduction

Traffic Cop is a security-focused WordPress plugin primarily designed for developers and site operators. On this page you will mainly find the technical documentation of the plugin.

Obtaining a License and Configuration

You must obtain the license and complete the configuration before installation.

  • Register in the Shop
  • Click the confirmation link in the email you receive
  • Log in to the Shop
  • Create a billing profile in the Shop
  • Purchase the product in the Shop
  • Pay by credit card or bank transfer
  • Select the license in the Shop
  • Activate the license by entering the WordPress Address (URL, not the Site Address) in the Shop
  • Download the plugin from the Shop
  • Upload and activate the plugin in WordPress
  • Copy the license key from the Shop
  • Configure the license key in WordPress

Purchasing a License

The plugin is sold under a license. You can purchase it via the Cone Shop: https://shop.conedevelopment.com/traffic-cop. After registering, logging in, and providing your billing details, you can purchase licenses for as many sites as you need.

After the purchase, the system automatically generates a license key. First, you must activate your store URL for this key, and then, after installing the plugin, you must enter the license key in WordPress.

Activating the URL / Domain

You can access previously purchased licenses at https://shop.conedevelopment.com/account/licenses.

Within each license, you can associate your store’s URL with the license key, ensuring that later activation will succeed.

Installation

You can perform the installation after obtaining the license and completing the configuration.

Via the WordPress Plugin Manager

On the license settings page, select the desired version and download the plugin, which you can then install on your WordPress instance.

After downloading, locate the .zip file and upload it to the target WordPress instance.

  1. Navigate to Plugins → Add New.
  2. Click the Upload Plugin button at the top.
  3. In the new section that appears, click to choose a file, then select the .zip file you downloaded earlier.
  4. Click the Install Now button.

After the upload, you will see a screen confirming that the plugin has been successfully installed. This is a simple page where you can follow the steps of the installation process.

As you can see on this screen, you can activate the plugin immediately. Click the Activate Plugin button and your Traffic Cop plugin will start running.

If you skip activation on this page, you can always activate (enable/disable), delete, or update the plugin later under Plugins → Installed Plugins.

After activation, you can find the plugin settings under Settings → Traffic Cop.

Here you can assign the license key to the plugin. This is an important step, because without validation the plugin will not work, and updates cannot be downloaded via the WordPress system.

Via the Composer Package Manager

Composer is a widely used dependency manager for PHP applications. In some setups, you may want to manage your WordPress installation and its dependencies with Composer.

The example composer.json below shows how to configure the conedevelopment/traffic-cop package so that Composer can download it from the correct location.

{
    "name": "conedevelopment/example-wp-composer",
    "description": "Example WordPress with Composer",
    "license": "MIT",
    "require": {
        "php": "^8.3.0",
        "conedevelopment/traffic-cop": "^1.0.0",
        "roots/wordpress": "^6.6.0"
    },
    "minimum-stability": "beta",
    "config": {
        "preferred-install": {
            "*": "dist"
        },
        "allow-plugins": {
            "composer/installers": true,
            "ffraenz/private-composer-installer": true,
            "roots/wordpress-core-installer": true
        }
    },
    "extra": {
        "installer-paths": {
            "wp-content/mu-plugins/{$name}/": [
                "type:wordpress-muplugin"
            ],
            "wp-content/plugins/{$name}/": [
                "type:wordpress-plugin"
            ],
            "wp-content/themes/{$name}/": [
                "type:wordpress-theme"
            ]
        }
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://wpackagist.org"
        },
        {
            "type": "package",
            "package": {
                "name": "conedevelopment/traffic-cop",
                "version": "1.0.0",
                "type": "wordpress-plugin",
                "dist": {
                    "type": "zip",
                    "url": "https://shop.conedevelopment.com/api/packages/{%CONE_LICENSE_KEY}/download?type=composer&version=v{%VERSION}"
                },
                "require": {
                    "composer/installers": "^2.3.0",
                    "ffraenz/private-composer-installer": "^5.0"
                }
            }
        }
    ]
}

The {%VERSION} placeholder resolves to the value of the version key, 1.0.0 in this case. However, it is not recommended to store {%CONE_LICENSE_KEY} directly in composer.json (especially if this file is tracked in Git). Instead, you should place it in an environment variable. This can be a .env variable or an environment variable defined in your CI (GitHub Actions, GitLab CI, etc.):

# Not a real license key!

CONE_LICENSE_KEY=eb819bed-ba18-4e60-9d95-d6d6b5d4364c

WAF

The purpose of the WAF (Web Application Firewall) feature is to filter HTTP requests based on certain rules and block those that are caught by the filter before they put load on the server.

Ideally, this functionality is implemented outside of WordPress, but on shared hosting it is often not available, so an alternative solution is needed. The plugin provides this alternative.

Its operation is very simple: it uses an IP address list that has been continuously maintained for about 10 years and contains IP addresses that send malicious HTTP requests. If the IP address appears in one of the blocked ranges, the plugin responds to the HTTP request with a 403 (Forbidden) HTTP status, thereby minimizing the load on the server.

Settings

You can find the WAF settings under SettingsTraffic CopWAF.

Rate Limiter

The Rate Limiter feature is intended to limit certain HTTP requests (e.g. bot requests) within a given time window (e.g. 10 seconds), for example to 3 requests within that window.

This is necessary because content-scanning bots (e.g. Google bot, Facebook bot) can generate significant load on the server in a very short time. This slows down the site and every related process, degrades the user experience, and can sometimes make the interface temporarily unusable.

Currently, you can choose from three Rate Limiter drivers: Transient, Redis, and Shmop.

Environment configuration using .htaccess

If we want, we can pass values corresponding to the desired rules to the Rate Limiter using .htaccess. For example:

RewriteCond %{HTTP_USER_AGENT} "^Mozilla.*(Chrome|Firefox|Safari)"
RewriteCond %{HTTP_ACCEPT_LANGUAGE} "^$"
RewriteCond %{HTTP_ACCEPT_ENCODING} "^gzip$"
RewriteCond %{HTTP_CONNECTION} "^keep-alive$"
RewriteCond %{HTTP_REFERER} "."
RewriteRule ^ - [E=RATE_LIMIT_KEY:Chinese-attacker,E=RATE_LIMIT_INTERVAL:10,E=RATE_LIMIT_LIMIT:1]

Important, the RATE_LIMIT_KEY, RATE_LIMIT_INTERVAL and RATE_LIMIT_LIMIT env variables must be specified in all cases.

Transient Driver

Transients are part of the WordPress core API. This option can be used without any prior setup or configuration.

Redis Driver

Redis is an open-source, in-memory, NoSQL key–value store that provides fast data processing. Because of its flexibility and speed, it is recommended when your site handles a higher volume of traffic.

Using this driver requires the redis PHP extension and the appropriate configuration in the wp-config.php file:

// e.g.:
define('TRAFFIC_COP_REDIS_CONFIG', [
    'host' => '127.0.0.1',
    'port' => 6379,
    'auth' => 'password', // ['user', 'password']
    'database' => 0,
]);

Shmop Driver

The "shmop" (shared memory operation) extension is a PHP module that allows simple handling of shared memory segments on Unix-based systems. It provides functions in PHP for reading, writing, creating, and deleting shared memory segments.

Using this driver requires the shmop extension to be installed.

Settings

You can find the Rate Limiter settings under SettingsTraffic CopRate Limiter.

Hook Index

The plugin allows you to influence its behavior through filters. By using these hooks correctly, you can implement highly customized solutions.

traffic-cop_waf_ip (Filter)

If we want to resolve the IP address based on unique logic, we can do this with the traffic-waf_ip filter:

add_filter('traffic-cop_waf_ip', function (string $ip): string {
    return $ip;
});

traffic-cop_waf_blocked (Action)

If we want to take action when the WAF blocked a HTTP request, we can do this with the traffic-cop_waf_blocked action:

add_action('traffic-cop_waf_blocked', function (string $rule, string $value): void {
    match ($rule) {
        'ip_rule' => handleIpRule($value),
        'uri_rule' => handleUriRule($value),
        default => null,
    };
});

traffic-cop_waf_ip_bypass (Filter)

If you want to explicitly allow or, conversely, block a specific IP address—regardless of whether it is present in the IP list—you can do so with the traffic-cop_waf_ip_bypass filter:

add_filter('traffic-cop_waf_ip_bypass', function (?bool $pass, string $ip): ?bool {
    return match (true) {
        in_array($ip, $enabled) => true,
        in_array($ip, $blocked) => false,
        default => $pass,
    };
}, 10, 2);

traffic-cop_rate_limiter_key (Filter)

If you want to modify the Rate Limiter key (that is, the value used to distinguish between individual HTTP requests), you can do so with the traffic-cop_rate_limiter_key filter:

add_filter('traffic-cop_rate_limiter_key', function (string $key): string {
    return $_SERVER['REMOTE_ADDR'];
});

traffic-cop_rate_limiter_limit (Filter)

If you want to modify the limit applied to a given key within the configured interval, you can do so with the traffic-cop_rate_limiter_limit filter:

add_filter('traffic-cop_rate_limiter_limit', function (int $limit): int {
    return match (true) {
        isBot() => 1,
        default => $limit,
    };
});

traffic-cop_rate_limiter_interval (Filter)

If you want to modify the time interval itself, you can do so with the traffic-cop_rate_limiter_interval filter:

add_filter('traffic-cop_rate_limiter_interval', function (int $interval): int {
    return match (true) {
        isBot() => 10,
        default => $interval,
    };
});

traffic-cop_should_be_rate_limited (Filter)

If you want to control, using custom logic, for which requests the rate limit should apply, you can do so with the traffic-cop_should_be_rate_limited filter:

add_filter('traffic-cop_should_be_rate_limited', function (bool $limited): bool {
    return match (true) {
        isBot() => true,
        default => false,
    };
});

traffic-cop_rate_limit_hit (Action)

If we want to perform an action when the Rate Limiter has run out, we can do this with the traffic-cop_rate_limit_hit action:

add_action('traffic-cop_rate_limit_hit', function (string $ip): void {
    //
});

traffic-cop_rate_limit_blocked (Action)

If we want to perform an action if the Rate Limiter has reached the limit and blocked the request, we can do this with the traffic-cop_rate_limit_blocked action:

add_action('traffic-cop_rate_limit_blocked', function (string $ip): void {
    //
});