[windows_kext] Remove inbound ALE layer

This commit is contained in:
Vladimir Stoilov 2024-06-05 14:57:22 +03:00
parent 9fe140bd02
commit 1730250a86
No known key found for this signature in database
GPG key ID: 2F190B67A43A81AF
4 changed files with 35 additions and 93 deletions
windows_kext

View file

@ -7,10 +7,7 @@ use smoltcp::wire::{
IpAddress, IpProtocol, Ipv4Address, Ipv6Address, IPV4_HEADER_LEN, IPV6_HEADER_LEN,
};
use wdk::filter_engine::callout_data::CalloutData;
use wdk::filter_engine::layer::{
self, FieldsAleAuthConnectV4, FieldsAleAuthConnectV6, FieldsAleAuthRecvAcceptV4,
FieldsAleAuthRecvAcceptV6, ValueType,
};
use wdk::filter_engine::layer::{self, FieldsAleAuthConnectV4, FieldsAleAuthConnectV6, ValueType};
use wdk::filter_engine::net_buffer::NetBufferList;
use wdk::filter_engine::packet::{Injector, TransportPacketList};
@ -87,24 +84,6 @@ pub fn ale_layer_connect_v4(data: CalloutData) {
ale_layer_auth(data, ale_data);
}
pub fn ale_layer_accept_v4(data: CalloutData) {
type Fields = FieldsAleAuthRecvAcceptV4;
let ale_data = AleLayerData {
is_ipv6: false,
reauthorize: data.is_reauthorize(Fields::Flags as usize),
process_id: data.get_process_id().unwrap_or(0),
protocol: get_protocol(&data, Fields::IpProtocol as usize),
direction: Direction::Inbound,
local_ip: get_ipv4_address(&data, Fields::IpLocalAddress as usize),
local_port: data.get_value_u16(Fields::IpLocalPort as usize),
remote_ip: get_ipv4_address(&data, Fields::IpRemoteAddress as usize),
remote_port: data.get_value_u16(Fields::IpRemotePort as usize),
interface_index: data.get_value_u32(Fields::InterfaceIndex as usize),
sub_interface_index: data.get_value_u32(Fields::SubInterfaceIndex as usize),
};
ale_layer_auth(data, ale_data);
}
pub fn ale_layer_connect_v6(data: CalloutData) {
type Fields = FieldsAleAuthConnectV6;
@ -125,24 +104,6 @@ pub fn ale_layer_connect_v6(data: CalloutData) {
ale_layer_auth(data, ale_data);
}
pub fn ale_layer_accept_v6(data: CalloutData) {
type Fields = FieldsAleAuthRecvAcceptV6;
let ale_data = AleLayerData {
is_ipv6: true,
reauthorize: data.is_reauthorize(Fields::Flags as usize),
process_id: data.get_process_id().unwrap_or(0),
protocol: get_protocol(&data, Fields::IpProtocol as usize),
direction: Direction::Inbound,
local_ip: get_ipv6_address(&data, Fields::IpLocalAddress as usize),
local_port: data.get_value_u16(Fields::IpLocalPort as usize),
remote_ip: get_ipv6_address(&data, Fields::IpRemoteAddress as usize),
remote_port: data.get_value_u16(Fields::IpRemotePort as usize),
interface_index: data.get_value_u32(Fields::InterfaceIndex as usize),
sub_interface_index: data.get_value_u32(Fields::SubInterfaceIndex as usize),
};
ale_layer_auth(data, ale_data);
}
fn ale_layer_auth(mut data: CalloutData, ale_data: AleLayerData) {
let Some(device) = crate::entry::get_device() else {
return;
@ -287,7 +248,21 @@ fn save_packet(
ale_data: &AleLayerData,
pend: bool,
) -> Result<Packet, alloc::string::String> {
let packet_list = create_packet_list(device, callout_data, ale_data);
let mut packet_list = None;
let mut save_packet_list = true;
match ale_data.protocol {
IpProtocol::Tcp => {
if let Direction::Outbound = ale_data.direction {
// Only time a packet data is missing is during connect state of outbound TCP connection.
// Don't save packet list only if connection is outbound, reauthorize is false and the protocol is TCP.
save_packet_list = ale_data.reauthorize;
}
}
_ => {}
};
if save_packet_list {
packet_list = create_packet_list(device, callout_data, ale_data);
}
if pend && matches!(ale_data.protocol, IpProtocol::Tcp | IpProtocol::Udp) {
match callout_data.pend_operation(packet_list) {
Ok(classify_defer) => Ok(Packet::AleLayer(classify_defer)),

View file

@ -20,15 +20,6 @@ pub fn get_callout_vec() -> Vec<Callout> {
FilterType::Resettable,
ale_callouts::ale_layer_connect_v4,
),
Callout::new(
"AleLayerInboundV4",
"ALE layer for inbound connections for ipv4",
0xc6021395_0724_4e2c_ae20_3dde51fc3c68,
Layer::AleAuthRecvAcceptV4,
consts::FWP_ACTION_CALLOUT_TERMINATING,
FilterType::Resettable,
ale_callouts::ale_layer_accept_v4,
),
Callout::new(
"AleLayerOutboundV6",
"ALE layer for outbound connections for ipv6",
@ -38,15 +29,6 @@ pub fn get_callout_vec() -> Vec<Callout> {
FilterType::Resettable,
ale_callouts::ale_layer_connect_v6,
),
Callout::new(
"AleLayerInboundV6",
"ALE layer for inbound connections for ipv6",
0xd24480da_38fa_4099_9383_b5c83b69e4f2,
Layer::AleAuthRecvAcceptV6,
consts::FWP_ACTION_CALLOUT_TERMINATING,
FilterType::Resettable,
ale_callouts::ale_layer_accept_v6,
),
// -----------------------------------------
// ALE connection end layers
Callout::new(

View file

@ -13,7 +13,6 @@ use crate::connection_cache::ConnectionCache;
use crate::connection_map::Key;
use crate::device::{Device, Packet};
use crate::packet_util::{get_key_from_nbl_v4, get_key_from_nbl_v6, Redirect};
use crate::{err, warn};
// IP packet layers
pub fn ip_packet_layer_outbound_v4(data: CalloutData) {
@ -141,7 +140,7 @@ fn ip_packet_layer(
} {
Ok(key) => key,
Err(err) => {
warn!("failed to get key from nbl: {}", err);
crate::warn!("failed to get key from nbl: {}", err);
return;
}
};
@ -151,7 +150,7 @@ fn ip_packet_layer(
return;
}
let mut is_tmp_verdict = false;
let mut send_request_to_portmaster = true;
let mut process_id = 0;
if matches!(
@ -164,13 +163,17 @@ fn ip_packet_layer(
process_id = conn_info.process_id;
// Check if there is action for this connection.
match conn_info.verdict {
Verdict::Undecided | Verdict::Accept | Verdict::Block | Verdict::Drop => {
is_tmp_verdict = true
Verdict::Undecided | Verdict::Accept | Verdict::Block | Verdict::Drop => {}
Verdict::PermanentAccept => {
send_request_to_portmaster = false;
data.action_permit();
}
Verdict::PermanentBlock => {
send_request_to_portmaster = false;
data.action_block();
}
Verdict::PermanentAccept => data.action_permit(),
Verdict::PermanentBlock => data.action_block(),
Verdict::Undeterminable | Verdict::PermanentDrop | Verdict::Failed => {
data.block_and_absorb()
data.block_and_absorb();
}
Verdict::RedirectNameServer | Verdict::RedirectTunnel => {
if let Some(redirect_info) = conn_info.redirect_info.take() {
@ -186,10 +189,10 @@ fn ip_packet_layer(
Ok(mut packet) => {
let _ = packet.redirect(redirect_info);
if let Err(err) = device.inject_packet(packet, false) {
err!("failed to inject packet: {}", err);
crate::err!("failed to inject packet: {}", err);
}
}
Err(err) => err!("failed to clone packet: {}", err),
Err(err) => crate::err!("failed to clone packet: {}", err),
}
}
@ -198,25 +201,11 @@ fn ip_packet_layer(
continue;
}
}
} else {
// TCP and UDP always need to go through ALE layer first.
if matches!(direction, Direction::Inbound) {
// If it's an inbound packet and the connection is not found, we need to continue to ALE layer
data.action_permit();
return;
} else {
// This happens sometimes. Leave the decision for portmaster. TODO(vladimir): Find out why.
err!("Invalid state for: {}", key);
is_tmp_verdict = true;
}
}
} else {
// Every other protocol treat as a tmp verdict.
is_tmp_verdict = true;
}
// Clone packet and send to Portmaster if it's a temporary verdict.
if is_tmp_verdict {
// Clone packet and send to Portmaster.
if send_request_to_portmaster {
let packet = match clone_packet(
device,
nbl,
@ -228,7 +217,7 @@ fn ip_packet_layer(
) {
Ok(p) => p,
Err(err) => {
err!("failed to clone packet: {}", err);
crate::err!("failed to clone packet: {}", err);
return;
}
};
@ -236,6 +225,7 @@ fn ip_packet_layer(
let info = device
.packet_cache
.push((key, packet), process_id, direction, false);
// Send to Portmaster
if let Some(info) = info {
let _ = device.event_queue.push(info);

View file

@ -32,13 +32,8 @@ impl ClassifyDefer {
unsafe {
match self {
ClassifyDefer::Initial(context, packet_list) => {
if let Some(packet) = packet_list {
FwpsCompleteOperation0(context, packet.net_buffer_list.nbl as _);
return Ok(Some(packet));
} else {
FwpsCompleteOperation0(context, core::ptr::null_mut());
}
return Ok(None);
FwpsCompleteOperation0(context, core::ptr::null_mut());
return Ok(packet_list);
}
ClassifyDefer::Reauthorization(_callout_id, packet_list) => {
// There is no way to reset single filter. If another request for filter reset is trigger at the same time it will fail.