Added basic abuse monitoring and report (Spec 11)

This commit is contained in:
Pinga 2023-12-09 12:41:41 +02:00
parent a453a6d745
commit 55fbbfd503
5 changed files with 161 additions and 28 deletions

View file

@ -53,7 +53,7 @@ Namingo is equipped with a comprehensive suite of features to meet the diverse n
- **GDPR-Compliant Database Encryption**: Supports comprehensive database encryption to ensure GDPR compliance. For more details, see our [Encryption Guide](docs/encryption.md).
- **Automation Scripts**: Ensures the continuous and smooth operation of the registry by performing routine checks and operations. Advanced scripting capabilities also facilitate the generation of RDE deposits, the creation of ICANN's monthly reports, and ensure full compliance with other ICANN gTLD requirements for streamlined regulatory adherence.
- **Automation Scripts**: Ensures the continuous and smooth operation of the registry by performing routine checks and operations. Advanced scripting capabilities also facilitate the generation of RDE deposits, the creation of ICANN's monthly reports, Spec 11 abuse monitoring, and ensure full compliance with other ICANN gTLD requirements for streamlined regulatory adherence.
## Installation Instructions

View file

@ -28,34 +28,12 @@ Coroutine::create(function () use ($pool, $log) {
try {
$pdo = $pool->get();
$stmt = $pdo->query('SELECT name, clid FROM domain');
// Get URLhaus data
$urlhausData = getUrlhausData();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$domain = $row['name'];
if (checkSpamhaus($domain)) {
$userStmt = $pdo->prepare('SELECT user_id FROM registrar_users WHERE registrar_id = ?');
$userStmt->execute([$row['clid']]);
$userData = $userStmt->fetch(PDO::FETCH_ASSOC);
if ($userData) {
// Prepare INSERT statement to add a ticket
$insertStmt = $pdo->prepare('INSERT INTO support_tickets (id, user_id, category_id, subject, message, status, priority, reported_domain, nature_of_abuse, evidence, relevant_urls, date_of_incident, date_created, last_updated) VALUES (NULL, ?, 8, ?, ?, "Open", "High", ?, "Abuse", ?, ?, ?, CURRENT_TIMESTAMP(3), CURRENT_TIMESTAMP(3))');
// Execute the prepared statement with appropriate values
$insertStmt->execute([
$userData['user_id'], // user_id
"Abuse Report for $domain", // subject
"Abuse detected for domain $domain.", // message
$domain, // reported_domain
"Link to Spamhaus", // evidence
"http://www.spamhaus.org/query/domain/$domain", // relevant_urls
date('Y-m-d H:i:s') // date_of_incident
]);
}
}
// Get URLhaus data
$urlhausData = getUrlhausData();
$urlhausResult = checkUrlhaus($domain, $urlhausData);
if ($urlhausResult) {
@ -79,6 +57,29 @@ Coroutine::create(function () use ($pool, $log) {
]);
}
}
if (checkSpamhaus($domain)) {
$userStmt = $pdo->prepare('SELECT user_id FROM registrar_users WHERE registrar_id = ?');
$userStmt->execute([$row['clid']]);
$userData = $userStmt->fetch(PDO::FETCH_ASSOC);
if ($userData) {
// Prepare INSERT statement to add a ticket
$insertStmt = $pdo->prepare('INSERT INTO support_tickets (id, user_id, category_id, subject, message, status, priority, reported_domain, nature_of_abuse, evidence, relevant_urls, date_of_incident, date_created, last_updated) VALUES (NULL, ?, 8, ?, ?, "Open", "High", ?, "Abuse", ?, ?, ?, CURRENT_TIMESTAMP(3), CURRENT_TIMESTAMP(3))');
// Execute the prepared statement with appropriate values
$insertStmt->execute([
$userData['user_id'], // user_id
"Abuse Report for $domain", // subject
"Abuse detected for domain $domain.", // message
$domain, // reported_domain
"Link to Spamhaus", // evidence
"http://www.spamhaus.org/query/domain/$domain", // relevant_urls
date('Y-m-d H:i:s') // date_of_incident
]);
}
}
}
$log->info('job finished successfully.');
} catch (PDOException $e) {

111
automation/abusereport.php Normal file
View file

@ -0,0 +1,111 @@
<?php
require __DIR__ . '/vendor/autoload.php';
$c = require_once 'config.php';
require_once 'helpers.php';
// Connect to the database
$dsn = "{$c['db_type']}:host={$c['db_host']};dbname={$c['db_database']}";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$logFilePath = '/var/log/namingo/abusereport.log';
$log = setupLogger($logFilePath, 'Abuse_Report');
$log->info('job started.');
try {
$dbh = new PDO($dsn, $c['db_username'], $c['db_password'], $options);
} catch (PDOException $e) {
$log->error('DB Connection failed: ' . $e->getMessage());
}
try {
// Prepare and execute the query
$query = "SELECT reported_domain, nature_of_abuse, status, priority, date_of_incident, date_created FROM support_tickets WHERE category_id = '8'";
$stmt = $dbh->query($query);
// Fetch all rows
$tickets = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Start HTML output
$html = "<!DOCTYPE html>
<html>
<head>
<title>Abuse Report</title>
</head>
<body>
<h1>Abuse Report</h1>
<p>Report Date: " . date('Y-m-d H:i:s') . "</p>"; // Display report generation date
if (empty($tickets)) {
$html .= "<p>No abuse cases found for the period.</p>"; // Message if no tickets
} else {
// Continue with the table if tickets are found
$html .= "<table border='1'>
<tr>
<th>Reported Domain</th>
<th>Nature of Abuse</th>
<th>Status</th>
<th>Priority</th>
<th>Date of Incident</th>
<th>Date Reported</th>
</tr>";
// Loop through tickets and add rows to the table
foreach ($tickets as $ticket) {
$html .= "<tr>
<td>" . htmlspecialchars($ticket['reported_domain']) . "</td>
<td>" . htmlspecialchars($ticket['nature_of_abuse']) . "</td>
<td>" . htmlspecialchars($ticket['status']) . "</td>
<td>" . htmlspecialchars($ticket['priority']) . "</td>
<td>" . htmlspecialchars($ticket['date_of_incident']) . "</td>
<td>" . htmlspecialchars($ticket['date_created']) . "</td>
</tr>";
}
$html .= "</table>"; // Close the table
}
// End HTML
$html .= "</body>
</html>";
// Prepare the data array
$data = [
'type' => 'sendmail',
'toEmail' => $toEmail,
'subject' => 'Abuse Report',
'body' => $html,
];
$url = 'http://127.0.0.1:8250';
$options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen(json_encode($data))
],
];
$curl = curl_init($url);
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
if ($response === false) {
throw new Exception(curl_error($curl), curl_errno($curl));
}
curl_close($curl);
$log->info('job finished successfully.');
} catch (PDOException $e) {
$log->error('Database error: ' . $e->getMessage());
} catch (Throwable $e) {
$log->error('Error: ' . $e->getMessage());
}

