Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
TRIGGERED_REF=v5.15.10
TRIGGERED_REF=test-orig-ip
83 changes: 64 additions & 19 deletions crates/telio-firewall/src/chain_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::libfirewall::{
LIBFW_CONTRACK_STATE_RELATED, LIBFW_DIRECTION_INBOUND, LIBFW_DIRECTION_OUTBOUND,
LIBFW_FILTER_ASSOCIATED_DATA, LIBFW_FILTER_CONNTRACK_STATE, LIBFW_FILTER_DIRECTION,
LIBFW_FILTER_DNS_QUERY_DOMAIN, LIBFW_FILTER_DST_NETWORK, LIBFW_FILTER_ICMP_TYPE,
LIBFW_FILTER_NEXT_LVL_PROTO, LIBFW_FILTER_SRC_NETWORK, LIBFW_FILTER_TCP_FLAGS,
LIBFW_ICMP_TYPE_DESTINATION_UNREACHABLE, LIBFW_ICMP_TYPE_ECHO_REPLY,
LIBFW_FILTER_NEXT_LVL_PROTO, LIBFW_FILTER_ORIG_SRC_IP, LIBFW_FILTER_SRC_NETWORK,
LIBFW_FILTER_TCP_FLAGS, LIBFW_ICMP_TYPE_DESTINATION_UNREACHABLE, LIBFW_ICMP_TYPE_ECHO_REPLY,
LIBFW_ICMP_TYPE_ECHO_REQUEST, LIBFW_ICMP_TYPE_PARAMETER_PROBLEM,
LIBFW_ICMP_TYPE_REDIRECT_MESSAGE, LIBFW_ICMP_TYPE_ROUTER_ADVERTISEMENT,
LIBFW_ICMP_TYPE_ROUTER_SOLICITATION, LIBFW_ICMP_TYPE_TIMESTAMP,
Expand Down Expand Up @@ -93,6 +93,7 @@ pub(crate) enum FilterData {
TcpFlags(u8),
IcmpType(IcmpType),
DnsQueryDomain(Vec<String>),
OrigSrcIp(IpAddr),
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -120,24 +121,28 @@ impl From<&[u8]> for LibfwAssociatedData {
}
}

fn libfw_ip_addr(ip: IpAddr) -> LibfwIpAddr {
let (ip_type, ip_data) = match ip {
IpAddr::V4(ipv4_addr) => (
LIBFW_IP_TYPE_V4,
LibfwIpData {
ipv4_bytes: ipv4_addr.octets(),
},
),
IpAddr::V6(ipv6_addr) => (
LIBFW_IP_TYPE_V6,
LibfwIpData {
ipv6_bytes: ipv6_addr.octets(),
},
),
};
LibfwIpAddr { ip_type, ip_data }
}

impl From<&NetworkFilterData> for LibfwNetworkFilter {
fn from(value: &NetworkFilterData) -> Self {
let (ip_type, ip_data) = match value.network.network() {
IpAddr::V4(ipv4_addr) => (
LIBFW_IP_TYPE_V4,
LibfwIpData {
ipv4_bytes: ipv4_addr.octets(),
},
),
IpAddr::V6(ipv6_addr) => (
LIBFW_IP_TYPE_V6,
LibfwIpData {
ipv6_bytes: ipv6_addr.octets(),
},
),
};
LibfwNetworkFilter {
network_addr: LibfwIpAddr { ip_type, ip_data },
network_addr: libfw_ip_addr(value.network.network()),
network_prefix: value.network.prefix_len(),
port_range_start: value.port_range.0,
port_range_end: value.port_range.1,
Expand Down Expand Up @@ -266,6 +271,13 @@ impl From<&Filter> for (LibfwFilter, Option<FilterExtraData>) {
Some(FilterExtraData::DomainSet(pinned)),
)
}
FilterData::OrigSrcIp(ip) => (
LibfwFilterData {
orig_src_ip: libfw_ip_addr(*ip),
},
LIBFW_FILTER_ORIG_SRC_IP,
None,
),
};
(
LibfwFilter {
Expand Down Expand Up @@ -380,8 +392,9 @@ pub mod tests {
LIBFW_CONTRACK_STATE_ESTABLISHED, LIBFW_DIRECTION_INBOUND, LIBFW_DIRECTION_OUTBOUND,
LIBFW_FILTER_ASSOCIATED_DATA, LIBFW_FILTER_CONNTRACK_STATE, LIBFW_FILTER_DIRECTION,
LIBFW_FILTER_DNS_QUERY_DOMAIN, LIBFW_FILTER_DST_NETWORK, LIBFW_FILTER_ICMP_TYPE,
LIBFW_FILTER_NEXT_LVL_PROTO, LIBFW_FILTER_SRC_NETWORK, LIBFW_FILTER_TCP_FLAGS,
LIBFW_ICMP_TYPE_ECHO_REPLY, LIBFW_IP_TYPE_V4, LIBFW_IP_TYPE_V6, LIBFW_NEXT_PROTO_UDP,
LIBFW_FILTER_NEXT_LVL_PROTO, LIBFW_FILTER_ORIG_SRC_IP, LIBFW_FILTER_SRC_NETWORK,
LIBFW_FILTER_TCP_FLAGS, LIBFW_ICMP_TYPE_ECHO_REPLY, LIBFW_IP_TYPE_V4, LIBFW_IP_TYPE_V6,
LIBFW_NEXT_PROTO_UDP,
},
};

Expand Down Expand Up @@ -429,6 +442,12 @@ pub mod tests {
filter_data: FilterData::IcmpType(IcmpType::EchoReply),
inverted: true,
},
Filter {
filter_data: FilterData::OrigSrcIp(std::net::IpAddr::V4(Ipv4Addr::new(
10, 0, 0, 5,
))),
inverted: false,
},
],
action: RuleAction::Drop,
},
Expand Down Expand Up @@ -540,6 +559,18 @@ pub mod tests {
icmp_type: LIBFW_ICMP_TYPE_ECHO_REPLY,
},
},
LibfwFilter {
inverted: false,
filter_type: LIBFW_FILTER_ORIG_SRC_IP,
filter: LibfwFilterData {
orig_src_ip: LibfwIpAddr {
ip_type: LIBFW_IP_TYPE_V4,
ip_data: LibfwIpData {
ipv4_bytes: [10, 0, 0, 5],
},
},
},
},
];

