BastionGuard/src/firewall/FirewallRuleManager.cpp
specialworld83 d34e319fbe Public release
2026-02-27 21:37:06 +01:00

118 lines
3.4 KiB
C++

/*
* 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 <https://www.gnu.org/licenses/>.
*
* BastionGuard™ is a trademark of Calogero Scarnà.
* The BastionGuard™ name and branding are not licensed under the GPL.
*/
#include "FirewallRuleManager.hpp"
#include <iostream>
#include <regex>
#include <unordered_set>
#include <sstream>
#include <glib/gi18n.h>
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<std::string>& ips) {
std::unordered_set<std::string> 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<std::string>& ips) {
std::unordered_set<std::string> 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<std::string>& 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;
}
}