View file

@ -18,6 +18,9 @@
# run abusemonitor.php every hour
30 * * * * root /usr/bin/php8.2 /opt/registry/automation/abusemonitor.php
# run abusereport.php every day
5 0 * * * root /usr/bin/php8.2 /opt/registry/automation/abusereport.php
# run send-invoice.php every 1st day
1 0 1 * * root /usr/bin/php8.2 /opt/registry/automation/send-invoice.php

View file

@ -7,6 +7,8 @@ use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\LineFormatter;
use Ds\Map;
use Swoole\Coroutine;
use Swoole\Coroutine\Http\Client;
/**
* Sets up and returns a Logger instance.
@ -68,9 +70,25 @@ function checkSpamhaus($domain) {
function getUrlhausData() {
$urlhausUrl = 'https://urlhaus.abuse.ch/downloads/json_recent/';
$json = file_get_contents($urlhausUrl);
$data = json_decode($json, true);
$map = new Map();
$data = [];
Coroutine::create(function () use ($urlhausUrl, &$data) {
$client = new Client('urlhaus.abuse.ch', 443, true); // SSL
$client->set(['timeout' => 5]); // 5 seconds timeout
$client->get('/downloads/json_recent/');
if ($client->statusCode == 200) {
$data = json_decode($client->body, true);
}
$client->close();
});
return processUrlhausData($data);
}
function processUrlhausData($data) {
$map = new \Ds\Map();
foreach ($data as $entry) {
foreach ($entry as $urlData) {