let assoc_data = vec![1u8; 32];
Expand Down Expand Up @@ -710,6 +741,20 @@ pub mod tests {
});
}
}
LIBFW_FILTER_ORIG_SRC_IP => {
let c = unsafe { conv.filter.orig_src_ip };
let e = unsafe { expected.filter.orig_src_ip };
assert_eq!(c.ip_type, e.ip_type);
match c.ip_type {
LIBFW_IP_TYPE_V4 => assert_eq!(unsafe { c.ip_data.ipv4_bytes }, unsafe {
e.ip_data.ipv4_bytes
}),
LIBFW_IP_TYPE_V6 => assert_eq!(unsafe { c.ip_data.ipv6_bytes }, unsafe {
e.ip_data.ipv6_bytes
}),
_ => unreachable!("Unknown IP type"),
};
}
_ => unreachable!("Unexpected filter type"),
}
}
Expand Down
29 changes: 7 additions & 22 deletions crates/telio-firewall/src/firewall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ use telio_utils::{

use crate::{
chain_helpers::{
ConnectionState, Direction, FfiChainGuard, Filter, FilterData, NetworkFilterData,
NextLevelProtocol, Rule, RuleAction,
Direction, FfiChainGuard, Filter, FilterData, NetworkFilterData, NextLevelProtocol, Rule,
RuleAction,
},
libfirewall::{LibfwChainV2, LibfwFirewall, LibfwLogLevel, LibfwResult, LibfwVerdict},
tp_lite_stats::{collect_stats, CallbackManager},
Expand Down Expand Up @@ -658,27 +658,12 @@ pub(crate) fn build_chain_rules(
});
}

// Accept packets for locally initiated connections
// Accept incoming packets only for connections initiated from this IP
rules.push(Rule {
filters: vec![
Filter {
filter_data: FilterData::ConntrackState(ConnectionState::Established),
inverted: false,
},
filter_dst_ip_all_ports(IpNet::from(*ip), false),
],
action: RuleAction::Accept,
});

// And packets related to them
rules.push(Rule {
filters: vec![
Filter {
filter_data: FilterData::ConntrackState(ConnectionState::Related),
inverted: false,
},
filter_dst_ip_all_ports(IpNet::from(*ip), false),
],
filters: vec![Filter {
filter_data: FilterData::OrigSrcIp(*ip),
inverted: false,
}],
action: RuleAction::Accept,
});

Expand Down
3 changes: 3 additions & 0 deletions crates/telio-firewall/src/libfirewall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub const LIBFW_FILTER_NEXT_LVL_PROTO: u8 = 5;
pub const LIBFW_FILTER_TCP_FLAGS: u8 = 6;
pub const LIBFW_FILTER_ICMP_TYPE: u8 = 7;
pub const LIBFW_FILTER_DNS_QUERY_DOMAIN: u8 = 8;
pub const LIBFW_FILTER_ORIG_SRC_IP: u8 = 9;
#[repr(u32)]
#[doc = " Log levels used in LibfwLogCallback\n"]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -182,6 +183,8 @@ pub union LibfwFilterData {
pub icmp_type: u8,
#[doc = " Set of DNS domain patterns to match against DNS query QNAMEs\n Use when filter_type = LibfwFilterDnsQueryDomain"]
pub dns_domain_set: LibfwDnsDomainSet,
#[doc = " Source IP of the connection's original (initiating) direction, taken from conntrack\n Use when filter_type = LIBFW_FILTER_ORIG_SRC_IP"]
pub orig_src_ip: LibfwIpAddr,
}
#[doc = " Struct describing a single Libfw filter\n"]
#[repr(C)]
Expand Down
Loading
Loading