Skip to content

Instantly share code, notes, and snippets.

@x-magic
Last active January 20, 2024 09:58
Show Gist options
  • Save x-magic/99f1ed7ca5ba9c9fc58a8d95140bfaba to your computer and use it in GitHub Desktop.
Save x-magic/99f1ed7ca5ba9c9fc58a8d95140bfaba to your computer and use it in GitHub Desktop.
Ban certain bittorrent clients on Aria2 with fail2ban
<?php
/*
* To block certain client when downloading and seeding with Aria2
*
* This will be triggered by CRON and write logs to a log file, where
* fail2ban will pick up and block the client
*
* Also probably run on PHP 8.x? I tested on PHP 8.2
*
* Remember to setup logrotate otherwise there will be too many logs!
*/
const LOG_FILE_PATH = "/var/log/aria2-block.log"; // remember to create the file as it's in /var/log so permission may be an issue
// Ensure log file is writable or just quit
if (is_writable(LOG_FILE_PATH) === false) exit(253);
const ARIA2RPC_HOST = "localhost";
const ARIA2RPC_PORT = 6800;
const ARIA2RPC_TOKEN = "<aria2 token>";
const ARIA2RPC_PROTOCOL = "https"; // or http - not accommodating websocket (ws/wss)
const ARIA2RPC_ENDPOINT = ARIA2RPC_PROTOCOL . "://" . ARIA2RPC_HOST . ":" . ARIA2RPC_PORT . "/jsonrpc";
const DISALLOWED_CLIENT_IDS = [
'XL',
'SD',
];
// Get all active downloads
$aria2_tasks = json_decode(file_post_contents(ARIA2RPC_ENDPOINT, [
'jsonrpc' => '2.0',
'id' => base64_encode("php-bt-fail2ban_" . microtime() . "_" . rand(100000, 999999)),
'method' => 'aria2.tellActive',
'params' => [
"token:" . ARIA2RPC_TOKEN,
[
'gid',
'status',
'connections',
],
],
]));
foreach ($aria2_tasks->result as $task) {
// Get task details
$aria2_task_details = json_decode(file_post_contents(ARIA2RPC_ENDPOINT, [
'jsonrpc' => '2.0',
'id' => base64_encode("php-bt-fail2ban_" . microtime() . "_" . rand(100000, 999999)),
'method' => 'aria2.getPeers',
'params' => [
"token:" . ARIA2RPC_TOKEN,
$task->gid,
],
]));
foreach ($aria2_task_details->result as $peer) {
// Decode peer id
$peer_id_decoded = urldecode($peer->peerId);
// Matching peer id with ban-list
if (preg_match("/^(-(" . implode("|", DISALLOWED_CLIENT_IDS) . ")\d{2,4}-)/", $peer_id_decoded, $peer_client)) {
// Write log entry for fail2ban
file_put_contents(
LOG_FILE_PATH,
time() . " aria2-rpc-block: gid[" . $task->gid . "] from [" . $peer->ip . "] Client:(" . $peer_client[1] . "+random)\n",
FILE_APPEND
);
}
}
}
// HTTP POST and JSON-related functions from https://stackoverflow.com/a/11319621/11296357
function file_post_contents($url, $data, $username = null, $password = null)
{
$post_data = json_encode($data);
if ($post_data === false) return false;
$opts = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/json',
'content' => $post_data,
],
'ssl' => [
"verify_peer" => false,
"verify_peer_name" => false,
],
];
if ($username && $password)
$opts['http']['header'] .= ("Authorization: Basic " . base64_encode("$username:$password"));
return file_get_contents($url, false, stream_context_create($opts));
}
# Run the script every two minutes
*/2 * * * * php /usr/local/bin/aria2-rpc-block.php >/dev/null 2>&1
# Fail2Ban filter for Aria2 invalid clients
# Detecting unwanted peers and block them based on peer id
# typically logged in /var/log/aria2-rpc-block.log
#
# Put into /etc/fail2ban/filter.d/aria2-rpc-block.conf
[Definition]
failregex = aria2-rpc-block: gid.* from \[<HOST>\] Client
# aria2-rpc-block.php jail
# Put into /etc/fail2ban/jail.d/aria2-rpc-block.conf
[aria2-rpc-block]
logpath = /var/log/aria2-block.log
filter = aria2-rpc-block
banaction = %(banaction_allports)s
bantime = 1d
maxentry = 1
enabled = true
# Rotate logs as this can generate quite a lot of logs
#
# Put into /etc/logrotate.d/aria2-rpc-block
/var/log/aria2-rpc-block.log {
daily
minsize 10M
rotate 7
copytruncate
compress
delaycompress
missingok
notifempty
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment