AI Engine Block Proxies & VPNs

Want to block proxies and VPNs from using your chatbots and forms? Here’s a way to do it for free (under 1000 queries per day) or for cheap if your needs exceed that.

No need for an API key if you have under 100 queries with unique IP addresses per day!

Installation

Add the following PHP snippet:

add_filter('mwai_ai_allowed', function($allowed, $query, $limits) {

    // BEGIN EDITABLE
    $allow_logged_in_to_use_vpn_proxies = true;
    $api_key = ''; // optionally enter your API key here for https://proxycheck.io/
    $error = 'To ensure fair usage and maintain equitable access to our services, we restrict the use of proxies and VPNs to registered users only. This measure prevents unregistered guests from exceeding their allocated usage limits.';
    // END EDITABLE

    if ($allow_logged_in_to_use_vpn_proxies && is_user_logged_in()) {
        return $allowed;
    }
    global $mwai_core;
    $ip = $mwai_core->get_ip_address();
    $transient_key = 'proxy_check_' . md5($ip);
    $cached_result = get_transient($transient_key);

    if ($cached_result !== false) {
        if ($cached_result === 'proxy') {
            ie_log('proxies',array($ip,"BLOCKED (cached)"));
            throw new Exception($error);
        }
        return $allowed;
    }

    $url = $api_key ? 'https://proxycheck.io/v2/'.$ip.'?key='.$api_key.'&vpn=1&asn=1' : 'https://proxycheck.io/v2/'.$ip.'?vpn=1&asn=1';
    $response = wp_remote_get($url);
    $body = wp_remote_retrieve_body($response);
    $data = json_decode($body, true);

    if (isset($data['status']) && ($data['status'] == 'ok' || $data['status'] == 'warning')) {
        $proxy = isset($data[$ip]) && isset($data[$ip]['proxy']) && $data[$ip]['proxy'] == 'yes';
        if ($proxy) {
            ie_log('proxies',array($ip,$data,"BLOCKED"));
            set_transient($transient_key, 'proxy', 90 * DAY_IN_SECONDS);
            throw new Exception($error);
        }
        set_transient($transient_key, 'not_proxy', 90 * DAY_IN_SECONDS);
    }

    return $allowed;
}, 10, 3);

if (!function_exists('ie_log')) {
    function ie_log($type, $data, $max_entries = 100) {
        // Check if user is logged in and get the user ID or 'guest'
        $user_id = get_current_user_id();
        $user_identifier = $user_id ? $user_id : 'guest';

        // Retrieve the current log for the specified type
        $log = get_transient('ie_log_' . $type);
        if (!$log) {
            $log = array();
        }

        // Prepend the new log entry, including the user identifier
        array_unshift($log, array(
            'time' => current_time('mysql'),
            'user' => $user_identifier,
            'data' => $data,
        ));

        // Limit the number of log entries
        $log = array_slice($log, 0, $max_entries);

        // Update the transient
        set_transient('ie_log_' . $type, $log, DAY_IN_SECONDS);
    }
    function ie_log_dashboard_widget($type) {
        // Check if the current user has the 'manage_options' capability
        if (current_user_can('manage_options')) {
            wp_add_dashboard_widget(
                'ie_log_dashboard_widget_' . $type, // Widget ID
                ucwords(str_replace('-', ' ', $type)) . ' Logs', // Title
                function() use ($type) { // Display callback
                    $log = get_transient('ie_log_' . $type);
                    if ($log) {
                        echo '<div style="max-height:400px; overflow:auto;">';
                        foreach ($log as $entry) {
                            echo '<pre>';
                            echo '[' . htmlspecialchars($entry['time']) . '] ';
                            echo 'User: ' . htmlspecialchars($entry['user']) . ' ';
                            // Use htmlspecialchars for displaying $entry['data']
                            if (is_array($entry['data']) || is_object($entry['data'])) {
                                // Convert array or object to a string representation
                                $dataString = print_r($entry['data'], true);
                                echo htmlspecialchars($dataString);
                            } else {
                                // Directly apply htmlspecialchars if it's already a string
                                echo htmlspecialchars($entry['data']);
                            }
                            echo '</pre>';
                        }
                        echo '</div>';
                    } else {
                        echo '<p>No logs found.</p>';
                    }
                }
            );
        }
    }    
}
add_action('wp_dashboard_setup', function() {
    ie_log_dashboard_widget('proxies');
});

Customization

  • Add your free API key from ProxyCheck’s website into the $api_key variable at the top of the script if you need over 100 queries with unique IPs per day.
  • Set $allow_logged_in_to_use_vpn_proxies to false if you do not wish to exempt logged in users from proxy and VPN checks.
  • If you disable the exemption, make sure to change the error message in $error to reflect that.

Logging

By default, the last 100 blocked queries will appear on your admin dashboard in the “Proxies Log” widget.


Let’s enhance your business! I can help you develop custom AI engine extensions or broader AI strategies.
Contact me.

Leave a Reply

Your email address will not be published. Required fields are marked *