Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/php
- <?php
- // Configuration
- define('CROWDSEC_API_URL', 'http://127.0.0.1:8080/v1/decisions'); // Adjust CrowdSec API URL
- define('CROWDSEC_API_KEY', 'api-key-here'); // Replace with your CrowdSec API key
- define('FIREWALLD_IPSETS_DIR', '/etc/firewalld/ipsets/');
- define('IPSET_NAME_IPV4', 'crowdsec-banned-ipv4');
- define('IPSET_NAME_IPV6', 'crowdsec-banned-ipv6');
- define('LOG_FILE', '/var/log/php-bouncer.log');
- define('SLEEP_INTERVAL', 60); // Set the interval for the service in seconds
- // Ensure this script is run from the command line
- //if (php_sapi_name() !== 'cli') {
- // die("This script can only be run from the command line.\n");
- //}
- // Function to fetch decisions from CrowdSec
- function fetchDecisions() {
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, CROWDSEC_API_URL);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- 'X-Api-Key: ' . CROWDSEC_API_KEY,
- 'Accept: application/json'
- ]);
- $userAgent = "Mozilla/5.0 (compatible; MyCustomUserAgent/1.0)";
- curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- $response = curl_exec($ch);
- if (curl_errno($ch)) {
- echo "Curl error: " . curl_error($ch);
- return [];
- }
- curl_close($ch);
- return json_decode($response, true);
- }
- // Function to separate IPv4 and IPv6 addresses
- function separateIpAddresses($decisions) {
- $ipv4Addresses = [];
- $ipv6Addresses = [];
- foreach ($decisions as $decision) {
- $ip = $decision['value'];
- if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
- $ipv4Addresses[] = $ip;
- } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
- $ipv6Addresses[] = $ip;
- }
- }
- return [$ipv4Addresses, $ipv6Addresses];
- }
- // Function to load existing ipset entries from an XML file
- function loadIpset($ipsetName) {
- $ipsetFile = FIREWALLD_IPSETS_DIR . $ipsetName . '.xml';
- $ipAddresses = [];
- if (file_exists($ipsetFile)) {
- $xml = simplexml_load_file($ipsetFile);
- foreach ($xml->entry as $entry) {
- $ipAddresses[] = (string) $entry;
- }
- }
- return $ipAddresses;
- }
- // Function to update firewalld ipset file only if changes are needed
- function updateIpsetIfNeeded($ipAddresses, $ipsetName, $type, $iptype) {
- $existingIps = loadIpset($ipsetName);
- sort($ipAddresses);
- sort($existingIps);
- // Check if there are any changes
- if ($ipAddresses === $existingIps) {
- echo "No changes needed for $ipsetName.\n";
- return false;
- }
- // Create new XML structure
- $xml = new SimpleXMLElement('<ipset></ipset>');
- $xml->addAttribute('type', $type); // 'hash:ip' for IPv4, 'hash:net' for IPv6
- $opt = $xml->addChild('option');
- $opt->addAttribute('name', 'family');
- $opt->addAttribute('value', $iptype);
- $opt = $xml->addChild('option');
- $opt->addAttribute('name', 'hashsize');
- $opt->addAttribute('value', '4096');
- $opt = $xml->addChild('option');
- $opt->addAttribute('name', 'maxelem');
- $opt->addAttribute('value', '1000000');
- foreach ($ipAddresses as $ip) {
- $entry = $xml->addChild('entry');
- $entry[0] = $ip;
- }
- // Save XML to ipset file
- $ipsetFile = FIREWALLD_IPSETS_DIR . $ipsetName . '.xml';
- $xml->asXML($ipsetFile);
- echo "Updated $ipsetName with new entries.\n";
- return true;
- }
- // Function to reload firewalld to apply changes
- function reloadFirewalld() {
- exec('firewall-cmd --reload', $output, $status);
- if ($status !== 0) {
- echo "Error reloading firewalld: " . implode("\n", $output) . "\n";
- }
- }
- function Run()
- {
- // Main script logic
- $decisions = fetchDecisions();
- if (!empty($decisions)) {
- list($ipv4Addresses, $ipv6Addresses) = separateIpAddresses($decisions);
- // Track if any changes were made
- $ipv4Updated = !empty($ipv4Addresses) ? updateIpsetIfNeeded($ipv4Addresses, IPSET_NAME_IPV4, 'hash:ip', 'inet') : false;
- $ipv6Updated = !empty($ipv6Addresses) ? updateIpsetIfNeeded($ipv6Addresses, IPSET_NAME_IPV6, 'hash:net', 'inet6') : false;
- //$ipv4Updated = true;
- //$ipv6Updated = true;
- // Reload firewalld only if there were changes
- if ($ipv4Updated || $ipv6Updated) {
- reloadFirewalld();
- logMessage("firewalld reloaded with new CrowdSec decisions for IPv4 and IPv6.");
- } else {
- //logMessage("No changes detected. firewalld reload not required.");
- }
- }
- else {
- logMessage("No decisions to update.");
- }
- // logMessage("Waiting for next iteration");
- //break;
- }
- // Flag to keep the service running
- $running = true;
- // Function to handle signals
- function signalHandler($signal) {
- global $running;
- switch ($signal) {
- case SIGTERM:
- case SIGINT:
- logMessage("Received termination signal. Stopping...");
- $running = false;
- break;
- }
- }
- // Attach signal handlers
- pcntl_signal(SIGTERM, "signalHandler");
- pcntl_signal(SIGINT, "signalHandler");
- // Function to log messages to a file
- function logMessage($message) {
- file_put_contents(LOG_FILE, date('Y-m-d H:i:s') . " - $message\n", FILE_APPEND);
- }
- // The main service function that runs the program logic
- function service($isService = false) {
- global $running;
- logMessage("Service started.");
- do {
- run();
- // Check for signals to allow graceful shutdown
- pcntl_signal_dispatch();
- // If running as a service, sleep for the specified interval before repeating
- if ($isService && $running) {
- sleep(SLEEP_INTERVAL);
- }
- } while ($isService && $running);
- logMessage("Service stopped.");
- }
- function isRunningAsService() {
- global $argv;
- return in_array('--service', $argv);
- }
- //chdir('/root');
- // Check if running from the command line or as a systemd service
- if (isRunningAsService()) {
- service(true);
- } else {
- service(false);
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement