summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2019-04-03 17:42:55 +0200
committerLinus Färnstrand <linus@mullvad.net>2019-04-03 17:42:55 +0200
commit5d5392d39cc00696cd42c547587bbd7d767dd1c9 (patch)
treeab306f220d70432731d1b565936edaab9abc5884
parentff97b87b8a5a547ae31dd8fde14cc2d60482e7e8 (diff)
parent0fafa528a46f592082085155a27ee427e662af01 (diff)
downloadmullvadvpn-5d5392d39cc00696cd42c547587bbd7d767dd1c9.tar.xz
mullvadvpn-5d5392d39cc00696cd42c547587bbd7d767dd1c9.zip
Merge branch 'upgrade-nftnl'
-rw-r--r--Cargo.lock14
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/firewall/linux.rs390
3 files changed, 199 insertions, 207 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ed0f8d6239..ae84577039 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1250,19 +1250,19 @@ dependencies = [
[[package]]
name = "nftnl"
version = "0.1.0"
-source = "git+https://github.com/mullvad/nftnl-rs?rev=f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6#f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6"
+source = "git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3#29651f4370fdf22cc2e3abf5097a51f8ff17e3a3"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.12.0 (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=f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6)",
+ "nftnl-sys 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3)",
]
[[package]]
name = "nftnl-sys"
version = "0.1.0"
-source = "git+https://github.com/mullvad/nftnl-rs?rev=f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6#f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6"
+source = "git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3#29651f4370fdf22cc2e3abf5097a51f8ff17e3a3"
dependencies = [
"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)",
@@ -1997,7 +1997,7 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mnl 0.1.0 (git+https://github.com/mullvad/mnl-rs?rev=f0d19501b9b85be9a1ffaec8317a378bcbdf4fa6)",
"netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=ignore-hw-address)",
- "nftnl 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6)",
+ "nftnl 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=29651f4370fdf22cc2e3abf5097a51f8ff17e3a3)",
"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)",
@@ -2727,8 +2727,8 @@ dependencies = [
"checksum mnl-sys 0.1.0 (git+https://github.com/mullvad/mnl-rs?rev=f0d19501b9b85be9a1ffaec8317a378bcbdf4fa6)" = "<none>"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=ignore-hw-address)" = "<none>"
-"checksum nftnl 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6)" = "<none>"
-"checksum nftnl-sys 0.1.0 (git+https://github.com/mullvad/nftnl-rs?rev=f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6)" = "<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 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 1d2e0f5276..5d577d1c46 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -44,7 +44,7 @@ netlink-socket = { git = "https://github.com/mullvad/netlink", branch = "ignore-
notify = "4.0"
resolv-conf = "0.6.1"
rtnetlink = { git = "https://github.com/mullvad/netlink", branch = "ignore-hw-address" }
-nftnl = { git = "https://github.com/mullvad/nftnl-rs", rev = "f0b1492fd2fd1f737dbffd047c9c60c300e6f7d6", features = ["nftnl-1-1-0"] }
+nftnl = { git = "https://github.com/mullvad/nftnl-rs", rev = "29651f4370fdf22cc2e3abf5097a51f8ff17e3a3", 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 d073853ad0..e687a7c7a7 100644
--- a/talpid-core/src/firewall/linux.rs
+++ b/talpid-core/src/firewall/linux.rs
@@ -5,36 +5,48 @@ use lazy_static::lazy_static;
use libc;
use nftnl::{
expr::{self, Verdict},
- nft_expr, nft_expr_bitwise, nft_expr_cmp, nft_expr_ct, nft_expr_meta, nft_expr_payload, table,
- Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table,
+ nft_expr, table, Batch, Chain, FinalizedBatch, ProtoFamily, Rule, Table,
};
use std::{
env,
ffi::{CStr, CString},
+ io,
net::{IpAddr, Ipv4Addr},
};
use talpid_types::net::{Endpoint, TransportProtocol};
-error_chain! {
- errors {
- /// Unable to open netlink socket to netfilter
- NetlinkOpenError { description("Unable to open netlink socket to netfilter") }
- /// Unable to send netlink command to netfilter
- NetlinkSendError { description("Unable to send netlink command to netfilter") }
- /// Error while reading from netlink socket
- NetlinkRecvError { description("Error while reading from netlink socket") }
- /// Error while processing an incoming netlink message
- ProcessNetlinkError { description("Error while processing an incoming netlink message") }
- /// Failed to verify that our tables are set. Probably means that
- /// it's the host does not support nftables properly.
- NetfilterTableNotSetError{ description("Failed to set firewall rules") }
- }
- links {
- Nftnl(nftnl::Error, nftnl::ErrorKind) #[doc = "Error in nftnl"];
- }
- foreign_links {
- IfaceIndexLookupError(crate::linux::IfaceIndexLookupError);
- }
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// Errors that can happen when interacting with Linux netfilter.
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ /// Unable to open netlink socket to netfilter.
+ #[error(display = "Unable to open netlink socket to netfilter")]
+ NetlinkOpenError(#[error(cause)] io::Error),
+
+ /// Unable to send netlink command to netfilter.
+ #[error(display = "Unable to send netlink command to netfilter")]
+ NetlinkSendError(#[error(cause)] io::Error),
+
+ /// Error while reading from netlink socket.
+ #[error(display = "Error while reading from netlink socket")]
+ NetlinkRecvError(#[error(cause)] io::Error),
+
+ /// Error while processing an incoming netlink message.
+ #[error(display = "Error while processing an incoming netlink message")]
+ ProcessNetlinkError(#[error(cause)] io::Error),
+
+ /// Failed to verify that our tables are set. Probably means that
+ /// it's the host that does not support nftables properly.
+ #[error(display = "Failed to set firewall rules")]
+ NetfilterTableNotSetError,
+
+ /// Unable to translate network interface name into index.
+ #[error(
+ display = "Unable to translate network interface name \"{}\" into index",
+ _0
+ )]
+ LookupIfaceIndexError(String, #[error(cause)] crate::linux::IfaceIndexLookupError),
}
lazy_static! {
@@ -78,21 +90,21 @@ impl FirewallT for Firewall {
}
fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<()> {
- let table = Table::new(&self.table_name, ProtoFamily::Inet)?;
- let batch = PolicyBatch::new(&table)?.finalize(&policy)?;
+ let table = Table::new(&self.table_name, ProtoFamily::Inet);
+ let batch = PolicyBatch::new(&table).finalize(&policy)?;
self.send_and_process(&batch)?;
self.verify_tables(&[&TABLE_NAME])
}
fn reset_policy(&mut self) -> Result<()> {
- let table = Table::new(&self.table_name, ProtoFamily::Inet)?;
+ let table = Table::new(&self.table_name, ProtoFamily::Inet);
let batch = {
- let mut batch = Batch::new()?;
+ let mut batch = Batch::new();
// Our batch will add and remove the table even though the goal is just to remove it.
// This because only removing it throws a strange error if the table does not exist.
- batch.add(&table, nftnl::MsgType::Add)?;
- batch.add(&table, nftnl::MsgType::Del)?;
- batch.finalize()?
+ batch.add(&table, nftnl::MsgType::Add);
+ batch.add(&table, nftnl::MsgType::Del);
+ batch.finalize()
};
log::debug!("Removing table and chain from netfilter");
@@ -102,18 +114,15 @@ impl FirewallT for Firewall {
impl Firewall {
fn send_and_process(&self, batch: &FinalizedBatch) -> Result<()> {
- let socket =
- mnl::Socket::new(mnl::Bus::Netfilter).chain_err(|| ErrorKind::NetlinkOpenError)?;
- socket
- .send_all(batch)
- .chain_err(|| ErrorKind::NetlinkSendError)?;
+ let socket = mnl::Socket::new(mnl::Bus::Netfilter).map_err(Error::NetlinkOpenError)?;
+ socket.send_all(batch).map_err(Error::NetlinkSendError)?;
let portid = socket.portid();
let mut buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize];
let seq = 0;
while let Some(message) = Self::socket_recv(&socket, &mut buffer[..])? {
- match mnl::cb_run(message, seq, portid).chain_err(|| ErrorKind::ProcessNetlinkError)? {
+ match mnl::cb_run(message, seq, portid).map_err(Error::ProcessNetlinkError)? {
mnl::CbResult::Stop => {
log::trace!("cb_run STOP");
break;
@@ -125,22 +134,21 @@ impl Firewall {
}
fn verify_tables(&self, expected_tables: &[&CStr]) -> Result<()> {
- let socket =
- mnl::Socket::new(mnl::Bus::Netfilter).chain_err(|| ErrorKind::NetlinkOpenError)?;
+ let socket = mnl::Socket::new(mnl::Bus::Netfilter).map_err(Error::NetlinkOpenError)?;
let portid = socket.portid();
let seq = 0;
let get_tables_msg = table::get_tables_nlmsg(seq);;
socket
.send(&get_tables_msg)
- .chain_err(|| ErrorKind::NetlinkSendError)?;
+ .map_err(Error::NetlinkSendError)?;
let mut table_set = ::std::collections::HashSet::new();
let mut msg_buffer = vec![0; nftnl::nft_nlmsg_maxsize() as usize];
while let Some(message) = Self::socket_recv(&socket, &mut msg_buffer)? {
match mnl::cb_run2(message, seq, portid, table::get_tables_cb, &mut table_set)
- .chain_err(|| ErrorKind::ProcessNetlinkError)?
+ .map_err(Error::ProcessNetlinkError)?
{
mnl::CbResult::Stop => {
log::trace!("cb_run STOP");
@@ -156,14 +164,14 @@ impl Firewall {
"Expected '{}' netfilter table to be set, but it is not",
expected_table.to_string_lossy()
);
- bail!(ErrorKind::NetfilterTableNotSetError)
+ bail!(Error::NetfilterTableNotSetError)
}
}
Ok(())
}
fn socket_recv<'a>(socket: &mnl::Socket, buf: &'a mut [u8]) -> Result<Option<&'a [u8]>> {
- let ret = socket.recv(buf).chain_err(|| ErrorKind::NetlinkRecvError)?;
+ let ret = socket.recv(buf).map_err(Error::NetlinkRecvError)?;
log::trace!("Read {} bytes from netlink", ret);
if ret > 0 {
Ok(Some(&buf[..ret]))
@@ -182,36 +190,36 @@ struct PolicyBatch<'a> {
impl<'a> PolicyBatch<'a> {
/// Bootstrap a new nftnl message batch object and add the initial messages creating the
/// table and chains.
- pub fn new(table: &'a Table) -> Result<Self> {
- let mut batch = Batch::new()?;
- let mut out_chain = Chain::new(&*OUT_CHAIN_NAME, table)?;
- let mut in_chain = Chain::new(&*IN_CHAIN_NAME, table)?;
+ pub fn new(table: &'a Table) -> Self {
+ let mut batch = Batch::new();
+ let mut out_chain = Chain::new(&*OUT_CHAIN_NAME, table);
+ let mut in_chain = Chain::new(&*IN_CHAIN_NAME, table);
out_chain.set_hook(nftnl::Hook::Out, 0);
in_chain.set_hook(nftnl::Hook::In, 0);
out_chain.set_policy(nftnl::Policy::Drop);
in_chain.set_policy(nftnl::Policy::Drop);
- batch.add(table, nftnl::MsgType::Add)?;
- batch.add(table, nftnl::MsgType::Del)?;
- batch.add(table, nftnl::MsgType::Add)?;
- batch.add(&out_chain, nftnl::MsgType::Add)?;
- batch.add(&in_chain, nftnl::MsgType::Add)?;
+ batch.add(table, nftnl::MsgType::Add);
+ batch.add(table, nftnl::MsgType::Del);
+ batch.add(table, nftnl::MsgType::Add);
+ batch.add(&out_chain, nftnl::MsgType::Add);
+ batch.add(&in_chain, nftnl::MsgType::Add);
- Ok(PolicyBatch {
+ PolicyBatch {
batch,
in_chain,
out_chain,
- })
+ }
}
/// Finalize the nftnl message batch by adding every firewall rule needed to satisfy the given
/// policy.
pub fn finalize(mut self, policy: &FirewallPolicy) -> Result<FinalizedBatch> {
self.add_loopback_rules()?;
- self.add_dhcp_rules()?;
+ self.add_dhcp_rules();
self.add_policy_specific_rules(policy)?;
- Ok(self.batch.finalize()?)
+ Ok(self.batch.finalize())
}
fn add_loopback_rules(&mut self) -> Result<()> {
@@ -219,54 +227,53 @@ impl<'a> PolicyBatch<'a> {
self.batch.add(
&allow_interface_rule(&self.out_chain, Direction::Out, LOOPBACK_IFACE_NAME)?,
nftnl::MsgType::Add,
- )?;
+ );
self.batch.add(
&allow_interface_rule(&self.in_chain, Direction::In, LOOPBACK_IFACE_NAME)?,
nftnl::MsgType::Add,
- )?;
+ );
Ok(())
}
- fn add_dhcp_rules(&mut self) -> Result<()> {
+ fn add_dhcp_rules(&mut self) {
use self::TransportProtocol::Udp;
const SERVER_PORT_V4: u16 = 67;
const CLIENT_PORT_V4: u16 = 68;
const SERVER_PORT_V6: u16 = 547;
const CLIENT_PORT_V6: u16 = 546;
{
- let mut out_v4 = Rule::new(&self.out_chain)?;
- check_port(&mut out_v4, Udp, End::Src, CLIENT_PORT_V4)?;
- check_ip(&mut out_v4, End::Dst, IpAddr::V4(Ipv4Addr::BROADCAST))?;
- check_port(&mut out_v4, Udp, End::Dst, SERVER_PORT_V4)?;
- add_verdict(&mut out_v4, &Verdict::Accept)?;
- self.batch.add(&out_v4, nftnl::MsgType::Add)?;
+ let mut out_v4 = Rule::new(&self.out_chain);
+ check_port(&mut out_v4, Udp, End::Src, CLIENT_PORT_V4);
+ check_ip(&mut out_v4, End::Dst, IpAddr::V4(Ipv4Addr::BROADCAST));
+ check_port(&mut out_v4, Udp, End::Dst, SERVER_PORT_V4);
+ add_verdict(&mut out_v4, &Verdict::Accept);
+ self.batch.add(&out_v4, nftnl::MsgType::Add);
}
{
- let mut in_v4 = Rule::new(&self.in_chain)?;
- check_port(&mut in_v4, Udp, End::Src, SERVER_PORT_V4)?;
- check_port(&mut in_v4, Udp, End::Dst, CLIENT_PORT_V4)?;
- add_verdict(&mut in_v4, &Verdict::Accept)?;
- self.batch.add(&in_v4, nftnl::MsgType::Add)?;
+ let mut in_v4 = Rule::new(&self.in_chain);
+ check_port(&mut in_v4, Udp, End::Src, SERVER_PORT_V4);
+ check_port(&mut in_v4, Udp, End::Dst, CLIENT_PORT_V4);
+ add_verdict(&mut in_v4, &Verdict::Accept);
+ self.batch.add(&in_v4, nftnl::MsgType::Add);
}
for dhcpv6_server in &*super::DHCPV6_SERVER_ADDRS {
- let mut out_v6 = Rule::new(&self.out_chain)?;
- check_net(&mut out_v6, End::Src, *super::LOCAL_INET6_NET)?;
- check_port(&mut out_v6, Udp, End::Src, CLIENT_PORT_V6)?;
- check_ip(&mut out_v6, End::Dst, *dhcpv6_server)?;
- check_port(&mut out_v6, Udp, End::Dst, SERVER_PORT_V6)?;
- add_verdict(&mut out_v6, &Verdict::Accept)?;
- self.batch.add(&out_v6, nftnl::MsgType::Add)?;
+ let mut out_v6 = Rule::new(&self.out_chain);
+ check_net(&mut out_v6, End::Src, *super::LOCAL_INET6_NET);
+ check_port(&mut out_v6, Udp, End::Src, CLIENT_PORT_V6);
+ check_ip(&mut out_v6, End::Dst, *dhcpv6_server);
+ check_port(&mut out_v6, Udp, End::Dst, SERVER_PORT_V6);
+ add_verdict(&mut out_v6, &Verdict::Accept);
+ self.batch.add(&out_v6, nftnl::MsgType::Add);
}
{
- let mut in_v6 = Rule::new(&self.in_chain)?;
- check_net(&mut in_v6, End::Src, *super::LOCAL_INET6_NET)?;
- check_port(&mut in_v6, Udp, End::Src, SERVER_PORT_V6)?;
- check_net(&mut in_v6, End::Dst, *super::LOCAL_INET6_NET)?;
- check_port(&mut in_v6, Udp, End::Dst, CLIENT_PORT_V6)?;
- add_verdict(&mut in_v6, &Verdict::Accept)?;
- self.batch.add(&in_v6, nftnl::MsgType::Add)?;
+ let mut in_v6 = Rule::new(&self.in_chain);
+ check_net(&mut in_v6, End::Src, *super::LOCAL_INET6_NET);
+ check_port(&mut in_v6, Udp, End::Src, SERVER_PORT_V6);
+ check_net(&mut in_v6, End::Dst, *super::LOCAL_INET6_NET);
+ check_port(&mut in_v6, Udp, End::Dst, CLIENT_PORT_V6);
+ add_verdict(&mut in_v6, &Verdict::Accept);
+ self.batch.add(&in_v6, nftnl::MsgType::Add);
}
- Ok(())
}
fn add_policy_specific_rules(&mut self, policy: &FirewallPolicy) -> Result<()> {
@@ -276,8 +283,8 @@ impl<'a> PolicyBatch<'a> {
pingable_hosts,
allow_lan,
} => {
- self.add_allow_icmp_pingable_hosts(&pingable_hosts)?;
- self.add_allow_endpoint_rules(peer_endpoint)?;
+ self.add_allow_icmp_pingable_hosts(&pingable_hosts);
+ self.add_allow_endpoint_rules(peer_endpoint);
*allow_lan
}
FirewallPolicy::Connected {
@@ -285,7 +292,7 @@ impl<'a> PolicyBatch<'a> {
tunnel,
allow_lan,
} => {
- self.add_allow_endpoint_rules(peer_endpoint)?;
+ self.add_allow_endpoint_rules(peer_endpoint);
self.add_dns_rule(tunnel, TransportProtocol::Udp)?;
self.add_dns_rule(tunnel, TransportProtocol::Tcp)?;
self.add_allow_tunnel_rules(tunnel)?;
@@ -295,56 +302,52 @@ impl<'a> PolicyBatch<'a> {
};
if allow_lan {
- self.add_allow_lan_rules()?;
+ self.add_allow_lan_rules();
}
Ok(())
}
- fn add_allow_endpoint_rules(&mut self, endpoint: &Endpoint) -> Result<()> {
- let mut in_rule = Rule::new(&self.in_chain)?;
- check_endpoint(&mut in_rule, End::Src, endpoint)?;
+ fn add_allow_endpoint_rules(&mut self, endpoint: &Endpoint) {
+ let mut in_rule = Rule::new(&self.in_chain);
+ check_endpoint(&mut in_rule, End::Src, endpoint);
- in_rule.add_expr(&nft_expr!(ct state))?;
+ in_rule.add_expr(&nft_expr!(ct state));
let allowed_states = nftnl::expr::ct::States::ESTABLISHED.bits();
- in_rule.add_expr(&nft_expr!(bitwise mask allowed_states, xor 0u32))?;
- in_rule.add_expr(&nft_expr!(cmp != 0u32))?;
- add_verdict(&mut in_rule, &Verdict::Accept)?;
-
- self.batch.add(&in_rule, nftnl::MsgType::Add)?;
+ in_rule.add_expr(&nft_expr!(bitwise mask allowed_states, xor 0u32));
+ in_rule.add_expr(&nft_expr!(cmp != 0u32));
+ add_verdict(&mut in_rule, &Verdict::Accept);
+ self.batch.add(&in_rule, nftnl::MsgType::Add);
- let mut out_rule = Rule::new(&self.out_chain)?;
- check_endpoint(&mut out_rule, End::Dst, endpoint)?;
- add_verdict(&mut out_rule, &Verdict::Accept)?;
- self.batch.add(&out_rule, nftnl::MsgType::Add)?;
+ let mut out_rule = Rule::new(&self.out_chain);
+ check_endpoint(&mut out_rule, End::Dst, endpoint);
+ add_verdict(&mut out_rule, &Verdict::Accept);
- Ok(())
+ self.batch.add(&out_rule, nftnl::MsgType::Add);
}
- fn add_allow_icmp_pingable_hosts(&mut self, pingable_hosts: &[IpAddr]) -> Result<()> {
+ fn add_allow_icmp_pingable_hosts(&mut self, pingable_hosts: &[IpAddr]) {
for host in pingable_hosts {
let icmp_proto = match &host {
&IpAddr::V4(_) => libc::IPPROTO_ICMP as u8,
&IpAddr::V6(_) => libc::IPPROTO_ICMPV6 as u8,
};
- let mut out_rule = Rule::new(&self.out_chain)?;
- check_ip(&mut out_rule, End::Dst, *host)?;
- out_rule.add_expr(&nft_expr!(meta l4proto))?;
- out_rule.add_expr(&nft_expr!(cmp == icmp_proto))?;
- add_verdict(&mut out_rule, &Verdict::Accept)?;
- self.batch.add(&out_rule, nftnl::MsgType::Add)?;
+ let mut out_rule = Rule::new(&self.out_chain);
+ check_ip(&mut out_rule, End::Dst, *host);
+ out_rule.add_expr(&nft_expr!(meta l4proto));
+ out_rule.add_expr(&nft_expr!(cmp == icmp_proto));
+ add_verdict(&mut out_rule, &Verdict::Accept);
+ self.batch.add(&out_rule, nftnl::MsgType::Add);
- let mut in_rule = Rule::new(&self.in_chain)?;
- check_ip(&mut in_rule, End::Src, *host)?;
- in_rule.add_expr(&nft_expr!(meta l4proto))?;
- in_rule.add_expr(&nft_expr!(cmp == icmp_proto))?;
- add_verdict(&mut in_rule, &Verdict::Accept)?;
- self.batch.add(&in_rule, nftnl::MsgType::Add)?;
+ let mut in_rule = Rule::new(&self.in_chain);
+ check_ip(&mut in_rule, End::Src, *host);
+ in_rule.add_expr(&nft_expr!(meta l4proto));
+ in_rule.add_expr(&nft_expr!(cmp == icmp_proto));
+ add_verdict(&mut in_rule, &Verdict::Accept);
+ self.batch.add(&in_rule, nftnl::MsgType::Add);
}
-
- Ok(())
}
fn add_dns_rule(
@@ -357,10 +360,10 @@ impl<'a> PolicyBatch<'a> {
if let Some(ipv6_gateway) = tunnel.ipv6_gateway {
self.add_allow_dns_rule(&tunnel.interface, protocol, ipv6_gateway.into())?;
};
- let mut block_rule = Rule::new(&self.out_chain)?;
- check_port(&mut block_rule, protocol, End::Dst, 53)?;
- add_verdict(&mut block_rule, &Verdict::Drop)?;
- self.batch.add(&block_rule, nftnl::MsgType::Add)?;
+ let mut block_rule = Rule::new(&self.out_chain);
+ check_port(&mut block_rule, protocol, End::Dst, 53);
+ add_verdict(&mut block_rule, &Verdict::Drop);
+ self.batch.add(&block_rule, nftnl::MsgType::Add);
Ok(())
}
@@ -371,21 +374,21 @@ impl<'a> PolicyBatch<'a> {
protocol: TransportProtocol,
host: IpAddr,
) -> Result<()> {
- let mut allow_rule = Rule::new(&self.out_chain)?;
+ let mut allow_rule = Rule::new(&self.out_chain);
let daddr = match host {
IpAddr::V4(_) => nft_expr!(payload ipv4 daddr),
IpAddr::V6(_) => nft_expr!(payload ipv6 daddr),
};
check_iface(&mut allow_rule, Direction::Out, interface)?;
- check_port(&mut allow_rule, protocol, End::Dst, 53)?;
- check_l3proto(&mut allow_rule, host)?;
+ check_port(&mut allow_rule, protocol, End::Dst, 53);
+ check_l3proto(&mut allow_rule, host);
- allow_rule.add_expr(&daddr)?;
- allow_rule.add_expr(&nft_expr!(cmp == host))?;
- add_verdict(&mut allow_rule, &Verdict::Accept)?;
+ allow_rule.add_expr(&daddr);
+ allow_rule.add_expr(&nft_expr!(cmp == host));
+ add_verdict(&mut allow_rule, &Verdict::Accept);
- self.batch.add(&allow_rule, nftnl::MsgType::Add)?;
+ self.batch.add(&allow_rule, nftnl::MsgType::Add);
Ok(())
}
@@ -393,53 +396,52 @@ impl<'a> PolicyBatch<'a> {
self.batch.add(
&allow_interface_rule(&self.out_chain, Direction::Out, &tunnel.interface[..])?,
nftnl::MsgType::Add,
- )?;
+ );
self.batch.add(
&allow_interface_rule(&self.in_chain, Direction::In, &tunnel.interface[..])?,
nftnl::MsgType::Add,
- )?;
+ );
Ok(())
}
- fn add_allow_lan_rules(&mut self) -> Result<()> {
+ fn add_allow_lan_rules(&mut self) {
// LAN -> LAN
for chain in &[&self.in_chain, &self.out_chain] {
for net in &*super::PRIVATE_NETS {
- let mut rule = Rule::new(chain)?;
- check_net(&mut rule, End::Src, *net)?;
- check_net(&mut rule, End::Dst, *net)?;
- add_verdict(&mut rule, &Verdict::Accept)?;
- self.batch.add(&rule, nftnl::MsgType::Add)?;
+ let mut rule = Rule::new(chain);
+ check_net(&mut rule, End::Src, *net);
+ check_net(&mut rule, End::Dst, *net);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
}
- let mut rule = Rule::new(chain)?;
- check_net(&mut rule, End::Src, *super::LOCAL_INET6_NET)?;
- check_net(&mut rule, End::Dst, *super::LOCAL_INET6_NET)?;
- add_verdict(&mut rule, &Verdict::Accept)?;
- self.batch.add(&rule, nftnl::MsgType::Add)?;
+ let mut rule = Rule::new(chain);
+ check_net(&mut rule, End::Src, *super::LOCAL_INET6_NET);
+ check_net(&mut rule, End::Dst, *super::LOCAL_INET6_NET);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
}
// LAN -> multicast
for net in &*super::PRIVATE_NETS {
- let mut rule = Rule::new(&self.out_chain)?;
- check_net(&mut rule, End::Src, *net)?;
- check_net(&mut rule, End::Dst, *super::MULTICAST_NET)?;
- add_verdict(&mut rule, &Verdict::Accept)?;
+ let mut rule = Rule::new(&self.out_chain);
+ check_net(&mut rule, End::Src, *net);
+ check_net(&mut rule, End::Dst, *super::MULTICAST_NET);
+ add_verdict(&mut rule, &Verdict::Accept);
- self.batch.add(&rule, nftnl::MsgType::Add)?;
+ self.batch.add(&rule, nftnl::MsgType::Add);
// LAN -> SSDP + WS-Discovery protocols
- let mut rule = Rule::new(&self.out_chain)?;
- check_net(&mut rule, End::Src, *net)?;
- check_ip(&mut rule, End::Dst, *super::SSDP_IP)?;
- add_verdict(&mut rule, &Verdict::Accept)?;
+ let mut rule = Rule::new(&self.out_chain);
+ check_net(&mut rule, End::Src, *net);
+ check_ip(&mut rule, End::Dst, *super::SSDP_IP);
+ add_verdict(&mut rule, &Verdict::Accept);
- self.batch.add(&rule, nftnl::MsgType::Add)?;
+ self.batch.add(&rule, nftnl::MsgType::Add);
}
- let mut rule = Rule::new(&self.out_chain)?;
- check_net(&mut rule, End::Src, *super::LOCAL_INET6_NET)?;
- check_net(&mut rule, End::Dst, *super::MULTICAST_INET6_NET)?;
- add_verdict(&mut rule, &Verdict::Accept)?;
- self.batch.add(&rule, nftnl::MsgType::Add)?;
- Ok(())
+ let mut rule = Rule::new(&self.out_chain);
+ check_net(&mut rule, End::Src, *super::LOCAL_INET6_NET);
+ check_net(&mut rule, End::Dst, *super::MULTICAST_INET6_NET);
+ add_verdict(&mut rule, &Verdict::Accept);
+ self.batch.add(&rule, nftnl::MsgType::Add);
}
}
@@ -448,86 +450,78 @@ fn allow_interface_rule<'a>(
direction: Direction,
iface: &str,
) -> Result<Rule<'a>> {
- let mut rule = Rule::new(&chain)?;
+ let mut rule = Rule::new(&chain);
check_iface(&mut rule, direction, iface)?;
- add_verdict(&mut rule, &Verdict::Accept)?;
+ add_verdict(&mut rule, &Verdict::Accept);
Ok(rule)
}
fn check_iface(rule: &mut Rule, direction: Direction, iface: &str) -> Result<()> {
- let iface_index = crate::linux::iface_index(iface)?;
+ let iface_index = crate::linux::iface_index(iface)
+ .map_err(|e| Error::LookupIfaceIndexError(iface.to_owned(), e))?;
rule.add_expr(&match direction {
Direction::In => nft_expr!(meta iif),
Direction::Out => nft_expr!(meta oif),
- })?;
- rule.add_expr(&nft_expr!(cmp == iface_index))?;
+ });
+ rule.add_expr(&nft_expr!(cmp == iface_index));
Ok(())
}
-fn check_net(rule: &mut Rule, end: End, net: IpNetwork) -> Result<()> {
+fn check_net(rule: &mut Rule, end: End, net: IpNetwork) {
// Must check network layer protocol before loading network layer payload
- check_l3proto(rule, net.ip())?;
+ check_l3proto(rule, net.ip());
rule.add_expr(&match (net, end) {
(IpNetwork::V4(_), End::Src) => nft_expr!(payload ipv4 saddr),
(IpNetwork::V4(_), End::Dst) => nft_expr!(payload ipv4 daddr),
(IpNetwork::V6(_), End::Src) => nft_expr!(payload ipv6 saddr),
(IpNetwork::V6(_), End::Dst) => nft_expr!(payload ipv6 daddr),
- })?;
+ });
match net {
- IpNetwork::V4(_) => rule.add_expr(&nft_expr!(bitwise mask net.mask(), xor 0u32))?,
- IpNetwork::V6(_) => {
- rule.add_expr(&nft_expr!(bitwise mask net.mask(), xor &[0u16; 8][..]))?
- }
+ IpNetwork::V4(_) => rule.add_expr(&nft_expr!(bitwise mask net.mask(), xor 0u32)),
+ IpNetwork::V6(_) => rule.add_expr(&nft_expr!(bitwise mask net.mask(), xor &[0u16; 8][..])),
};
- rule.add_expr(&nft_expr!(cmp == net.ip()))?;
-
- Ok(())
+ rule.add_expr(&nft_expr!(cmp == net.ip()));
}
-fn check_endpoint(rule: &mut Rule, end: End, endpoint: &Endpoint) -> Result<()> {
- check_ip(rule, end, endpoint.address.ip())?;
- check_port(rule, endpoint.protocol, end, endpoint.address.port())?;
- Ok(())
+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());
}
-
-fn check_ip(rule: &mut Rule, end: End, ip: IpAddr) -> Result<()> {
+fn check_ip(rule: &mut Rule, end: End, ip: IpAddr) {
// Must check network layer protocol before loading network layer payload
- check_l3proto(rule, ip)?;
+ check_l3proto(rule, ip);
rule.add_expr(&match (ip, end) {
(IpAddr::V4(..), End::Src) => nft_expr!(payload ipv4 saddr),
(IpAddr::V4(..), End::Dst) => nft_expr!(payload ipv4 daddr),
(IpAddr::V6(..), End::Src) => nft_expr!(payload ipv6 saddr),
(IpAddr::V6(..), End::Dst) => nft_expr!(payload ipv6 daddr),
- })?;
+ });
match ip {
- IpAddr::V4(addr) => rule.add_expr(&nft_expr!(cmp == addr))?,
- IpAddr::V6(addr) => rule.add_expr(&nft_expr!(cmp == addr))?,
+ IpAddr::V4(addr) => rule.add_expr(&nft_expr!(cmp == addr)),
+ IpAddr::V6(addr) => rule.add_expr(&nft_expr!(cmp == addr)),
}
- Ok(())
}
-fn check_port(rule: &mut Rule, protocol: TransportProtocol, end: End, port: u16) -> Result<()> {
+fn check_port(rule: &mut Rule, protocol: TransportProtocol, end: End, port: u16) {
// Must check transport layer protocol before loading transport layer payload
- check_l4proto(rule, protocol)?;
+ check_l4proto(rule, protocol);
rule.add_expr(&match (protocol, end) {
(TransportProtocol::Udp, End::Src) => nft_expr!(payload udp sport),
(TransportProtocol::Udp, End::Dst) => nft_expr!(payload udp dport),
(TransportProtocol::Tcp, End::Src) => nft_expr!(payload tcp sport),
(TransportProtocol::Tcp, End::Dst) => nft_expr!(payload tcp dport),
- })?;
- rule.add_expr(&nft_expr!(cmp == port.to_be()))?;
- Ok(())
+ });
+ rule.add_expr(&nft_expr!(cmp == port.to_be()));
}
-fn check_l3proto(rule: &mut Rule, ip: IpAddr) -> Result<()> {
- rule.add_expr(&nft_expr!(meta nfproto))?;
- rule.add_expr(&nft_expr!(cmp == l3proto(ip)))?;
- Ok(())
+fn check_l3proto(rule: &mut Rule, ip: IpAddr) {
+ rule.add_expr(&nft_expr!(meta nfproto));
+ rule.add_expr(&nft_expr!(cmp == l3proto(ip)));
}
fn l3proto(addr: IpAddr) -> u8 {
@@ -537,10 +531,9 @@ fn l3proto(addr: IpAddr) -> u8 {
}
}
-fn check_l4proto(rule: &mut Rule, protocol: TransportProtocol) -> Result<()> {
- rule.add_expr(&nft_expr!(meta l4proto))?;
- rule.add_expr(&nft_expr!(cmp == l4proto(protocol)))?;
- Ok(())
+fn check_l4proto(rule: &mut Rule, protocol: TransportProtocol) {
+ rule.add_expr(&nft_expr!(meta l4proto));
+ rule.add_expr(&nft_expr!(cmp == l4proto(protocol)));
}
fn l4proto(protocol: TransportProtocol) -> u8 {
@@ -550,10 +543,9 @@ fn l4proto(protocol: TransportProtocol) -> u8 {
}
}
-fn add_verdict(rule: &mut Rule, verdict: &expr::Verdict) -> Result<()> {
+fn add_verdict(rule: &mut Rule, verdict: &expr::Verdict) {
if *ADD_COUNTERS {
- rule.add_expr(&nft_expr!(counter))?;
+ rule.add_expr(&nft_expr!(counter));
}
- rule.add_expr(verdict)?;
- Ok(())
+ rule.add_expr(verdict);
}