diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2019-05-07 15:24:32 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2019-05-08 14:12:32 +0200 |
| commit | 9efcd31574d18c34d9baff593c6364c314237ef5 (patch) | |
| tree | 19c75819c5875e206593a8e4bdc51111b5ceee35 | |
| parent | 6bb9c4335919530b90a5be86d5321b355f591bbd (diff) | |
| download | mullvadvpn-9efcd31574d18c34d9baff593c6364c314237ef5.tar.xz mullvadvpn-9efcd31574d18c34d9baff593c6364c314237ef5.zip | |
Add router solicitation/advertisement rules to Linux
| -rw-r--r-- | Cargo.lock | 17 | ||||
| -rw-r--r-- | talpid-core/Cargo.toml | 2 | ||||
| -rw-r--r-- | talpid-core/src/firewall/linux.rs | 49 | ||||
| -rw-r--r-- | talpid-core/src/firewall/mod.rs | 10 |
4 files changed, 68 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock index 94e2e8b782..99dcef5a24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1254,21 +1254,22 @@ dependencies = [ [[package]] name = "nftnl" -version = "0.1.0" -source = "git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3#29651f4370fdf22cc2e3abf5097a51f8ff17e3a3" +version = "0.2.0" +source = "git+https://github.com/mullvad/nftnl-rs?rev=86b30cdc38a6d4b30a900c21f7c644857d6f7401#86b30cdc38a6d4b30a900c21f7c644857d6f7401" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "nftnl-sys 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3)", + "nftnl-sys 0.2.0 (git+https://github.com/mullvad/nftnl-rs?rev=86b30cdc38a6d4b30a900c21f7c644857d6f7401)", ] [[package]] name = "nftnl-sys" -version = "0.1.0" -source = "git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3#29651f4370fdf22cc2e3abf5097a51f8ff17e3a3" +version = "0.2.0" +source = "git+https://github.com/mullvad/nftnl-rs?rev=86b30cdc38a6d4b30a900c21f7c644857d6f7401#86b30cdc38a6d4b30a900c21f7c644857d6f7401" dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1996,7 +1997,7 @@ dependencies = [ "netlink-proto 0.1.1 (git+https://github.com/mullvad/netlink?branch=hack-older-kernel-compat)", "netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=ignore-hw-address)", "netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?branch=hack-older-kernel-compat)", - "nftnl 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3)", + "nftnl 0.2.0 (git+https://github.com/mullvad/nftnl-rs?rev=86b30cdc38a6d4b30a900c21f7c644857d6f7401)", "nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "openvpn-plugin 0.3.0 (git+https://github.com/mullvad/openvpn-plugin-rs?branch=auth-failed-event)", @@ -2726,8 +2727,8 @@ dependencies = [ "checksum netlink-proto 0.1.1 (git+https://github.com/mullvad/netlink?branch=hack-older-kernel-compat)" = "<none>" "checksum netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=ignore-hw-address)" = "<none>" "checksum netlink-sys 0.1.0 (git+https://github.com/mullvad/netlink?branch=hack-older-kernel-compat)" = "<none>" -"checksum nftnl 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3)" = "<none>" -"checksum nftnl-sys 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3)" = "<none>" +"checksum nftnl 0.2.0 (git+https://github.com/mullvad/nftnl-rs?rev=86b30cdc38a6d4b30a900c21f7c644857d6f7401)" = "<none>" +"checksum nftnl-sys 0.2.0 (git+https://github.com/mullvad/nftnl-rs?rev=86b30cdc38a6d4b30a900c21f7c644857d6f7401)" = "<none>" "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index c2fd7b90bc..982b1d500d 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -44,7 +44,7 @@ rtnetlink = { git = "https://github.com/mullvad/netlink", branch = "hack-older-k netlink-proto = { git = "https://github.com/mullvad/netlink", branch = "hack-older-kernel-compat" } netlink-packet = { git = "https://github.com/mullvad/netlink", branch = "hack-older-kernel-compat" } netlink-sys = { git = "https://github.com/mullvad/netlink", branch = "hack-older-kernel-compat" } -nftnl = { git = "https://github.com/mullvad/nftnl-rs", rev = "29651f4370fdf22cc2e3abf5097a51f8ff17e3a3", features = ["nftnl-1-1-0"] } +nftnl = { git = "https://github.com/mullvad/nftnl-rs", rev = "86b30cdc38a6d4b30a900c21f7c644857d6f7401", features = ["nftnl-1-1-0"] } mnl = { git = "https://github.com/mullvad/mnl-rs", rev = "f0d19501b9b85be9a1ffaec8317a378bcbdf4fa6", features = ["mnl-1-0-4"] } which = "2.0" err-derive = "0.1.5" diff --git a/talpid-core/src/firewall/linux.rs b/talpid-core/src/firewall/linux.rs index 232252fd69..a1bb4cc635 100644 --- a/talpid-core/src/firewall/linux.rs +++ b/talpid-core/src/firewall/linux.rs @@ -4,7 +4,8 @@ use ipnetwork::IpNetwork; use lazy_static::lazy_static; use libc; use nftnl::{ - expr::{self, Verdict}, + self, + expr::{self, Payload, Verdict}, nft_expr, table, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table, }; use std::{ @@ -274,6 +275,52 @@ impl<'a> PolicyBatch<'a> { add_verdict(&mut in_v6, &Verdict::Accept); self.batch.add(&in_v6, nftnl::MsgType::Add); } + // Outgoing Router solicitation (part of NDP) + { + let mut rule = Rule::new(&self.out_chain); + + check_ip( + &mut rule, + 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)); + + add_verdict(&mut rule, &Verdict::Accept); + self.batch.add(&rule, nftnl::MsgType::Add); + } + // Incoming Router advertisement (part of NDP) + { + let mut rule = Rule::new(&self.in_chain); + + check_net(&mut rule, End::Src, *super::ROUTER_ADVERTISEMENT_IN_SRC_NET); + + 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)); + + add_verdict(&mut rule, &Verdict::Accept); + self.batch.add(&rule, nftnl::MsgType::Add); + } } fn add_policy_specific_rules(&mut self, policy: &FirewallPolicy) -> Result<()> { diff --git a/talpid-core/src/firewall/mod.rs b/talpid-core/src/firewall/mod.rs index d52e3ce9b5..2315c6ccc3 100644 --- a/talpid-core/src/firewall/mod.rs +++ b/talpid-core/src/firewall/mod.rs @@ -50,13 +50,23 @@ lazy_static! { // Site-local IPv6 multicast. IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 0, 0), 16).unwrap()), ]; + // The firewall should always allow DHCPv6 to enable automatic configuring of network adapters + /// The allowed source address of outbound DHCPv6 requests static ref DHCPV6_SRC_ADDR: Ipv6Network = Ipv6Network::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), 10).unwrap(); + /// The allowed target addresses of outbound DHCPv6 requests static ref DHCPV6_SERVER_ADDRS: [Ipv6Addr; 2] = [ Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 1, 2), Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 1, 3), ]; + // The firewall needs to always allow Router Solicitation/Advertisement (part of NDP) + // It should only allow ICMPv6 packets on these addresses. If the platform supports it + // it should check that the solicitation packet has ICMP type 133, code 0 for solicitation + // and type 134, code 0 for advertisement. + static ref ROUTER_SOLICITATION_OUT_DST_ADDR: Ipv6Addr = Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 2); + static ref ROUTER_ADVERTISEMENT_IN_SRC_NET: Ipv6Network = Ipv6Network::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), 10).unwrap(); } + /// A enum that describes network security strategy #[derive(Debug, Clone, Eq, PartialEq)] pub enum FirewallPolicy { |
