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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList LinuxFirewall::getExcludeRule(const QStringList& servers)
|
QStringList LinuxFirewall::getAllowRule(const QStringList& servers)
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
for (const QString& server : servers)
|
for (const QString& server : servers)
|
||||||
|
@ -178,6 +178,16 @@ QStringList LinuxFirewall::getExcludeRule(const QStringList& servers)
|
||||||
return result;
|
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()
|
void LinuxFirewall::install()
|
||||||
{
|
{
|
||||||
|
@ -237,10 +247,13 @@ void LinuxFirewall::install()
|
||||||
QStringLiteral("-o tun0+ -j ACCEPT"),
|
QStringLiteral("-o tun0+ -j ACCEPT"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
installAnchor(IPv4, QStringLiteral("120.blockNets"), {});
|
||||||
|
|
||||||
|
installAnchor(IPv4, QStringLiteral("110.allowNets"), {});
|
||||||
|
|
||||||
installAnchor(Both, QStringLiteral("100.blockAll"), {
|
installAnchor(Both, QStringLiteral("100.blockAll"), {
|
||||||
QStringLiteral("-j REJECT"),
|
QStringLiteral("-j REJECT"),
|
||||||
});
|
});
|
||||||
|
|
||||||
// NAT rules
|
// NAT rules
|
||||||
installAnchor(Both, QStringLiteral("100.transIp"), {
|
installAnchor(Both, QStringLiteral("100.transIp"), {
|
||||||
|
|
||||||
|
@ -309,6 +322,8 @@ void LinuxFirewall::uninstall()
|
||||||
uninstallAnchor(Both, QStringLiteral("290.allowDHCP"));
|
uninstallAnchor(Both, QStringLiteral("290.allowDHCP"));
|
||||||
uninstallAnchor(IPv6, QStringLiteral("250.blockIPv6"));
|
uninstallAnchor(IPv6, QStringLiteral("250.blockIPv6"));
|
||||||
uninstallAnchor(Both, QStringLiteral("200.allowVPN"));
|
uninstallAnchor(Both, QStringLiteral("200.allowVPN"));
|
||||||
|
uninstallAnchor(IPv4, QStringLiteral("120.blockNets"));
|
||||||
|
uninstallAnchor(IPv4, QStringLiteral("110.allowNets"));
|
||||||
uninstallAnchor(Both, QStringLiteral("100.blockAll"));
|
uninstallAnchor(Both, QStringLiteral("100.blockAll"));
|
||||||
|
|
||||||
// Remove Nat anchors
|
// Remove Nat anchors
|
||||||
|
@ -403,16 +418,25 @@ void LinuxFirewall::updateDNSServers(const QStringList& servers)
|
||||||
execute(QStringLiteral("iptables -A %1.320.allowDNS %2").arg(kAnchorName, rule));
|
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 {};
|
static QStringList existingServers {};
|
||||||
|
|
||||||
existingServers = servers;
|
existingServers = servers;
|
||||||
execute(QStringLiteral("iptables -F %1.100.blockAll").arg(kAnchorName));
|
execute(QStringLiteral("iptables -F %1.110.allowNets").arg(kAnchorName));
|
||||||
for (const QString& rule : getExcludeRule(servers))
|
for (const QString& rule : getAllowRule(servers))
|
||||||
execute(QStringLiteral("iptables -A %1.100.blockAll %2").arg(kAnchorName, rule));
|
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)
|
int waitForExitCode(QProcess& process)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,8 +12,8 @@ struct FirewallParams
|
||||||
QStringList dnsServers;
|
QStringList dnsServers;
|
||||||
// QSharedPointer<NetworkAdapter> adapter;
|
// QSharedPointer<NetworkAdapter> adapter;
|
||||||
QVector<QString> excludeApps; // Apps to exclude if VPN exemptions are enabled
|
QVector<QString> excludeApps; // Apps to exclude if VPN exemptions are enabled
|
||||||
|
QStringList allowAddrs;
|
||||||
QStringList excludeAddrs;
|
QStringList blockAddrs;
|
||||||
// The follow flags indicate which general rulesets are needed. Note that
|
// 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
|
// 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
|
// 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 allowLoopback; // Exempt loopback traffic
|
||||||
bool allowHnsd; // Exempt Handshake DNS traffic
|
bool allowHnsd; // Exempt Handshake DNS traffic
|
||||||
bool allowVpnExemptions; // Exempt specified traffic from the tunnel (route it over the physical uplink instead)
|
bool allowVpnExemptions; // Exempt specified traffic from the tunnel (route it over the physical uplink instead)
|
||||||
|
bool allowNets;
|
||||||
|
bool blockNets;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LinuxFirewall
|
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 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 void uninstallAnchor(IPVersion ip, const QString& anchor, const QString& tableName = kFilterTable);
|
||||||
static QStringList getDNSRules(const QStringList& servers);
|
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 setupTrafficSplitting();
|
||||||
static void teardownTrafficSplitting();
|
static void teardownTrafficSplitting();
|
||||||
static int execute(const QString& command, bool ignoreErrors = false);
|
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 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 replaceAnchor(LinuxFirewall::IPVersion ip, const QString &anchor, const QString &newRule, const QString& tableName);
|
||||||
static void updateDNSServers(const QStringList& servers);
|
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));
|
int err = uapiErrno(uapiCommand(message));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
logger.error() << "Interface configuration failed:" << strerror(err);
|
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 {};
|
applyFirewallRules(params);
|
||||||
params.dnsServers.append(config.m_dnsServer);
|
}
|
||||||
params.excludeAddrs.append(config.m_serverIpv4AddrIn);
|
|
||||||
applyFirewallRules(params);
|
|
||||||
|
|
||||||
return (err == 0);
|
return (err == 0);
|
||||||
}
|
}
|
||||||
|
@ -273,22 +287,19 @@ void WireguardUtilsLinux::applyFirewallRules(FirewallParams& params)
|
||||||
LinuxFirewall::ensureRootAnchorPriority();
|
LinuxFirewall::ensureRootAnchorPriority();
|
||||||
|
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), params.blockAll);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("200.allowVPN"), true);
|
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::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), 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::updateDNSServers(params.dnsServers);
|
||||||
LinuxFirewall::updateExcludeAddrs(params.excludeAddrs);
|
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), 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) {
|
bool WireguardUtilsLinux::updateRoutePrefix(const IPAddress& prefix) {
|
||||||
|
|
|
@ -144,12 +144,18 @@ uint OpenVpnProtocol::selectMgmtPort()
|
||||||
|
|
||||||
void OpenVpnProtocol::updateRouteGateway(QString line)
|
void OpenVpnProtocol::updateRouteGateway(QString line)
|
||||||
{
|
{
|
||||||
// TODO: fix for macos
|
if (line.contains("net_route_v4_best_gw")) {
|
||||||
line = line.split("ROUTE_GATEWAY", Qt::SkipEmptyParts).at(1);
|
QStringList params = line.split(" ");
|
||||||
if (!line.contains("/"))
|
if (params.size() == 6) {
|
||||||
return;
|
m_routeGateway = params.at(3);
|
||||||
m_routeGateway = line.split("/", Qt::SkipEmptyParts).first();
|
}
|
||||||
m_routeGateway.replace(" ", "");
|
} 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;
|
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);
|
updateRouteGateway(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "ikev2ConfigModel.h".h "
|
#include "ikev2ConfigModel.h"
|
||||||
|
|
||||||
#include "protocols/protocols_defs.h"
|
#include "protocols/protocols_defs.h"
|
||||||
|
|
||||||
|
|
|
@ -181,39 +181,7 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
|
||||||
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||||
// 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
|
|
||||||
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
||||||
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
||||||
bool blockAll = 0;
|
bool blockAll = 0;
|
||||||
|
@ -241,6 +209,31 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
|
||||||
allownets.append(v.toString());
|
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
|
// 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)
|
// 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