#!/usr/local/psa/bin/sw-engine-pleskrun
<?php

// AbuseIPDB reporting script © Copyright 2025 Danami. All Rights Reserved.
$ip_address = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
$comment    = isset($_SERVER['argv'][6]) ? $_SERVER['argv'][6] : '';
$trigger    = isset($_SERVER['argv'][8]) ? $_SERVER['argv'][8] : '';
$api_key    = '';

// do not report blocks coming from other cluster members (only report attacks coming directly)
if ($trigger == 'LF_CLUSTER')
{
    exit(1);
}

// only valid non-private IP addresses are allowed
if (!filter_var($ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))
{
    exit(1);
}

/* get the API key */
$db = new mysqli('localhost', 'admin', trim(file_get_contents('/etc/psa/.psa.shadow')), 'danami_juggernaut');
if (mysqli_connect_errno())
{
    echo "Database connect failed: (" . mysqli_connect_errno() . ") " . mysqli_connect_error();
    exit(1);
}
$stmt  = $db->prepare("SELECT config_value FROM config WHERE group_name='networkinfo' AND config_key='abuseipdb_api_key' LIMIT 1;");
$query = $stmt->execute();
$stmt->bind_result($api_key);
$stmt->fetch();
$api_key = unserialize($api_key, array(FALSE));
if (!$api_key)
{
    exit(1);
}

// remove any data we do not want to include (like email addresses)
$comment = preg_replace('/\[.*\]/', '[redacted]', $comment);
$comment = preg_replace('/[^@\s]*@[^@\s]*\.[^@\s]*/', '[redacted]', $comment);
$comment = rtrim(preg_replace('/(?:\d+)? in the last \d+ secs/', '', $comment), ' ;:');
$comment = rtrim(preg_replace('/\d+ hits in the last \d+ seconds/', '', $comment), ' ;:');

// map keywords to AbuseIPDB categories
// see https://www.abuseipdb.com/categories
$keywords = array(
    'apache-overflows'  => array(15),
    'apache-referrers'  => array(19),
    'apache-scanners'   => array(14),
    'apache-useragents' => array(19),
    'ftpd'              => array(5, 18),
    'horde'             => array(18),
    'htpasswd'          => array(18),
    'imapd'             => array(18),
    'joomla'            => array(18),
    'mod_security'      => array(16),
    'opencart'          => array(18),
    'mysqld'            => array(18),
    'php-url-fopen'     => array(21),
    'plesk-panel'       => array(18),
    'pop3d'             => array(18),
    'symlink'           => array(15),
    'whmcs'             => array(18),
    'wordpress'         => array(18),
    'roundecube'        => array(18),
    'smtpauth'          => array(18),
    'sshd'              => array(18, 22),
);

// map csf triggers to AbuseIPDB categories
$triggers = array(
    'APACHE_401'    => array(19),
    'APACHE_403'    => array(19),
    'APACHE_404'    => array(19),
    'CT_LIMIT'      => array(4),
    'LF_BIND'       => array(2),
    'LF_DISTATTACK' => array(18),
    'LF_FTPD'       => array(5, 18),
    'LF_HTACCESS'   => array(18),
    'LF_IMAPD'      => array(18),
    'LF_POP3D'      => array(18),
    'LF_QOS'        => array(4),
    'LF_MODSEC'     => array(16),
    'LF_NETBLOCK'   => array(15),
    'LF_SMTPAUTH'   => array(18),
    'LF_SSHD'       => array(18, 22),
    'LF_SUHOSIN'    => array(21),
    'PS_LIMIT'      => array(14),
);

// match keywords
$categories = array();
foreach ($keywords as $key => $category)
{
    if (strpos($comment, $key) !== FALSE)
    {
        foreach ($category as $value)
        {
            $categories[$value] = $value;
        }
    }
}

// match triggers
if (isset($triggers[$trigger]))
{
    foreach ($triggers[$trigger] as $value)
    {
        $categories[$value] = $value;
    }
}

// set a default category of "hacking" if keywords or triggers did not match
if (!count($categories))
{
    $categories[] = 15;
}

// submit to the API
$request = curl_init('https://api.abuseipdb.com/api/v2/report');
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_CONNECTTIMEOUT, 8);
curl_setopt($request, CURLOPT_TIMEOUT, 30);
curl_setopt($request, CURLOPT_POSTFIELDS, http_build_query(array('ip' => $ip_address, 'categories' => implode(',', $categories), 'comment' => $comment)));
curl_setopt($request, CURLOPT_HTTPHEADER, array('Key: ' . $api_key, 'Accept: application/json'));
$response     = curl_exec($request);
$error        = curl_error($request);
$error_number = curl_errno($request);
curl_close($request);
if ($error_number)
{
    echo 'Error: ' . $error;
    exit($error_number);
}
echo $response;
exit(0);