Skip to content

Commit c415089

Browse files
[#107]: Updated the get_veth_channels() function to dynamically check Ethernet interfaces-related activity. Authors: @siddh34 @LorenzoTettamanti
2 parents 8c60f59 + 54a9861 commit c415089

11 files changed

Lines changed: 655 additions & 174 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,5 @@ admission-webhook.yaml
173173
certificate-manager.yaml
174174
client-deployment.yaml
175175
dns-deployment.yaml
176-
proxy-injector.yaml
176+
proxy-injector.yaml
177+
core/src/components/conntracker/src/bindings.rs

cli/Cargo.toml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
name = "cortexflow-cli"
33
version = "0.1.0"
44
edition = "2024"
5+
description = "CortexFlow command line interface made to interact with the CortexBrain core components"
6+
authors = ["Lorenzo Tettamanti", "Pranav Verma", "Lorenzo Bradanini"]
7+
documentation = "https://docs.cortexflow.org"
8+
homepage = "https://docs.cortexflow.org"
9+
repository = "https://github.com/CortexFlow/CortexBrain"
10+
license = "Apache-2.0"
511

612
[dependencies]
713
clap = { version = "4.5.38", features = ["derive"] }
814
tracing = "0.1.41"
915

10-
#commented until first release
11-
12-
#[[bin]]
13-
#name="cfcli"
14-
#path="src/main.rs"
16+
[[bin]]
17+
name = "cfcli"
18+
path = "src/main.rs"

core/src/components/conntracker/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name = "conntracker"
33
version = "0.1.0"
44
edition = "2021"
55

6+
67
[dependencies]
78
aya-ebpf = { git = "https://github.com/aya-rs/aya" }
89
aya-log-ebpf = { git = "https://github.com/aya-rs/aya" }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
11
echo "🚀 Building connection tracker"
2+
3+
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
4+
5+
if [ $? -ne 0 ]; then
6+
echo "Error: Failed to dump BTF from vmlinux. Ensure bpftool is installed and has access to the kernel BTF."
7+
exit 1
8+
fi
9+
10+
bindgen vmlinux.h -o src/bindings.rs --use-core --allowlist-type 'sk_buff'
11+
12+
13+
if ! command -v bindgen &> /dev/null; then
14+
echo "bindgen not found, installing..."
15+
cargo install bindgen-cli
16+
fi
17+
218
cargo +nightly build -Z build-std=core --target bpfel-unknown-none --release --bin conntracker
19+
20+
rm -f vmlinux.h

core/src/components/conntracker/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
use which::which;
23

34
/// Building this crate has an undeclared dependency on the `bpf-linker` binary. This would be

core/src/components/conntracker/src/main.rs

Lines changed: 187 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*
1+
/* TODO: this part needs an update
22
*
33
* This file contains the code for the identity service
44
*
@@ -16,15 +16,16 @@
1616
#![allow(warnings)]
1717

1818
//mod skbuff;
19+
//mod veth_trace;
20+
mod bindings;
1921

2022
use bytemuck::{ Pod, Zeroable };
2123
use aya_ebpf::{
2224
bindings::{ TC_ACT_OK, TC_ACT_SHOT },
23-
macros::{ classifier, map, kprobe, tracepoint },
24-
maps::PerfEventArray,
25-
maps::LruPerCpuHashMap,
26-
programs::{ TcContext, TracePointContext },
27-
helpers::{ bpf_probe_read_kernel, bpf_ktime_get_ns },
25+
helpers::{ bpf_ktime_get_ns, bpf_probe_read_kernel, bpf_probe_read_kernel_str_bytes },
26+
macros::{ classifier, kprobe, map, tracepoint },
27+
maps::{ LruPerCpuHashMap, PerfEventArray },
28+
programs::{ ProbeContext, TcContext, TracePointContext },
2829
};
2930
use aya_ebpf::EbpfContext;
3031
//use crate::skbuff::{ sock, sock_common };
@@ -40,6 +41,8 @@ use network_types::{
4041
udp::UdpHdr,
4142
};
4243
use core::ptr::addr_of;
44+
45+
use crate::bindings::net_device;
4346
/*
4447
* ETHERNET TYPE II FRAME:
4548
* Reference: https://it.wikipedia.org/wiki/Frame_Ethernet
@@ -109,6 +112,7 @@ pub struct ConnArray {
109112

110113
#[map(name = "EventsMap")]
111114
static mut EVENTS: PerfEventArray<PacketLog> = PerfEventArray::new(0);
115+
//TODO: ConnectionMap needs a rework after implementing issue #105
112116
#[map(name = "ConnectionMap")]
113117
pub static mut ACTIVE_CONNECTIONS: LruPerCpuHashMap<
114118
u16,
@@ -121,6 +125,18 @@ pub static mut CONNTRACKER: LruPerCpuHashMap<ConnArray, u8> = LruPerCpuHashMap::
121125
0
122126
);
123127

128+
#[repr(C)]
129+
#[derive(Clone, Copy, Zeroable, Debug)]
130+
struct VethLog {
131+
name: [u8; 16],
132+
state: u64, //state var type: long unsigned int
133+
dev_addr: [u32; 8],
134+
event_type: u8, //i choose 1 for veth creation or 2 for veth destruction
135+
}
136+
137+
#[map(name = "veth_identity_map")]
138+
pub static mut VETH_CREATION_EVENTS: PerfEventArray<VethLog> = PerfEventArray::new(0);
139+
124140
const IPV4_ETHERTYPE: u16 = 0x0800;
125141

126142
//IPV4 STACK
@@ -148,19 +164,177 @@ const AF_INET6: u16 = 10; //ipv6
148164
const IPPROTO_UDP: u8 = 17;
149165
const IPPROTO_TCP: u8 = 6;
150166

151-
//TODO: add kprobe tracing for process ID
152-
//kprobe docs: https://docs.kernel.org/trace/kprobes.html
153-
154167
/* constants */
168+
//FIXME: this will be deprecated after solving issue #105
155169
const HOST_NETNS_INUM: u32 = 4026531993;
156170
const KUBE_POD_CIDR: u32 = 0x0af40000; // 10.244.0.0/16
157-
158171
/* Helper Functions */
159172
#[inline]
160173
unsafe fn is_kube_internal(ip: u32) -> bool {
161174
(ip & 0xffff0000) == KUBE_POD_CIDR
162175
}
163176

177+
#[kprobe]
178+
pub fn veth_creation_trace(ctx: ProbeContext) -> u32 {
179+
match try_veth_creation_trace(ctx) {
180+
Ok(ret_val) => ret_val,
181+
Err(ret_val) => ret_val.try_into().unwrap_or(1),
182+
}
183+
}
184+
#[kprobe]
185+
pub fn veth_deletion_trace(ctx: ProbeContext) -> u32 {
186+
match try_veth_deletion_trace(ctx) {
187+
Ok(ret_val) => ret_val,
188+
Err(ret_val) => ret_val.try_into().unwrap_or(1),
189+
}
190+
}
191+
192+
193+
pub fn try_veth_creation_trace(ctx: ProbeContext) -> Result<u32, i64> {
194+
let net_device_pointer: *const net_device = ctx.arg(0).ok_or(1i64)?;
195+
196+
// first control: i'm, verifying that the pointer is not null
197+
if net_device_pointer.is_null() {
198+
return Err(1);
199+
}
200+
201+
let name_field_offset = 304; // reading the name field offset
202+
//pahole commands:
203+
//syntax pahole -C <struct name>
204+
// pahole -C net_device | grep name
205+
206+
let dev_addr_offset = 1080;
207+
let state_offset = 168;
208+
209+
let name_pointer = unsafe { (net_device_pointer as *const u8).add(name_field_offset) };
210+
let dev_addr_pointer = unsafe { (net_device_pointer as *const u8).add(dev_addr_offset) };
211+
let state_pointer = unsafe { (net_device_pointer as *const u8).add(state_offset) };
212+
213+
let mut name_buf = [0u8; 16];
214+
let mut dev_addr_buf = [0u32; 8];
215+
216+
let name_array_ptr = name_pointer as *const [u8; 16];
217+
let dev_addr_ptr_array = dev_addr_pointer as *const [u32; 8];
218+
219+
let name_array = unsafe {
220+
match bpf_probe_read_kernel(name_array_ptr) {
221+
Ok(arr) => arr,
222+
Err(ret) => {
223+
return Err(ret);
224+
}
225+
}
226+
};
227+
228+
let state=unsafe {
229+
match bpf_probe_read_kernel(state_pointer) {
230+
Ok(s)=>s,
231+
Err(ret)=>{
232+
return Err(ret);
233+
}
234+
}
235+
};
236+
237+
let dev_addr_array = unsafe {
238+
match bpf_probe_read_kernel(dev_addr_ptr_array) {
239+
Ok(arr) => arr,
240+
Err(ret) => {
241+
return Err(ret);
242+
}
243+
}
244+
};
245+
246+
name_buf.copy_from_slice(&name_array);
247+
dev_addr_buf.copy_from_slice(&dev_addr_array);
248+
249+
let veth_data = VethLog {
250+
name: name_buf,
251+
state: state.into(),
252+
dev_addr: dev_addr_buf,
253+
event_type: 1
254+
};
255+
256+
//send the data to the userspace
257+
unsafe {
258+
VETH_CREATION_EVENTS.output(&ctx, &veth_data, 0);
259+
}
260+
261+
Ok(0)
262+
}
263+
264+
pub fn try_veth_deletion_trace(ctx: ProbeContext) -> Result<u32, i64> {
265+
let net_device_pointer: *const net_device = ctx.arg(0).ok_or(1i64)?;
266+
267+
// first control: i'm, verifying that the pointer is not null
268+
if net_device_pointer.is_null() {
269+
return Err(1);
270+
}
271+
272+
let name_field_offset = 304; // reading the name field offset
273+
//pahole commands:
274+
//syntax pahole -C <struct name>
275+
// pahole -C net_device | grep name
276+
277+
let dev_addr_offset = 1080;
278+
let state_offset = 168;
279+
280+
let name_pointer = unsafe { (net_device_pointer as *const u8).add(name_field_offset) };
281+
let dev_addr_pointer = unsafe { (net_device_pointer as *const u8).add(dev_addr_offset) };
282+
let state_pointer = unsafe { (net_device_pointer as *const u8).add(state_offset) };
283+
284+
let mut name_buf = [0u8; 16];
285+
let mut dev_addr_buf = [0u32; 8];
286+
287+
let name_array_ptr = name_pointer as *const [u8; 16];
288+
let dev_addr_ptr_array = dev_addr_pointer as *const [u32; 8];
289+
290+
let name_array = unsafe {
291+
match bpf_probe_read_kernel(name_array_ptr) {
292+
Ok(arr) => arr,
293+
Err(ret) => {
294+
return Err(ret);
295+
}
296+
}
297+
};
298+
299+
let state=unsafe {
300+
match bpf_probe_read_kernel(state_pointer) {
301+
Ok(s)=>s,
302+
Err(ret)=>{
303+
return Err(ret);
304+
}
305+
}
306+
};
307+
308+
let dev_addr_array = unsafe {
309+
match bpf_probe_read_kernel(dev_addr_ptr_array) {
310+
Ok(arr) => arr,
311+
Err(ret) => {
312+
return Err(ret);
313+
}
314+
}
315+
};
316+
317+
name_buf.copy_from_slice(&name_array);
318+
dev_addr_buf.copy_from_slice(&dev_addr_array);
319+
320+
let veth_data = VethLog {
321+
name: name_buf,
322+
state: state.into(),
323+
dev_addr: dev_addr_buf,
324+
event_type: 2
325+
};
326+
327+
//send the data to the userspace
328+
unsafe {
329+
VETH_CREATION_EVENTS.output(&ctx, &veth_data, 0);
330+
}
331+
332+
Ok(0)
333+
}
334+
335+
336+
337+
164338
#[classifier]
165339
pub fn identity_classifier(ctx: TcContext) -> i32 {
166340
match try_identity_classifier(ctx) {
@@ -200,9 +374,9 @@ fn try_identity_classifier(ctx: TcContext) -> Result<(), i64> {
200374

201375
//not logging internal communication packets
202376
//TODO: do not log internal communications such as minikube dashboard packets or kubectl api packets
203-
//FIXME: this part is not working properly because the ip associated in the k8s environment constantly changes every restart
377+
//FIXME: this part is not working properly because the ip associated in the k8s environment constantly changes every restart
204378
let ip_to_block = u32::from_be_bytes([90, 120, 244, 10]); // kubernetes-dashboard internal ip
205-
let ip_to_block_2 = u32::from_be_bytes([87, 120, 244, 10]); // cert manager internal ip
379+
let ip_to_block_2 = u32::from_be_bytes([87, 120, 244, 10]); // cert manager internal ip
206380
let ip_to_block_3 = u32::from_be_bytes([89, 120, 244, 10]); // kube-system internal ip
207381
let ip_to_block_4 = u32::from_be_bytes([88, 120, 244, 10]); // other kuber-system internal ip
208382

@@ -262,4 +436,4 @@ fn try_identity_classifier(ctx: TcContext) -> Result<(), i64> {
262436
fn panic(_info: &core::panic::PanicInfo) -> ! {
263437
loop {
264438
}
265-
}
439+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod bindings;

0 commit comments

Comments
 (0)