summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2018-10-31 10:15:39 +0100
committerLinus Färnstrand <linus@mullvad.net>2018-10-31 16:03:41 +0100
commit06e7fdb299294addd4ab64d098bab497ddffca71 (patch)
treeb952b99703d4153f1b04b834cb2fd14773e15fbd
parentb92342834f2c8f3624c0d9a7a9a85fff886ab795 (diff)
downloadmullvadvpn-06e7fdb299294addd4ab64d098bab497ddffca71.tar.xz
mullvadvpn-06e7fdb299294addd4ab64d098bab497ddffca71.zip
Add DHCPv6 firewall rules for macOS
-rw-r--r--talpid-core/src/security/macos/mod.rs85
-rw-r--r--talpid-core/src/security/mod.rs4
2 files changed, 57 insertions, 32 deletions
diff --git a/talpid-core/src/security/macos/mod.rs b/talpid-core/src/security/macos/mod.rs
index 874a4bf57c..4fb711e4da 100644
--- a/talpid-core/src/security/macos/mod.rs
+++ b/talpid-core/src/security/macos/mod.rs
@@ -191,65 +191,92 @@ impl NetworkSecurity {
fn get_allow_lan_rules() -> Result<Vec<pfctl::FilterRule>> {
let mut rules = vec![];
+ // IPv4
for net in &*super::PRIVATE_NETS {
let mut rule_builder = pfctl::FilterRuleBuilder::default();
rule_builder
.action(pfctl::FilterRuleAction::Pass)
.quick(true)
.af(pfctl::AddrFamily::Ipv4)
- .from(pfctl::Ip::from(ipnetwork_compat(*net)));
- let allow_net = rule_builder
- .to(pfctl::Ip::from(ipnetwork_compat(*net)))
- .build()?;
+ .from(pfctl::Ip::from(*net));
+ let allow_net = rule_builder.to(pfctl::Ip::from(*net)).build()?;
let allow_multicast = rule_builder
- .to(pfctl::Ip::from(ipnetwork_compat(*super::MULTICAST_NET)))
+ .to(pfctl::Ip::from(*super::MULTICAST_NET))
.build()?;
let allow_ssdp = rule_builder.to(pfctl::Ip::from(*super::SSDP_IP)).build()?;
rules.push(allow_net);
rules.push(allow_multicast);
rules.push(allow_ssdp);
}
+ // IPv6
let mut rule_builder = pfctl::FilterRuleBuilder::default();
rule_builder
.action(pfctl::FilterRuleAction::Pass)
.quick(true)
.af(pfctl::AddrFamily::Ipv6)
- .from(pfctl::Ip::from(ipnetwork_compat(*super::LOCAL_INET6_NET)));
- let allow_net = rule_builder
- .to(pfctl::Ip::from(ipnetwork_compat(*super::LOCAL_INET6_NET)))
+ .from(pfctl::Ip::from(*super::LOCAL_INET6_NET));
+ let allow_net_v6 = rule_builder
+ .to(pfctl::Ip::from(*super::LOCAL_INET6_NET))
.build()?;
- let allow_multicast = rule_builder
- .to(pfctl::Ip::from(ipnetwork_compat(
- *super::MULTICAST_INET6_NET,
- )))
+ let allow_multicast_v6 = rule_builder
+ .to(pfctl::Ip::from(*super::MULTICAST_INET6_NET))
.build()?;
- rules.push(allow_net);
- rules.push(allow_multicast);
+ rules.push(allow_net_v6);
+ rules.push(allow_multicast_v6);
Ok(rules)
}
fn get_allow_dhcp_rules() -> Result<Vec<pfctl::FilterRule>> {
- let broadcast_address = Ipv4Addr::new(255, 255, 255, 255);
- let server_port = pfctl::Port::from(67);
- let client_port = pfctl::Port::from(68);
+ let server_port_v4 = pfctl::Port::from(67);
+ let client_port_v4 = pfctl::Port::from(68);
+ let server_port_v6 = pfctl::Port::from(547);
+ let client_port_v6 = pfctl::Port::from(546);
let mut dhcp_rule_builder = pfctl::FilterRuleBuilder::default();
dhcp_rule_builder
.action(pfctl::FilterRuleAction::Pass)
- .proto(pfctl::Proto::Udp)
.quick(true)
- .keep_state(pfctl::StatePolicy::Keep);
- let allow_outgoing_dhcp = dhcp_rule_builder
+ .proto(pfctl::Proto::Udp);
+
+ let mut rules = Vec::new();
+ let allow_outgoing_dhcp_v4 = dhcp_rule_builder
.direction(pfctl::Direction::Out)
- .from(client_port)
- .to(pfctl::Endpoint::new(broadcast_address, server_port))
+ .from(client_port_v4)
+ .to(pfctl::Endpoint::new(Ipv4Addr::BROADCAST, server_port_v4))
+ .build()?;
+ rules.push(allow_outgoing_dhcp_v4);
+ let allow_incoming_dhcp_v4 = dhcp_rule_builder
+ .af(pfctl::AddrFamily::Ipv4)
+ .direction(pfctl::Direction::In)
+ .from(server_port_v4)
+ .to(client_port_v4)
.build()?;
- let allow_incoming_dhcp = dhcp_rule_builder
+ rules.push(allow_incoming_dhcp_v4);
+
+ for dhcpv6_server in &*super::DHCPV6_SERVER_ADDRS {
+ let allow_outgoing_dhcp_v6 = dhcp_rule_builder
+ .af(pfctl::AddrFamily::Ipv6)
+ .direction(pfctl::Direction::Out)
+ .from(pfctl::Endpoint::new(
+ *super::LOCAL_INET6_NET,
+ client_port_v6,
+ ))
+ .to(pfctl::Endpoint::new(*dhcpv6_server, server_port_v6))
+ .build()?;
+ rules.push(allow_outgoing_dhcp_v6);
+ }
+ let allow_incoming_dhcp_v6 = dhcp_rule_builder
+ .af(pfctl::AddrFamily::Ipv6)
.direction(pfctl::Direction::In)
- .from(server_port)
- .to(client_port)
+ .from(server_port_v6)
+ .to(pfctl::Endpoint::new(
+ *super::LOCAL_INET6_NET,
+ client_port_v6,
+ ))
.build()?;
- Ok(vec![allow_outgoing_dhcp, allow_incoming_dhcp])
+ rules.push(allow_incoming_dhcp_v6);
+
+ Ok(rules)
}
fn get_tcp_flags() -> pfctl::TcpFlags {
@@ -308,9 +335,3 @@ fn as_pfctl_proto(protocol: net::TransportProtocol) -> pfctl::Proto {
net::TransportProtocol::Tcp => pfctl::Proto::Tcp,
}
}
-
-/// Converts a network from the struct version that talpid-core uses to the version pfctl uses.
-fn ipnetwork_compat(net: ::ipnetwork::IpNetwork) -> pfctl::ipnetwork::IpNetwork {
- pfctl::ipnetwork::IpNetwork::new(net.ip(), net.prefix())
- .expect("IpNetwork versions not compatible")
-}
diff --git a/talpid-core/src/security/mod.rs b/talpid-core/src/security/mod.rs
index 513386b30f..b6749e432c 100644
--- a/talpid-core/src/security/mod.rs
+++ b/talpid-core/src/security/mod.rs
@@ -38,6 +38,10 @@ lazy_static! {
static ref MULTICAST_INET6_NET: IpNetwork =
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xfe02, 0, 0, 0, 0, 0, 0, 0), 16).unwrap());
static ref SSDP_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(239, 255, 255, 250));
+ static ref DHCPV6_SERVER_ADDRS: [IpAddr; 2] = [
+ IpAddr::V6(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 1, 2)),
+ IpAddr::V6(Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 1, 3)),
+ ];
}
/// A enum that describes network security strategy