/* * BastionGuard™ * Copyright (C) 2025–2026 Calogero Scarnà * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * BastionGuard™ is a trademark of Calogero Scarnà. * The BastionGuard™ name and branding are not licensed under the GPL. */ #include "FirewallRuleManager.hpp" #include #include #include #include #include static bool is_valid_ip(const std::string& ip) { static const std::regex ipv4( R"(^(25[0-5]|2[0-4]\d|1?\d{1,2})(\.(25[0-5]|2[0-4]\d|1?\d{1,2})){3}$)" ); static const std::regex ipv6( R"(^(?:[0-9a-fA-F]{1,4}:){2,7}[0-9a-fA-F]{1,4}$)" ); return std::regex_match(ip, ipv4) || std::regex_match(ip, ipv6); } bool FirewallRuleManager::run(const std::string& cmd) { int r = std::system(cmd.c_str()); if (r != 0) std::cerr << _("[Firewall] Command failed: ") << cmd << "\n"; return r == 0; } void FirewallRuleManager::applyWithFirewalld(const std::vector& ips) { std::unordered_set filtered; for (const auto& ip : ips) { if (is_valid_ip(ip)) filtered.insert(ip); else std::cerr << _("[Firewall] SKIP non-IP: ") << ip << "\n"; } if (filtered.empty()) { std::cerr << _("[Firewall] Nessun IP valido da applicare.\n"); return; } run("pkexec firewall-cmd --permanent --new-ipset=bastionguard-blocklist " "--type=hash:ip --option=family=inet"); for (const auto& ip : filtered) { std::string cmd = "pkexec firewall-cmd --permanent " "--ipset=bastionguard-blocklist --add-entry=" + ip; run(cmd); } run("pkexec firewall-cmd --permanent " "--add-rich-rule='rule source ipset=\"bastionguard-blocklist\" reject'"); run("pkexec firewall-cmd --reload"); } void FirewallRuleManager::applyWithUfw(const std::vector& ips) { std::unordered_set filtered; for (const auto& ip : ips) { if (is_valid_ip(ip)) filtered.insert(ip); else std::cerr << _("[Firewall] SKIP non-IP: ") << ip << "\n"; } if (filtered.empty()) { std::cerr << _("[Firewall] Nessun IP valido da applicare.\n"); return; } for (const auto& ip : filtered) { run("pkexec ufw deny from " + ip); } run("pkexec ufw reload"); } void FirewallRuleManager::apply(FirewallType fw, const std::vector& ips) { switch (fw) { case FirewallType::FIREWALLD: std::cout << _("[Firewall] Applying rules with firewalld (ipset)\n"); applyWithFirewalld(ips); break; case FirewallType::UFW: std::cout << _("[Firewall] Applying rules with UFW\n"); applyWithUfw(ips); break; default: std::cerr << _("[Firewall] Nessun firewall selezionato.\n"); break; } }