summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-10-11 10:06:35 +0200
committerDavid Lönnhager <david.l@mullvad.net>2021-10-11 10:06:35 +0200
commit9c3b434bd4a087a15a98e67d270efb3f50fddb20 (patch)
treeee91bc405287a57b83c44eebb911524e986ea3f6
parent6aa2b5ce21d3b3f740ed241b5f659b022e4f9790 (diff)
parent2d31b521c6807f3f71562bda1963872f11797295 (diff)
downloadmullvadvpn-9c3b434bd4a087a15a98e67d270efb3f50fddb20.tar.xz
mullvadvpn-9c3b434bd4a087a15a98e67d270efb3f50fddb20.zip
Merge branch 'win-fix-fw-ndp'
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.lock4
-rw-r--r--docs/security.md15
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/firewall/linux.rs98
-rw-r--r--talpid-core/src/firewall/macos.rs106
-rw-r--r--talpid-core/src/firewall/mod.rs1
-rw-r--r--windows/winfw/src/winfw/mullvadguids.cpp60
-rw-r--r--windows/winfw/src/winfw/mullvadguids.h4
-rw-r--r--windows/winfw/src/winfw/rules/baseline/permitndp.cpp97
10 files changed, 321 insertions, 68 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e3d205723..517944c068 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -78,6 +78,8 @@ Line wrap the file at 100 chars. Th
- Read macOS scrollbar visibility settings to decide wheter or not the scrollbars should hide when
not scrolling.
- Fix desktop app showing a future date for when WireGuard key was generated.
+- Fix IPv6 connections to WireGuard servers by not dropping select neighbor advertisements and
+ solicitations.
#### Linux
- Make offline monitor aware of routing table changes.
diff --git a/Cargo.lock b/Cargo.lock
index ee564d9d2f..a0ed359d31 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1737,9 +1737,9 @@ dependencies = [
[[package]]
name = "pfctl"
-version = "0.4.1"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d091ecb01c905b5a31757cd43a6d00b484c835831e41e8b20385dec08514fc"
+checksum = "52063325d6b0de17051e72275d44f96c5b73a75029fcdd7e05e54a62ff216437"
dependencies = [
"derive_builder",
"errno",
diff --git a/docs/security.md b/docs/security.md
index c34a7d73a0..2f0b09e31c 100644
--- a/docs/security.md
+++ b/docs/security.md
@@ -64,10 +64,14 @@ The following network traffic is allowed or blocked independent of state:
server)
* Incoming UDP from `[fe80::]/10:547` to `[fe80::]/10:546` (server to client)
-1. Router solicitation, advertisement and redirects (subset of NDP) is always allowed:
+1. A subset of NDP is allowed:
* Outgoing to `ff02::2`, but only ICMPv6 with type 133 and code 0 (Router solicitation)
- * Incoming from `[fe80::]/10`, but only ICMPv6 type 134 and code 0 (Router advertisement)
- * Incoming from `[fe80::]/10`, but only ICMPv6 type 137 and code 0 (Redirect)
+ * Incoming from `fe80::/10`, but only ICMPv6 type 134 and code 0 (Router advertisement)
+ * Incoming from `fe80::/10`, but only ICMPv6 type 137 and code 0 (Redirect)
+ * Outgoing to `ff02::1:ff00:0/104` and `fe80::/10`, but only ICMPv6 with type 135 and code 0 (Neighbor solicitation).
+ * Incoming from `fe80::/10`, but only ICMPv6 with type 135 and code 0 (Neighbor solicitation).
+ * Outgoing to `fe80::/10`, but only ICMPv6 with type 136 and code 0 (Neighbor advertisement).
+ * Incoming from `*`, but only ICMPv6 with type 136 and code 0 (Neighbor advertisement).
1. If the "Allow LAN" setting is enabled, the following is also allowed:
* Outgoing to, and incoming from, any IP in an unroutable network, that means:
@@ -95,11 +99,6 @@ The following network traffic is allowed or blocked independent of state:
On Linux, any situation that permits incoming or outgoing traffic also allows that traffic to be
forwarded. All other forward traffic is rejected.
-#### macOS deviations
-
-* The app does not look at ICMPv6 type and code headers. So all ICMPv6 is allowed between the
- specified IP networks.
-
### Disconnected
This is the default state that the `mullvad-daemon` starts in when the device boots, unless
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index f8ebc64564..21c308f1ac 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -68,7 +68,7 @@ internet-checksum = "0.2"
[target.'cfg(target_os = "macos")'.dependencies]
-pfctl = "0.4.1"
+pfctl = "0.4.4"
system-configuration = "0.4"
tun = "0.5.1"
diff --git a/talpid-core/src/firewall/linux.rs b/talpid-core/src/firewall/linux.rs
index 674a95c9b6..f584df4475 100644
--- a/talpid-core/src/firewall/linux.rs
+++ b/talpid-core/src/firewall/linux.rs
@@ -319,6 +319,7 @@ impl<'a> PolicyBatch<'a> {
self.add_loopback_rules()?;
self.add_split_tunneling_rules(policy)?;
self.add_dhcp_client_rules();
+ self.add_ndp_rules();
self.add_policy_specific_rules(policy)?;
Ok(self.batch.finalize())
@@ -480,6 +481,9 @@ impl<'a> PolicyBatch<'a> {
add_verdict(&mut in_v6, &Verdict::Accept);
self.batch.add(&in_v6, nftnl::MsgType::Add);
}
+ }
+
+ fn add_ndp_rules(&mut self) {
// Outgoing Router solicitation (part of NDP)
for chain in &[&self.out_chain, &self.forward_chain] {
let mut rule = Rule::new(chain);
@@ -488,19 +492,7 @@ impl<'a> PolicyBatch<'a> {
End::Dst,
*super::ROUTER_SOLICITATION_OUT_DST_ADDR,
);
-
- rule.add_expr(&nft_expr!(meta l4proto));
- rule.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8));
-
- rule.add_expr(&Payload::Transport(
- nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Type),
- ));
- rule.add_expr(&nft_expr!(cmp == 133u8));
- rule.add_expr(&nftnl::expr::Payload::Transport(
- nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Code),
- ));
- rule.add_expr(&nft_expr!(cmp == 0u8));
-
+ check_icmpv6(&mut rule, 133, 0);
add_verdict(&mut rule, &Verdict::Accept);
self.batch.add(&rule, nftnl::MsgType::Add);
}
@@ -508,19 +500,7 @@ impl<'a> PolicyBatch<'a> {
for chain in &[&self.in_chain, &self.forward_chain] {
let mut rule = Rule::new(chain);
check_net(&mut rule, End::Src, *super::IPV6_LINK_LOCAL);
-
- rule.add_expr(&nft_expr!(meta l4proto));
- rule.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8));
-
- rule.add_expr(&Payload::Transport(
- nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Type),
- ));
- rule.add_expr(&nft_expr!(cmp == 134u8));
- rule.add_expr(&nftnl::expr::Payload::Transport(
- nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Code),
- ));
- rule.add_expr(&nft_expr!(cmp == 0u8));
-
+ check_icmpv6(&mut rule, 134, 0);
add_verdict(&mut rule, &Verdict::Accept);
self.batch.add(&rule, nftnl::MsgType::Add);
}
@@ -528,19 +508,45 @@ impl<'a> PolicyBatch<'a> {
for chain in &[&self.in_chain, &self.forward_chain] {
let mut rule = Rule::new(chain);
check_net(&mut rule, End::Src, *super::IPV6_LINK_LOCAL);
-
- rule.add_expr(&nft_expr!(meta l4proto));
- rule.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8));
-
- rule.add_expr(&Payload::Transport(
- nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Type),
- ));
- rule.add_expr(&nft_expr!(cmp == 137u8));
- rule.add_expr(&nftnl::expr::Payload::Transport(
- nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Code),
- ));
- rule.add_expr(&nft_expr!(cmp == 0u8));
-
+ check_icmpv6(&mut rule, 137, 0);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
+ }
+ // Outgoing Neighbor solicitation (part of NDP)
+ for chain in &[&self.out_chain, &self.forward_chain] {
+ let mut rule = Rule::new(chain);
+ check_net(&mut rule, End::Dst, *super::SOLICITED_NODE_MULTICAST);
+ check_icmpv6(&mut rule, 135, 0);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
+ }
+ for chain in &[&self.out_chain, &self.forward_chain] {
+ let mut rule = Rule::new(chain);
+ check_net(&mut rule, End::Dst, *super::IPV6_LINK_LOCAL);
+ check_icmpv6(&mut rule, 135, 0);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
+ }
+ // Incoming Neighbor solicitation (part of NDP)
+ for chain in &[&self.in_chain, &self.forward_chain] {
+ let mut rule = Rule::new(chain);
+ check_net(&mut rule, End::Src, *super::IPV6_LINK_LOCAL);
+ check_icmpv6(&mut rule, 135, 0);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
+ }
+ // Outgoing Neighbor advertisement (part of NDP)
+ for chain in &[&self.out_chain, &self.forward_chain] {
+ let mut rule = Rule::new(chain);
+ check_net(&mut rule, End::Dst, *super::IPV6_LINK_LOCAL);
+ check_icmpv6(&mut rule, 136, 0);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
+ }
+ // Incoming Neighbor advertisement (part of NDP)
+ for chain in &[&self.in_chain, &self.forward_chain] {
+ let mut rule = Rule::new(chain);
+ check_icmpv6(&mut rule, 136, 0);
add_verdict(&mut rule, &Verdict::Accept);
self.batch.add(&rule, nftnl::MsgType::Add);
}
@@ -934,6 +940,20 @@ fn check_net(rule: &mut Rule<'_>, end: End, net: impl Into<IpNetwork>) {
rule.add_expr(&nft_expr!(cmp == net.ip()));
}
+fn check_icmpv6(rule: &mut Rule<'_>, r#type: u8, code: u8) {
+ rule.add_expr(&nft_expr!(meta l4proto));
+ rule.add_expr(&nft_expr!(cmp == libc::IPPROTO_ICMPV6 as u8));
+
+ rule.add_expr(&Payload::Transport(
+ nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Type),
+ ));
+ rule.add_expr(&nft_expr!(cmp == r#type));
+ rule.add_expr(&nftnl::expr::Payload::Transport(
+ nftnl::expr::TransportHeaderField::Icmpv6(nftnl::expr::Icmpv6HeaderField::Code),
+ ));
+ rule.add_expr(&nft_expr!(cmp == code));
+}
+
fn check_endpoint(rule: &mut Rule<'_>, end: End, endpoint: &Endpoint) {
check_ip(rule, end, endpoint.address.ip());
check_port(rule, endpoint.protocol, end, endpoint.address.port());
diff --git a/talpid-core/src/firewall/macos.rs b/talpid-core/src/firewall/macos.rs
index 1a899279ed..4057d03a05 100644
--- a/talpid-core/src/firewall/macos.rs
+++ b/talpid-core/src/firewall/macos.rs
@@ -70,6 +70,7 @@ impl Firewall {
new_filter_rules.append(&mut self.get_allow_loopback_rules()?);
new_filter_rules.append(&mut self.get_allow_dhcp_client_rules()?);
+ new_filter_rules.append(&mut self.get_allow_ndp_rules()?);
new_filter_rules.append(&mut self.get_policy_specific_rules(policy)?);
let return_out_rule = self
@@ -420,23 +421,96 @@ impl Firewall {
.build()?;
rules.push(allow_incoming_dhcp_v6);
- // NDP (router solicitation, advertisement and redirect)
- let allow_router_solicitation = self
- .create_rule_builder(FilterRuleAction::Pass)
- .quick(true)
- .proto(pfctl::Proto::IcmpV6)
- .direction(pfctl::Direction::Out)
- .to(*super::ROUTER_SOLICITATION_OUT_DST_ADDR)
- .build()?;
- let allow_router_advertisement_and_redirect = self
- .create_rule_builder(FilterRuleAction::Pass)
+ Ok(rules)
+ }
+
+ fn get_allow_ndp_rules(&self) -> Result<Vec<pfctl::FilterRule>> {
+ let mut ndp_rule_builder = self.create_rule_builder(FilterRuleAction::Pass);
+ ndp_rule_builder
.quick(true)
- .proto(pfctl::Proto::IcmpV6)
- .direction(pfctl::Direction::In)
- .from(pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)))
- .build()?;
- rules.push(allow_router_solicitation);
- rules.push(allow_router_advertisement_and_redirect);
+ .af(pfctl::AddrFamily::Ipv6)
+ .proto(pfctl::Proto::IcmpV6);
+
+ let mut rules = Vec::new();
+
+ // Outgoing router solicitation to `ff02::2`
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::Out)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::RouterSol))
+ .to(*super::ROUTER_SOLICITATION_OUT_DST_ADDR)
+ .build()?,
+ );
+
+ // Incoming router advertisement from `fe80::/10`
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::In)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::RouterAdv))
+ .from(pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)))
+ .build()?,
+ );
+
+ // Incoming Redirect from `fe80::/10`
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::In)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::Redir))
+ .from(pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)))
+ .build()?,
+ );
+
+ // Outgoing neighbor solicitation to `ff02::1:ff00:0/104` and `fe80::/10`
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::Out)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::NeighbrSol))
+ .to(pfctl::Ip::from(IpNetwork::V6(
+ *super::SOLICITED_NODE_MULTICAST,
+ )))
+ .build()?,
+ );
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::Out)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::NeighbrSol))
+ .to(pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)))
+ .build()?,
+ );
+
+ // Incoming neighbor solicitation from `fe80::/10`
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::In)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::NeighbrSol))
+ .from(pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)))
+ .build()?,
+ );
+
+ // Outgoing neigbor advertisement to fe80::/10`
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::Out)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::NeighbrAdv))
+ .to(pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)))
+ .build()?,
+ );
+
+ // Incoming neigbor advertisement from anywhere
+ rules.push(
+ ndp_rule_builder
+ .clone()
+ .direction(pfctl::Direction::In)
+ .icmp_type(pfctl::IcmpType::Icmp6(pfctl::Icmp6Type::NeighbrAdv))
+ .build()?,
+ );
Ok(rules)
}
diff --git a/talpid-core/src/firewall/mod.rs b/talpid-core/src/firewall/mod.rs
index 557ae01412..e3ece0cbfe 100644
--- a/talpid-core/src/firewall/mod.rs
+++ b/talpid-core/src/firewall/mod.rs
@@ -67,6 +67,7 @@ lazy_static! {
Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 1, 3),
];
static ref ROUTER_SOLICITATION_OUT_DST_ADDR: Ipv6Addr = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 2);
+ static ref SOLICITED_NODE_MULTICAST: Ipv6Network = Ipv6Network::new(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 1, 0xFF00, 0), 104).unwrap();
static ref LOOPBACK_NETS: [IpNetwork; 2] = [
IpNetwork::V4(ipnetwork::Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap()),
IpNetwork::V6(ipnetwork::Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap()),
diff --git a/windows/winfw/src/winfw/mullvadguids.cpp b/windows/winfw/src/winfw/mullvadguids.cpp
index f5693d7751..8a9de5fe0f 100644
--- a/windows/winfw/src/winfw/mullvadguids.cpp
+++ b/windows/winfw/src/winfw/mullvadguids.cpp
@@ -136,6 +136,10 @@ MullvadGuids::DetailedIdentityRegistry MullvadGuids::DetailedRegistry(IdentityQu
registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitVpnTunnelService_Ipv6()));
registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Outbound_Router_Solicitation()));
registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Inbound_Router_Advertisement()));
+ registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Outbound_Neighbor_Solicitation()));
+ registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Inbound_Neighbor_Solicitation()));
+ registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Outbound_Neighbor_Advertisement()));
+ registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Inbound_Neighbor_Advertisement()));
registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitNdp_Inbound_Redirect()));
registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitDns_Outbound_Ipv4()));
registry.insert(std::make_pair(WfpObjectType::Filter, Filter_Baseline_PermitDns_Outbound_Ipv6()));
@@ -741,6 +745,62 @@ const GUID &MullvadGuids::Filter_Baseline_PermitNdp_Inbound_Router_Advertisement
}
//static
+const GUID &MullvadGuids::Filter_Baseline_PermitNdp_Outbound_Neighbor_Solicitation()
+{
+ static const GUID g =
+ {
+ 0x8cc5348a,
+ 0xf736,
+ 0x4ec4,
+ { 0x8e, 0x8f, 0xd7, 0x13, 0x17, 0xd4, 0xc2, 0xb8 }
+ };
+
+ return g;
+}
+
+//static
+const GUID &MullvadGuids::Filter_Baseline_PermitNdp_Inbound_Neighbor_Solicitation()
+{
+ static const GUID g =
+ {
+ 0x0c95bb19,
+ 0x40a2,
+ 0x48ee,
+ { 0xa7, 0xca, 0x5b, 0x61, 0x2c, 0xab, 0x5f, 0x9d }
+ };
+
+ return g;
+}
+
+//static
+const GUID &MullvadGuids::Filter_Baseline_PermitNdp_Outbound_Neighbor_Advertisement()
+{
+ static const GUID g =
+ {
+ 0x932042c4,
+ 0x2275,
+ 0x4c3e,
+ { 0x85, 0xe8, 0xf9, 0xa2, 0x77, 0x18, 0x19, 0x5c }
+ };
+
+ return g;
+}
+
+//static
+const GUID &MullvadGuids::Filter_Baseline_PermitNdp_Inbound_Neighbor_Advertisement()
+{
+ static const GUID g =
+ {
+ 0xc0e39478,
+ 0x7920,
+ 0x4632,
+ { 0x82, 0x12, 0x2a, 0xe5, 0xd2, 0x6f, 0x39, 0x5c }
+ };
+
+ return g;
+}
+
+//static
const GUID &MullvadGuids::Filter_Baseline_PermitNdp_Inbound_Redirect()
{
static const GUID g =
diff --git a/windows/winfw/src/winfw/mullvadguids.h b/windows/winfw/src/winfw/mullvadguids.h
index f8b9fbb770..ed064a9409 100644
--- a/windows/winfw/src/winfw/mullvadguids.h
+++ b/windows/winfw/src/winfw/mullvadguids.h
@@ -79,6 +79,10 @@ public:
static const GUID &Filter_Baseline_PermitNdp_Outbound_Router_Solicitation();
static const GUID &Filter_Baseline_PermitNdp_Inbound_Router_Advertisement();
+ static const GUID &Filter_Baseline_PermitNdp_Outbound_Neighbor_Solicitation();
+ static const GUID &Filter_Baseline_PermitNdp_Inbound_Neighbor_Solicitation();
+ static const GUID &Filter_Baseline_PermitNdp_Outbound_Neighbor_Advertisement();
+ static const GUID &Filter_Baseline_PermitNdp_Inbound_Neighbor_Advertisement();
static const GUID &Filter_Baseline_PermitNdp_Inbound_Redirect();
static const GUID &Filter_Baseline_PermitDns_Outbound_Ipv4();
diff --git a/windows/winfw/src/winfw/rules/baseline/permitndp.cpp b/windows/winfw/src/winfw/rules/baseline/permitndp.cpp
index 60c95ec8e9..3c5bb32d76 100644
--- a/windows/winfw/src/winfw/rules/baseline/permitndp.cpp
+++ b/windows/winfw/src/winfw/rules/baseline/permitndp.cpp
@@ -18,6 +18,7 @@ bool PermitNdp::apply(IObjectInstaller &objectInstaller)
{
const wfp::IpNetwork linkLocal(wfp::IpAddress::Literal6({ 0xFE80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }), 10);
const wfp::IpAddress::Literal6 linkLocalRouterMulticast{ 0xFF02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 };
+ const wfp::IpNetwork solicitedNodeMulticast(wfp::IpAddress::Literal6({ 0xFF02, 0, 0, 0, 0, 1, 0xFF00, 0 }), 104);
wfp::FilterBuilder filterBuilder;
@@ -81,12 +82,104 @@ bool PermitNdp::apply(IObjectInstaller &objectInstaller)
.name(L"Permit inbound NDP redirect")
.layer(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6);
+ {
+ wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6);
+
+ conditionBuilder.add_condition(ConditionProtocol::IcmpV6());
+ conditionBuilder.add_condition(ConditionIcmp::Type(137));
+ conditionBuilder.add_condition(ConditionIcmp::Code(0));
+ conditionBuilder.add_condition(ConditionIp::Remote(linkLocal));
+
+ if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
+ {
+ return false;
+ }
+ }
+
+ //
+ // #4 Permit outbound neighbor solicitation.
+ //
+
+ filterBuilder
+ .key(MullvadGuids::Filter_Baseline_PermitNdp_Outbound_Neighbor_Solicitation())
+ .name(L"Permit outbound NDP neighbor solicitation")
+ .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
+
+ {
+ wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
+
+ conditionBuilder.add_condition(ConditionProtocol::IcmpV6());
+ conditionBuilder.add_condition(ConditionIcmp::Type(135));
+ conditionBuilder.add_condition(ConditionIcmp::Code(0));
+ conditionBuilder.add_condition(ConditionIp::Remote(solicitedNodeMulticast));
+ conditionBuilder.add_condition(ConditionIp::Remote(linkLocal));
+
+ if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
+ {
+ return false;
+ }
+ }
+
+ //
+ // #5 Permit inbound neighbor solicitation.
+ //
+
+ filterBuilder
+ .key(MullvadGuids::Filter_Baseline_PermitNdp_Inbound_Neighbor_Solicitation())
+ .name(L"Permit inbound NDP neighbor solicitation")
+ .layer(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6);
+
+ {
+ wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6);
+
+ conditionBuilder.add_condition(ConditionProtocol::IcmpV6());
+ conditionBuilder.add_condition(ConditionIcmp::Type(135));
+ conditionBuilder.add_condition(ConditionIcmp::Code(0));
+ conditionBuilder.add_condition(ConditionIp::Remote(linkLocal));
+
+ if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
+ {
+ return false;
+ }
+ }
+
+ //
+ // #6 Permit outbound neighbor advertisement.
+ //
+
+ filterBuilder
+ .key(MullvadGuids::Filter_Baseline_PermitNdp_Outbound_Neighbor_Advertisement())
+ .name(L"Permit outbound NDP neighbor advertisement")
+ .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
+
+ {
+ wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
+
+ conditionBuilder.add_condition(ConditionProtocol::IcmpV6());
+ conditionBuilder.add_condition(ConditionIcmp::Type(136));
+ conditionBuilder.add_condition(ConditionIcmp::Code(0));
+ conditionBuilder.add_condition(ConditionIp::Remote(linkLocal));
+
+ if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
+ {
+ return false;
+ }
+ }
+
+ //
+ // #7 Permit inbound neighbor advertisement.
+ //
+
+ filterBuilder
+ .key(MullvadGuids::Filter_Baseline_PermitNdp_Inbound_Neighbor_Advertisement())
+ .name(L"Permit inbound NDP neighbor advertisement")
+ .layer(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6);
+
wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6);
conditionBuilder.add_condition(ConditionProtocol::IcmpV6());
- conditionBuilder.add_condition(ConditionIcmp::Type(137));
+ conditionBuilder.add_condition(ConditionIcmp::Type(136));
conditionBuilder.add_condition(ConditionIcmp::Code(0));
- conditionBuilder.add_condition(ConditionIp::Remote(linkLocal));
return objectInstaller.addFilter(filterBuilder, conditionBuilder);
}