summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOdd Stranne <odd@mullvad.net>2020-06-08 15:37:26 +0200
committerOdd Stranne <odd@mullvad.net>2020-06-09 10:12:07 +0200
commit9fd0d3024378a2755bc93da61a1569f03b13b071 (patch)
tree5d0738ce5d97a687e533e13f7f3dd7e72b8d2bac
parent5cde31bf205656e1a1f5c834b1e3d5c715bc4d12 (diff)
downloadmullvadvpn-9fd0d3024378a2755bc93da61a1569f03b13b071.tar.xz
mullvadvpn-9fd0d3024378a2755bc93da61a1569f03b13b071.zip
Install PermitVpnRelay rule into different sublayer based on relay port
-rw-r--r--windows/winfw/src/winfw/fwcontext.cpp117
-rw-r--r--windows/winfw/src/winfw/fwcontext.h11
2 files changed, 68 insertions, 60 deletions
diff --git a/windows/winfw/src/winfw/fwcontext.cpp b/windows/winfw/src/winfw/fwcontext.cpp
index 4883e6f6d8..7661fe95d4 100644
--- a/windows/winfw/src/winfw/fwcontext.cpp
+++ b/windows/winfw/src/winfw/fwcontext.cpp
@@ -11,14 +11,13 @@
#include "rules/baseline/permitlan.h"
#include "rules/baseline/permitlanservice.h"
#include "rules/baseline/permitloopback.h"
-#include "rules/baseline/permitvpnrelay.h"
#include "rules/baseline/permitvpntunnel.h"
#include "rules/baseline/permitvpntunnelservice.h"
#include "rules/baseline/permitping.h"
#include "rules/baseline/permitdns.h"
#include "rules/dns/blockall.h"
-#include "rules/dns/permitnontunnel.h"
#include "rules/dns/permittunnel.h"
+#include "rules/multi/permitvpnrelay.h"
#include <libwfp/transaction.h>
#include <libwfp/filterengine.h>
#include <libcommon/error.h>
@@ -30,12 +29,12 @@ using namespace rules;
namespace
{
-baseline::PermitVpnRelay::Protocol TranslateProtocol(WinFwProtocol protocol)
+multi::PermitVpnRelay::Protocol TranslateProtocol(WinFwProtocol protocol)
{
switch (protocol)
{
- case Tcp: return baseline::PermitVpnRelay::Protocol::Tcp;
- case Udp: return baseline::PermitVpnRelay::Protocol::Udp;
+ case Tcp: return multi::PermitVpnRelay::Protocol::Tcp;
+ case Udp: return multi::PermitVpnRelay::Protocol::Udp;
default:
{
THROW_ERROR("Missing case handler in switch clause");
@@ -48,16 +47,20 @@ baseline::PermitVpnRelay::Protocol TranslateProtocol(WinFwProtocol protocol)
// a local resolver to leave the machine. From the local resolver the request will either be
// resolved from cache, or forwarded out onto the Internet.
//
-// Therefore, whenever the PermitLan rule might be activated, we must also do proper DNS management
-// to prevent leaks.
+// Therefore, we're unconditionally lifting all DNS traffic out of the baseline sublayer and restricting
+// it in the DNS sublayer instead. The PermitDNS rule in the baseline sublayer accomplishes this.
+//
+// This has implications for the way the relay access is configured. In the regular case there
+// is no issue: The PermitVpnRelay rule can be installed in the baseline sublayer.
+//
+// However, if the relay is running on the DNS port (53), it would be blocked unless the DNS
+// sublayer permits this traffic. For this reason, whenever the relay is on port 53, the
+// PermitVpnRelay rule has to be installed to the DNS sublayer instead of the baseline sublayer.
//
void AppendSettingsRules
(
FwContext::Ruleset &ruleset,
- const WinFwSettings &settings,
- std::optional<std::wstring> tunnelInterfaceAlias = std::nullopt,
- std::optional<std::vector<wfp::IpAddress> > nonTunnelDnsServers = std::nullopt,
- std::optional<std::vector<wfp::IpAddress> > tunnelDnsServers = std::nullopt
+ const WinFwSettings &settings
)
{
if (settings.permitDhcp)
@@ -79,18 +82,32 @@ void AppendSettingsRules
ruleset.emplace_back(std::make_unique<baseline::PermitDns>());
ruleset.emplace_back(std::make_unique<dns::BlockAll>());
+}
- if (nonTunnelDnsServers.has_value())
- {
- ruleset.emplace_back(std::make_unique<dns::PermitNonTunnel>(
- tunnelInterfaceAlias, nonTunnelDnsServers.value()));
- }
+//
+// Refer comment on `AppendSettingsRules`.
+//
+void AppendRelayRules
+(
+ FwContext::Ruleset &ruleset,
+ const WinFwRelay &relay,
+ const std::vector<std::wstring> &approvedApplications
+)
+{
+ auto sublayer =
+ (
+ DNS_SERVER_PORT == relay.port
+ ? rules::multi::PermitVpnRelay::Sublayer::Dns
+ : rules::multi::PermitVpnRelay::Sublayer::Baseline
+ );
- if (tunnelInterfaceAlias.has_value() && tunnelDnsServers.has_value())
- {
- ruleset.emplace_back(std::make_unique<dns::PermitTunnel>(
- tunnelInterfaceAlias.value(), tunnelDnsServers.value()));
- }
+ ruleset.emplace_back(std::make_unique<multi::PermitVpnRelay>(
+ wfp::IpAddress(relay.ip),
+ relay.port,
+ TranslateProtocol(relay.protocol),
+ approvedApplications,
+ sublayer
+ ));
}
void AppendNetBlockedRules(FwContext::Ruleset &ruleset)
@@ -99,23 +116,15 @@ void AppendNetBlockedRules(FwContext::Ruleset &ruleset)
ruleset.emplace_back(std::make_unique<baseline::PermitLoopback>());
}
-std::optional<std::vector<wfp::IpAddress> >
-CreateRelayDnsExclusion(const WinFwRelay &relay)
-{
- if (relay.port != DNS_SERVER_PORT)
- {
- return std::nullopt;
- }
-
- std::vector<wfp::IpAddress> result = { wfp::IpAddress(relay.ip) };
-
- return std::move(result);
-}
-
} // anonymous namespace
-FwContext::FwContext(uint32_t timeout)
- : m_baseline(0)
+FwContext::FwContext
+(
+ uint32_t timeout,
+ const std::vector<std::wstring> &approvedApplications
+)
+ : m_approvedApplications(approvedApplications)
+ , m_baseline(0)
, m_activePolicy(Policy::None)
{
auto engine = wfp::FilterEngine::StandardSession(timeout);
@@ -134,8 +143,14 @@ FwContext::FwContext(uint32_t timeout)
m_activePolicy = Policy::None;
}
-FwContext::FwContext(uint32_t timeout, const WinFwSettings &settings)
- : m_baseline(0)
+FwContext::FwContext
+(
+ uint32_t timeout,
+ const WinFwSettings &settings,
+ const std::vector<std::wstring> &approvedApplications
+)
+ : m_approvedApplications(approvedApplications)
+ , m_baseline(0)
, m_activePolicy(Policy::None)
{
auto engine = wfp::FilterEngine::StandardSession(timeout);
@@ -166,13 +181,8 @@ bool FwContext::applyPolicyConnecting
Ruleset ruleset;
AppendNetBlockedRules(ruleset);
- AppendSettingsRules(ruleset, settings, std::nullopt, CreateRelayDnsExclusion(relay));
-
- ruleset.emplace_back(std::make_unique<baseline::PermitVpnRelay>(
- wfp::IpAddress(relay.ip),
- relay.port,
- TranslateProtocol(relay.protocol)
- ));
+ AppendSettingsRules(ruleset, settings);
+ AppendRelayRules(ruleset, relay, m_approvedApplications);
//
// Permit pinging the gateway inside the tunnel.
@@ -208,20 +218,11 @@ bool FwContext::applyPolicyConnected
Ruleset ruleset;
AppendNetBlockedRules(ruleset);
+ AppendSettingsRules(ruleset, settings);
+ AppendRelayRules(ruleset, relay, m_approvedApplications);
- AppendSettingsRules
- (
- ruleset,
- settings,
- std::make_optional<>(tunnelInterfaceAlias),
- CreateRelayDnsExclusion(relay),
- std::make_optional<>(tunnelDnsServers)
- );
-
- ruleset.emplace_back(std::make_unique<baseline::PermitVpnRelay>(
- wfp::IpAddress(relay.ip),
- relay.port,
- TranslateProtocol(relay.protocol)
+ ruleset.emplace_back(std::make_unique<dns::PermitTunnel>(
+ tunnelInterfaceAlias, tunnelDnsServers
));
ruleset.emplace_back(std::make_unique<baseline::PermitVpnTunnel>(
diff --git a/windows/winfw/src/winfw/fwcontext.h b/windows/winfw/src/winfw/fwcontext.h
index 6bdb398b16..fd8871e26b 100644
--- a/windows/winfw/src/winfw/fwcontext.h
+++ b/windows/winfw/src/winfw/fwcontext.h
@@ -13,10 +13,15 @@ class FwContext
{
public:
- FwContext(uint32_t timeout);
+ FwContext(uint32_t timeout, const std::vector<std::wstring> &approvedApplications);
// This ctor applies the "blocked" policy.
- FwContext(uint32_t timeout, const WinFwSettings &settings);
+ FwContext
+ (
+ uint32_t timeout,
+ const WinFwSettings &settings,
+ const std::vector<std::wstring> &approvedApplications
+ );
struct PingableHosts
{
@@ -69,6 +74,8 @@ private:
bool applyRuleset(const Ruleset &ruleset);
bool applyRulesetDirectly(const Ruleset &ruleset, SessionController &controller);
+ const std::vector<std::wstring> m_approvedApplications;
+
std::unique_ptr<SessionController> m_sessionController;
uint32_t m_baseline;