diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2019-05-08 10:02:34 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2019-05-08 14:12:32 +0200 |
| commit | e7d94b77ba620ee5103ee72803eb6ed0abe49541 (patch) | |
| tree | 2c8bfb916ecc68c57250825571fe8ed08d9038db | |
| parent | 346b9a77beba94c85f05658869e70040f361ecb8 (diff) | |
| download | mullvadvpn-e7d94b77ba620ee5103ee72803eb6ed0abe49541.tar.xz mullvadvpn-e7d94b77ba620ee5103ee72803eb6ed0abe49541.zip | |
Update macOS firewall to new specs
| -rw-r--r-- | talpid-core/src/firewall/macos.rs | 128 |
1 files changed, 76 insertions, 52 deletions
diff --git a/talpid-core/src/firewall/macos.rs b/talpid-core/src/firewall/macos.rs index ba920d4e79..04dfa7c8d2 100644 --- a/talpid-core/src/firewall/macos.rs +++ b/talpid-core/src/firewall/macos.rs @@ -1,4 +1,5 @@ use super::{FirewallArguments, FirewallPolicy, FirewallT}; +use ipnetwork::IpNetwork; use pfctl::FilterRuleAction; use std::{ env, @@ -206,21 +207,21 @@ impl Firewall { let out_rule = self .create_rule_builder(FilterRuleAction::Pass) + .quick(true) .direction(pfctl::Direction::Out) - .to(pfctl::Endpoint::new(*host, 0)) .proto(icmp_proto) + .to(pfctl::Endpoint::new(*host, 0)) .keep_state(pfctl::StatePolicy::Keep) - .quick(true) .build()?; rules.push(out_rule); let in_rule = self .create_rule_builder(FilterRuleAction::Pass) + .quick(true) .direction(pfctl::Direction::In) - .from(pfctl::Endpoint::new(*host, 0)) .proto(icmp_proto) + .from(pfctl::Endpoint::new(*host, 0)) .keep_state(pfctl::StatePolicy::Keep) - .quick(true) .build()?; rules.push(in_rule); } @@ -230,108 +231,131 @@ impl Firewall { fn get_allow_tunnel_rule(&self, tunnel_interface: &str) -> Result<pfctl::FilterRule> { Ok(self .create_rule_builder(FilterRuleAction::Pass) + .quick(true) .interface(tunnel_interface) .keep_state(pfctl::StatePolicy::Keep) .tcp_flags(Self::get_tcp_flags()) - .quick(true) .build()?) } fn get_allow_loopback_rules(&self) -> Result<Vec<pfctl::FilterRule>> { let lo0_rule = self .create_rule_builder(FilterRuleAction::Pass) + .quick(true) .interface("lo0") .keep_state(pfctl::StatePolicy::Keep) - .quick(true) .build()?; Ok(vec![lo0_rule]) } fn get_allow_lan_rules(&self) -> Result<Vec<pfctl::FilterRule>> { let mut rules = vec![]; - // IPv4 - for net in &*super::PRIVATE_NETS { + for net in &*super::ALLOWED_LAN_NETS { let mut rule_builder = self.create_rule_builder(FilterRuleAction::Pass); - rule_builder + rule_builder.quick(true).af(match net { + IpNetwork::V4(_) => pfctl::AddrFamily::Ipv4, + IpNetwork::V6(_) => pfctl::AddrFamily::Ipv6, + }); + let allow_out = rule_builder + .direction(pfctl::Direction::Out) + .from(pfctl::Ip::Any) + .to(pfctl::Ip::from(*net)) + .build()?; + let allow_in = rule_builder + .direction(pfctl::Direction::In) + .from(pfctl::Ip::from(*net)) + .to(pfctl::Ip::Any) + .build()?; + rules.push(allow_out); + rules.push(allow_in); + } + for multicast_net in &*super::ALLOWED_LAN_MULTICAST_NETS { + let allow_multicast_out = self + .create_rule_builder(FilterRuleAction::Pass) .quick(true) - .af(pfctl::AddrFamily::Ipv4) - .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(*super::MULTICAST_NET)) + .direction(pfctl::Direction::Out) + .af(match multicast_net { + IpNetwork::V4(_) => pfctl::AddrFamily::Ipv4, + IpNetwork::V6(_) => pfctl::AddrFamily::Ipv6, + }) + .to(pfctl::Ip::from(*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); + rules.push(allow_multicast_out); } - // IPv6 - let mut rule_builder = self.create_rule_builder(FilterRuleAction::Pass); - rule_builder - .quick(true) - .af(pfctl::AddrFamily::Ipv6) - .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_v6 = rule_builder - .to(pfctl::Ip::from(*super::MULTICAST_INET6_NET)) - .build()?; - rules.push(allow_net_v6); - rules.push(allow_multicast_v6); - Ok(rules) } fn get_allow_dhcp_rules(&self) -> Result<Vec<pfctl::FilterRule>> { - 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 = self.create_rule_builder(FilterRuleAction::Pass); dhcp_rule_builder.quick(true).proto(pfctl::Proto::Udp); let mut rules = Vec::new(); + + // DHCPv4 + dhcp_rule_builder.af(pfctl::AddrFamily::Ipv4); let allow_outgoing_dhcp_v4 = dhcp_rule_builder .direction(pfctl::Direction::Out) - .from(client_port_v4) - .to(pfctl::Endpoint::new(Ipv4Addr::BROADCAST, server_port_v4)) + .from(pfctl::Port::from(super::DHCPV4_CLIENT_PORT)) + .to(pfctl::Endpoint::new( + Ipv4Addr::BROADCAST, + pfctl::Port::from(super::DHCPV4_SERVER_PORT), + )) .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) + .from(pfctl::Port::from(super::DHCPV4_SERVER_PORT)) + .to(pfctl::Port::from(super::DHCPV4_CLIENT_PORT)) .build()?; + rules.push(allow_outgoing_dhcp_v4); rules.push(allow_incoming_dhcp_v4); + // DHCPv6 + dhcp_rule_builder.af(pfctl::AddrFamily::Ipv6); 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, + IpNetwork::V6(*super::IPV6_LINK_LOCAL), + pfctl::Port::from(super::DHCPV6_CLIENT_PORT), + )) + .to(pfctl::Endpoint::new( + *dhcpv6_server, + pfctl::Port::from(super::DHCPV6_SERVER_PORT), )) - .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(pfctl::Endpoint::new( - *super::LOCAL_INET6_NET, - server_port_v6, + pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)), + pfctl::Port::from(super::DHCPV6_SERVER_PORT), )) .to(pfctl::Endpoint::new( - *super::LOCAL_INET6_NET, - client_port_v6, + pfctl::Ip::from(IpNetwork::V6(*super::IPV6_LINK_LOCAL)), + pfctl::Port::from(super::DHCPV6_CLIENT_PORT), )) .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) + .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); + Ok(rules) } |
