Use MacOS logic for LinuxFirewall
This commit is contained in:
parent
874de74ac8
commit
5c9d45a8a8
6 changed files with 104 additions and 66 deletions
|
@ -168,7 +168,7 @@ QStringList LinuxFirewall::getDNSRules(const QStringList& servers)
|
|||
return result;
|
||||
}
|
||||
|
||||
QStringList LinuxFirewall::getExcludeRule(const QStringList& servers)
|
||||
QStringList LinuxFirewall::getAllowRule(const QStringList& servers)
|
||||
{
|
||||
QStringList result;
|
||||
for (const QString& server : servers)
|
||||
|
@ -178,6 +178,16 @@ QStringList LinuxFirewall::getExcludeRule(const QStringList& servers)
|
|||
return result;
|
||||
}
|
||||
|
||||
QStringList LinuxFirewall::getBlockRule(const QStringList& servers)
|
||||
{
|
||||
QStringList result;
|
||||
for (const QString& server : servers)
|
||||
{
|
||||
result << QStringLiteral("-d %1 -j REJECT").arg(server);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void LinuxFirewall::install()
|
||||
{
|
||||
|
@ -237,10 +247,13 @@ void LinuxFirewall::install()
|
|||
QStringLiteral("-o tun0+ -j ACCEPT"),
|
||||
});
|
||||
|
||||
installAnchor(IPv4, QStringLiteral("120.blockNets"), {});
|
||||
|
||||
installAnchor(IPv4, QStringLiteral("110.allowNets"), {});
|
||||
|
||||
installAnchor(Both, QStringLiteral("100.blockAll"), {
|
||||
QStringLiteral("-j REJECT"),
|
||||
});
|
||||
|
||||
// NAT rules
|
||||
installAnchor(Both, QStringLiteral("100.transIp"), {
|
||||
|
||||
|
@ -309,6 +322,8 @@ void LinuxFirewall::uninstall()
|
|||
uninstallAnchor(Both, QStringLiteral("290.allowDHCP"));
|
||||
uninstallAnchor(IPv6, QStringLiteral("250.blockIPv6"));
|
||||
uninstallAnchor(Both, QStringLiteral("200.allowVPN"));
|
||||
uninstallAnchor(IPv4, QStringLiteral("120.blockNets"));
|
||||
uninstallAnchor(IPv4, QStringLiteral("110.allowNets"));
|
||||
uninstallAnchor(Both, QStringLiteral("100.blockAll"));
|
||||
|
||||
// Remove Nat anchors
|
||||
|
@ -403,16 +418,25 @@ void LinuxFirewall::updateDNSServers(const QStringList& servers)
|
|||
execute(QStringLiteral("iptables -A %1.320.allowDNS %2").arg(kAnchorName, rule));
|
||||
}
|
||||
|
||||
void LinuxFirewall::updateExcludeAddrs(const QStringList& servers)
|
||||
void LinuxFirewall::updateAllowNets(const QStringList& servers)
|
||||
{
|
||||
static QStringList existingServers {};
|
||||
|
||||
existingServers = servers;
|
||||
execute(QStringLiteral("iptables -F %1.100.blockAll").arg(kAnchorName));
|
||||
for (const QString& rule : getExcludeRule(servers))
|
||||
execute(QStringLiteral("iptables -A %1.100.blockAll %2").arg(kAnchorName, rule));
|
||||
execute(QStringLiteral("iptables -F %1.110.allowNets").arg(kAnchorName));
|
||||
for (const QString& rule : getAllowRule(servers))
|
||||
execute(QStringLiteral("iptables -A %1.110.allowNets %2").arg(kAnchorName, rule));
|
||||
}
|
||||
|
||||
void LinuxFirewall::updateBlockNets(const QStringList& servers)
|
||||
{
|
||||
static QStringList existingServers {};
|
||||
|
||||
existingServers = servers;
|
||||
execute(QStringLiteral("iptables -F %1.120.blockNets").arg(kAnchorName));
|
||||
for (const QString& rule : getBlockRule(servers))
|
||||
execute(QStringLiteral("iptables -A %1.120.blockNets %2").arg(kAnchorName, rule));
|
||||
}
|
||||
|
||||
int waitForExitCode(QProcess& process)
|
||||
{
|
||||
|
|
|
@ -12,8 +12,8 @@ struct FirewallParams
|
|||
QStringList dnsServers;
|
||||
// QSharedPointer<NetworkAdapter> adapter;
|
||||
QVector<QString> excludeApps; // Apps to exclude if VPN exemptions are enabled
|
||||
|
||||
QStringList excludeAddrs;
|
||||
QStringList allowAddrs;
|
||||
QStringList blockAddrs;
|
||||
// The follow flags indicate which general rulesets are needed. Note that
|
||||
// this is after some sanity filtering, i.e. an allow rule may be listed
|
||||
// as not needed if there were no block rules preceding it. The rulesets
|
||||
|
@ -29,6 +29,8 @@ struct FirewallParams
|
|||
bool allowLoopback; // Exempt loopback traffic
|
||||
bool allowHnsd; // Exempt Handshake DNS traffic
|
||||
bool allowVpnExemptions; // Exempt specified traffic from the tunnel (route it over the physical uplink instead)
|
||||
bool allowNets;
|
||||
bool blockNets;
|
||||
};
|
||||
|
||||
class LinuxFirewall
|
||||
|
@ -47,7 +49,8 @@ private:
|
|||
static void installAnchor(IPVersion ip, const QString& anchor, const QStringList& rules, const QString& tableName = kFilterTable, const FilterCallbackFunc& enableFunc = {}, const FilterCallbackFunc& disableFunc = {});
|
||||
static void uninstallAnchor(IPVersion ip, const QString& anchor, const QString& tableName = kFilterTable);
|
||||
static QStringList getDNSRules(const QStringList& servers);
|
||||
static QStringList getExcludeRule(const QStringList& servers);
|
||||
static QStringList getAllowRule(const QStringList& servers);
|
||||
static QStringList getBlockRule(const QStringList& servers);
|
||||
static void setupTrafficSplitting();
|
||||
static void teardownTrafficSplitting();
|
||||
static int execute(const QString& command, bool ignoreErrors = false);
|
||||
|
@ -66,7 +69,8 @@ public:
|
|||
static void setAnchorEnabled(IPVersion ip, const QString& anchor, bool enabled, const QString& tableName = kFilterTable);
|
||||
static void replaceAnchor(LinuxFirewall::IPVersion ip, const QString &anchor, const QString &newRule, const QString& tableName);
|
||||
static void updateDNSServers(const QStringList& servers);
|
||||
static void updateExcludeAddrs(const QStringList& servers);
|
||||
static void updateAllowNets(const QStringList& servers);
|
||||
static void updateBlockNets(const QStringList& servers);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -118,12 +118,26 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
|
|||
int err = uapiErrno(uapiCommand(message));
|
||||
if (err != 0) {
|
||||
logger.error() << "Interface configuration failed:" << strerror(err);
|
||||
}
|
||||
} else {
|
||||
FirewallParams params { };
|
||||
params.dnsServers.append(config.m_dnsServer);
|
||||
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
|
||||
params.blockAll = true;
|
||||
if (config.m_excludedAddresses.size()) {
|
||||
params.allowNets = true;
|
||||
foreach (auto net, config.m_excludedAddresses) {
|
||||
params.allowAddrs.append(net.toUtf8());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
params.blockNets = true;
|
||||
foreach (auto net, config.m_allowedIPAddressRanges) {
|
||||
params.blockAddrs.append(net.toString());
|
||||
}
|
||||
}
|
||||
|
||||
FirewallParams params {};
|
||||
params.dnsServers.append(config.m_dnsServer);
|
||||
params.excludeAddrs.append(config.m_serverIpv4AddrIn);
|
||||
applyFirewallRules(params);
|
||||
applyFirewallRules(params);
|
||||
}
|
||||
|
||||
return (err == 0);
|
||||
}
|
||||
|
@ -273,22 +287,19 @@ void WireguardUtilsLinux::applyFirewallRules(FirewallParams& params)
|
|||
LinuxFirewall::ensureRootAnchorPriority();
|
||||
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("200.allowVPN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), params.blockAll);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("110.allowNets"), params.allowNets);
|
||||
LinuxFirewall::updateAllowNets(params.allowAddrs);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("120.blockNets"), params.blockNets);
|
||||
LinuxFirewall::updateBlockNets(params.blockAddrs);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("200.allowVPN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("310.blockDNS"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("310.blockDNS"), true);
|
||||
LinuxFirewall::updateDNSServers(params.dnsServers);
|
||||
LinuxFirewall::updateExcludeAddrs(params.excludeAddrs);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), true);
|
||||
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4,
|
||||
QStringLiteral("100.vpnTunOnly"),
|
||||
true,
|
||||
LinuxFirewall::kRawTable);
|
||||
|
||||
}
|
||||
|
||||
bool WireguardUtilsLinux::updateRoutePrefix(const IPAddress& prefix) {
|
||||
|
|
|
@ -144,12 +144,18 @@ uint OpenVpnProtocol::selectMgmtPort()
|
|||
|
||||
void OpenVpnProtocol::updateRouteGateway(QString line)
|
||||
{
|
||||
// TODO: fix for macos
|
||||
line = line.split("ROUTE_GATEWAY", Qt::SkipEmptyParts).at(1);
|
||||
if (!line.contains("/"))
|
||||
return;
|
||||
m_routeGateway = line.split("/", Qt::SkipEmptyParts).first();
|
||||
m_routeGateway.replace(" ", "");
|
||||
if (line.contains("net_route_v4_best_gw")) {
|
||||
QStringList params = line.split(" ");
|
||||
if (params.size() == 6) {
|
||||
m_routeGateway = params.at(3);
|
||||
}
|
||||
} else {
|
||||
line = line.split("ROUTE_GATEWAY", Qt::SkipEmptyParts).at(1);
|
||||
if (!line.contains("/"))
|
||||
return;
|
||||
m_routeGateway = line.split("/", Qt::SkipEmptyParts).first();
|
||||
m_routeGateway.replace(" ", "");
|
||||
}
|
||||
qDebug() << "Set VPN route gateway" << m_routeGateway;
|
||||
}
|
||||
|
||||
|
@ -288,7 +294,7 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
|
|||
}
|
||||
}
|
||||
|
||||
if (line.contains("ROUTE_GATEWAY")) {
|
||||
if (line.contains("ROUTE_GATEWAY") || line.contains("net_route_v4_best_gw")) {
|
||||
updateRouteGateway(line);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "ikev2ConfigModel.h".h "
|
||||
#include "ikev2ConfigModel.h"
|
||||
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
|
|
|
@ -181,39 +181,7 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
|
|||
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// double-check + ensure our firewall is installed and enabled
|
||||
if (!LinuxFirewall::isInstalled()) LinuxFirewall::install();
|
||||
|
||||
// Note: rule precedence is handled inside IpTablesFirewall
|
||||
LinuxFirewall::ensureRootAnchorPriority();
|
||||
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("200.allowVPN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), true);
|
||||
// LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("310.blockDNS"), true);
|
||||
QStringList serverAddr;
|
||||
serverAddr.append(configStr.value(amnezia::config_key::hostName).toString());
|
||||
LinuxFirewall::updateExcludeAddrs(serverAddr);
|
||||
QStringList dnsServers;
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns1).toString());
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns2).toString());
|
||||
dnsServers.append("127.0.0.1");
|
||||
dnsServers.append("127.0.0.53");
|
||||
LinuxFirewall::updateDNSServers(dnsServers);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), true);
|
||||
|
||||
// LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4,
|
||||
// QStringLiteral("100.vpnTunOnly"),
|
||||
// true,
|
||||
// LinuxFirewall::kRawTable);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
||||
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
||||
bool blockAll = 0;
|
||||
|
@ -241,6 +209,31 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
|
|||
allownets.append(v.toString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// double-check + ensure our firewall is installed and enabled
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), blockAll);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("110.allowNets"), allowNets);
|
||||
LinuxFirewall::updateAllowNets(allownets);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("120.blockNets"), blockAll);
|
||||
LinuxFirewall::updateBlockNets(blocknets);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("200.allowVPN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), true);
|
||||
QStringList dnsServers;
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns1).toString());
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns2).toString());
|
||||
dnsServers.append("127.0.0.1");
|
||||
dnsServers.append("127.0.0.53");
|
||||
LinuxFirewall::updateDNSServers(dnsServers);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), true);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
|
||||
// double-check + ensure our firewall is installed and enabled. This is necessary as
|
||||
// other software may disable pfctl before re-enabling with their own rules (e.g other VPNs)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue