From a3224bcba18591d3ab3abac43e2a724e416828b8 Mon Sep 17 00:00:00 2001 From: AlexandreBrg Date: Thu, 11 May 2023 19:16:44 +0200 Subject: [PATCH] chore(riklet): improve security on iptables * Accept only external request and target TAP interfaces of microVM. Previously we were accepting all requests and applying conntrack on it, it was unsafe. Signed-off-by: AlexandreBrg --- docs/src/reference/riklet.md | 8 ++--- riklet/README.md | 8 ++--- riklet/src/cli/function_config.rs | 1 - riklet/src/core.rs | 2 +- .../src/runtime/network/function_network.rs | 13 +++++++-- riklet/src/runtime/network/mod.rs | 29 +++++-------------- 6 files changed, 27 insertions(+), 34 deletions(-) diff --git a/docs/src/reference/riklet.md b/docs/src/reference/riklet.md index 2c9f7be..71d6dac 100644 --- a/docs/src/reference/riklet.md +++ b/docs/src/reference/riklet.md @@ -19,8 +19,8 @@ To run riklet with FAAS configuration. ```bash sudo riklet --kernel-path ${KERNEL_LOCATION} \ - --ifnet ${IFACE} \ - --ifnet-ip ${IFACE_IP} \ + --iface ${IFACE} \ + --iface-ip ${IFACE_IP} \ ``` > The firecracker binary location is determined by the following order: @@ -33,7 +33,7 @@ Exemple: ```bash sudo riklet --kernel-path ./vmlinux.bin \ - --ifnet wlp2s0 \ - --ifnet-ip 192.168.1.84 \ + --iface wlp2s0 \ + --iface-ip 192.168.1.84 \ --script-path ./scripts/setup-host-tap.sh ``` diff --git a/riklet/README.md b/riklet/README.md index 2cc5f83..705c169 100644 --- a/riklet/README.md +++ b/riklet/README.md @@ -54,8 +54,8 @@ To run riklet with FAAS configuration. ```bash sudo riklet --kernel-path ${KERNEL_LOCATION} \ - --ifnet ${IFACE} \ - --ifnet-ip ${IFACE_IP} \ + --iface ${IFACE} \ + --iface-ip ${IFACE_IP} \ ``` > The firecracker binary location is determined by the following order: @@ -68,8 +68,8 @@ Exemple: ```bash sudo riklet --kernel-path ./vmlinux.bin \ - --ifnet wlp2s0 \ - --ifnet-ip 192.168.1.84 + --iface wlp2s0 \ + --iface-ip 192.168.1.84 ``` You should see something like that : diff --git a/riklet/src/cli/function_config.rs b/riklet/src/cli/function_config.rs index 8e0d822..783620d 100644 --- a/riklet/src/cli/function_config.rs +++ b/riklet/src/cli/function_config.rs @@ -31,7 +31,6 @@ impl FnConfiguration { None => get_default_iface()?, }; Ok(FnConfiguration { - firecracker_location: opts.firecracker_path, kernel_location: opts.kernel_path, gateway_ip, iface, diff --git a/riklet/src/core.rs b/riklet/src/core.rs index 51aae38..4f92cd0 100644 --- a/riklet/src/core.rs +++ b/riklet/src/core.rs @@ -205,7 +205,7 @@ impl Riklet { let fn_configuration = FnConfiguration::load().map_err(|e| RikletError::InvalidInput(e.to_string()))?; - let mut global_runtime_network = GlobalRuntimeNetwork::new(fn_configuration.gateway_ip) + let mut global_runtime_network = GlobalRuntimeNetwork::new(fn_configuration.iface) .map_err(|e| RikletError::NetworkError(NetworkError::IptablesError(e)))?; global_runtime_network .init() diff --git a/riklet/src/runtime/network/function_network.rs b/riklet/src/runtime/network/function_network.rs index 1a11132..dcbb4e4 100644 --- a/riklet/src/runtime/network/function_network.rs +++ b/riklet/src/runtime/network/function_network.rs @@ -98,6 +98,15 @@ impl FunctionRuntimeNetwork { table: Table::Filter, chain: Chain::Forward, }; + let filter_conntrack = Rule { + chain: Chain::Forward, + table: Table::Filter, + rule: format!( + "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -o {}", + self.tap_name()? + ), + }; + rules.push(filter_conntrack); rules.push(rule); // port mapping for (exposed_port, internal_port) in self.port_mapping.iter() { @@ -214,7 +223,7 @@ mod tests { use super::FunctionRuntimeNetwork; - const GATEWAY_MOCK: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1); + const GATEWAY_MOCK: &str = "eth0"; fn open_tap_shell(iface_name: &str) -> Result<(), String> { let tap_output = Command::new("ip") @@ -281,7 +290,7 @@ mod tests { #[tokio::test] #[serial] async fn apply_exposure_network_routing() { - let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK).unwrap(); + let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK.to_string()).unwrap(); let result = network.init().await; assert!(result.is_ok()); diff --git a/riklet/src/runtime/network/mod.rs b/riklet/src/runtime/network/mod.rs index 469fc5c..f56ff48 100644 --- a/riklet/src/runtime/network/mod.rs +++ b/riklet/src/runtime/network/mod.rs @@ -5,7 +5,6 @@ use async_trait::async_trait; use once_cell::sync::Lazy; use shared::utils::ip_allocator::IpAllocator; use std::fmt::Debug; -use std::net::Ipv4Addr; use std::sync::Mutex; use thiserror::Error; @@ -58,13 +57,11 @@ pub struct GlobalRuntimeNetwork { iptables: Iptables, /// Name of the interface that will be used as the gateway for the network - gateway_iface: Ipv4Addr, + gateway_iface: String, } impl GlobalRuntimeNetwork { - pub fn new( - gateway_iface: Ipv4Addr, - ) -> std::result::Result { + pub fn new(gateway_iface: String) -> std::result::Result { Ok(GlobalRuntimeNetwork { iptables: Iptables::new(true)?, gateway_iface, @@ -122,17 +119,9 @@ impl RuntimeNetwork for GlobalRuntimeNetwork { rule: format!("-o {} -j MASQUERADE", self.gateway_iface), }; - let filter_conntrack = Rule { - chain: Chain::Forward, - table: Table::Filter, - rule: "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT".to_string(), - }; self.iptables .create(&nat_masquerade) .map_err(NetworkError::IptablesError)?; - self.iptables - .create(&filter_conntrack) - .map_err(NetworkError::IptablesError)?; Ok(()) } @@ -151,12 +140,12 @@ mod tests { use crate::runtime::network::{GlobalRuntimeNetwork, RuntimeNetwork}; use serial_test::serial; - const GATEWAY_MOCK: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1); + const GATEWAY_MOCK: &str = "eth0"; #[tokio::test] #[serial] async fn test_network_init_ok() { - let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK).unwrap(); + let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK.to_string()).unwrap(); let result = network.init().await; assert!(result.is_ok()); let result = network.destroy().await; @@ -166,7 +155,7 @@ mod tests { #[tokio::test] #[serial] async fn test_network_init_drop() { - let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK).unwrap(); + let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK.to_string()).unwrap(); let result = network.init().await; assert!(result.is_ok()); @@ -213,19 +202,15 @@ mod tests { #[tokio::test] #[serial] async fn test_multiple_global_network_fails() { - let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK).unwrap(); + let mut network = GlobalRuntimeNetwork::new(GATEWAY_MOCK.to_string()).unwrap(); let result = network.init().await; assert!(result.is_ok()); - let mut network2 = GlobalRuntimeNetwork::new(GATEWAY_MOCK).unwrap(); + let mut network2 = GlobalRuntimeNetwork::new(GATEWAY_MOCK.to_string()).unwrap(); let result = network2.init().await; assert!(result.is_err()); let result = network.destroy().await; assert!(result.is_ok()); } - - fn test_to_string_gateway() { - assert_eq!(GATEWAY_MOCK.to_string(), "192.168.0.1".to_string()); - } }