Skip to content

feat: integrate community-id #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3dd8ec9
doc(ebpf): removed useless comment
qjerome Sep 20, 2024
181db09
add(common,ebpf): IpPort::src_from_sock_common
qjerome Sep 20, 2024
1908f17
chg(ebpf): move code blocks without logic change in send_data.rs
qjerome Sep 20, 2024
9699f5f
fix(ebpf): fix alloc init in send_data.rs
qjerome Sep 23, 2024
2fae031
refactor(common): net::IpPort -> net::SockAddr
qjerome Sep 24, 2024
43c47d3
feat(main): community-id integrated in send_data event
qjerome Sep 24, 2024
5e44dc3
chg(main): use SockAddr in send_data event processing
qjerome Sep 25, 2024
63da1fa
feat: community-id in connect event
qjerome Sep 25, 2024
97472cc
doc(common): removed useless comment
qjerome Sep 25, 2024
353deec
feat: community-id in dns_query event
qjerome Sep 25, 2024
67cf5a3
add(common): kernel agnostic accessor to sock.sk_protocol
qjerome Sep 25, 2024
7f8e594
fix(all): use sk_protocol instead of sk_type to compute community-id
qjerome Sep 25, 2024
926aa3a
add(kunai): helper function to convert u16 IpProto to String
qjerome Sep 25, 2024
914caaf
feat: add protocol information in connect event
qjerome Sep 25, 2024
268fb6f
feat: add proto to send_data event
qjerome Sep 25, 2024
04ea797
chg: use SocketInfo to carry protocol information in connect event
qjerome Sep 26, 2024
af9c6a1
chg: use SocketInfo to carry protocol information in send_data event
qjerome Sep 26, 2024
39f1fbd
refactor(ebpf): renamed field in eBPF connect event
qjerome Sep 26, 2024
dd113fd
chg: use SocketInfo to carry protocol information in dns_query event
qjerome Sep 26, 2024
89b7c87
rm(user): remove helper utils::ip_proto_to_string
qjerome Sep 26, 2024
c80866e
chg(ebpf): remove duplicated BPF CORE calls in send_data probe
qjerome Sep 26, 2024
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
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions kunai-common/src/bpf_events/events/connect.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::{bpf_events::Event, net::IpPort};
use crate::{
bpf_events::Event,
net::{SockAddr, SocketInfo},
};

pub type ConnectEvent = Event<ConnectData>;

#[repr(C)]
pub struct ConnectData {
pub family: u32,
pub ip_port: IpPort,
pub socket: SocketInfo,
pub src: SockAddr,
pub dst: SockAddr,
pub connected: bool,
}
15 changes: 7 additions & 8 deletions kunai-common/src/bpf_events/events/dns_query.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::bpf_events::Event;
use crate::macros::not_bpf_target_code;
use crate::{buffer::Buffer, net::IpPort};
use crate::net::{IpProto, SocketInfo};
use crate::{buffer::Buffer, net::SockAddr};

pub const DNS_MAX_PACKET_SIZE: usize = 2048;

Expand All @@ -15,8 +16,9 @@ pub enum DnsError {
#[repr(C)]
#[derive(Debug, Clone)]
pub struct DnsQueryData {
pub ip_port: IpPort,
pub proto: u16,
pub socket: SocketInfo,
pub src: SockAddr,
pub dst: SockAddr,
pub data: Buffer<DNS_MAX_PACKET_SIZE>,
pub tcp_header: bool,
pub error: DnsError,
Expand All @@ -28,14 +30,11 @@ impl DnsQueryData {
pub fn header_is_null(&self) -> bool {
let h = &self.packet_data()[..12];
h.iter().filter(|&&b| b == 0).count() == 12
/*let part1: u64 = u64::from_be_bytes([h[7], h[6], h[5], h[4], h[3], h[2], h[1], h[0]]);
let part2: u32 = u32::from_be_bytes([h[11], h[10], h[9], h[8]]);
part2 == 0 && part1 == 0*/
}

pub fn packet_data(&self) -> &[u8] {
// this is a TCP connection SOCK_STREAM == 1
if self.proto == 1 && self.tcp_header && self.data.len() >= 14 {
// this is a TCP connection
if self.socket.proto == IpProto::TCP as u16 && self.tcp_header && self.data.len() >= 14 {
// there are two bytes at front encoding the size of the packet
return &self.data.as_slice()[2..];
}
Expand Down
11 changes: 8 additions & 3 deletions kunai-common/src/bpf_events/events/send_entropy.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::{bpf_events::Event, macros::not_bpf_target_code};

use crate::net::IpPort;
use crate::net::{SockAddr, SocketInfo};

pub const ENCRYPT_DATA_MAX_BUFFER_SIZE: usize = 4096;

#[repr(C)]
pub struct SendEntropyData {
pub ip_port: IpPort,
pub socket: SocketInfo,
pub src: SockAddr,
pub dst: SockAddr,
pub freq: [u32; 256],
pub freq_sum: u32,
pub real_data_size: u64,
Expand All @@ -28,8 +30,10 @@ impl SendEntropyEvent {
self.data.freq_sum += 1;
}
}
}

not_bpf_target_code! {
not_bpf_target_code! {
impl SendEntropyEvent {
// we cannot do complicated operations of f32 in eBPF
#[inline]
pub fn shannon_entropy(&self) -> f32{
Expand All @@ -46,4 +50,5 @@ impl SendEntropyEvent {
entropy
}
}

}
45 changes: 34 additions & 11 deletions kunai-common/src/co_re/c/shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,18 @@ struct inode
unsigned long i_ino;
struct super_block *i_sb;
loff_t i_size;
union {
union
{
struct timespec64 i_atime;
struct timespec64 __i_atime;
};
union {
union
{
struct timespec64 i_mtime;
struct timespec64 __i_mtime;
};
union {
union
{
struct timespec64 i_ctime;
struct timespec64 __i_ctime;
};
Expand Down Expand Up @@ -379,7 +382,8 @@ struct task_struct
pid_t pid;
__u64 start_time;
// attempt to make compatible with older kernels
union {
union
{
__u64 start_boottime;
__u64 real_start_time;
};
Expand Down Expand Up @@ -519,7 +523,8 @@ typedef __u32 __portpair;

struct in6_addr
{
union {
union
{
__u8 u6_addr8[16];
__be16 u6_addr16[8];
__be32 u6_addr32[4];
Expand Down Expand Up @@ -570,11 +575,13 @@ SHIM_REF(sockaddr_in6, sin6_addr);

struct sock_common
{
union {
union
{
__addrpair skc_addrpair;
};

union {
union
{
__portpair skc_portpair;
};

Expand Down Expand Up @@ -626,13 +633,26 @@ SHIM(sk_buff_head, qlen);
struct sock
{
struct sock_common __sk_common;
//__u16 sk_protocol;
__u8 sk_protocol;
// sk_type is always a u16, bitfield or not
__u16 sk_type;
struct sk_buff_head sk_receive_queue;
} __attribute__((preserve_access_index));

// BPF core trims any ___$SUFFIX and treat structure
// as if suffix is not there
// https://nakryiko.com/posts/bpf-core-reference-guide/#handling-incompatible-field-and-type-changes
struct sock___pre_5_6
{
// on kernel < 5.6 sk_protocol is a bitfield
__u8 sk_protocol;
} __attribute__((preserve_access_index));

SHIM_BITFIELD(sock___pre_5_6, sk_protocol);

SHIM_REF(sock, __sk_common);
SHIM_BITFIELD(sock, sk_protocol);
SHIM(sock, sk_protocol);
SHIM_BITFIELD(sock, sk_type);
SHIM_REF(sock, sk_receive_queue)

Expand Down Expand Up @@ -690,19 +710,22 @@ SHIM(bio_vec, bv_offset);

struct iov_iter
{
union {
union
{
u8 iter_type;
unsigned int type;
};
size_t count;
union {
union
{
struct iovec *iov;
struct iovec *__iov;
void *ubuf;
struct bio_vec *bvec;
};

union {
union
{
unsigned long nr_segs;
};
} __attribute__((preserve_access_index));
Expand Down
21 changes: 20 additions & 1 deletion kunai-common/src/co_re/core_sock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,32 @@ impl socket {
rust_shim_kernel_impl!(pub, socket, sk, sock);
}

// this is used for older kernels < 5.6
// where sk_protocol is a bitfield
#[allow(non_camel_case_types)]
type sock___pre_5_6 = CoRe<gen::sock___pre_5_6>;

impl sock___pre_5_6 {
rust_shim_kernel_impl!(pub(self), sock___pre_5_6, sk_protocol, u8);
}

#[allow(non_camel_case_types)]
pub type sock = CoRe<gen::sock>;

impl sock {
rust_shim_kernel_impl!(pub, sk_common, sock, __sk_common, sock_common);
rust_shim_kernel_impl!(pub, sock, sk_type, u16);
rust_shim_kernel_impl!(pub, sock, sk_protocol, u8);
// for kernels >= 5.6
rust_shim_kernel_impl!(pub(self), _sk_protocol, sock, sk_protocol, u16);

// for any kernel
pub unsafe fn sk_protocol(&self) -> Option<u16> {
let os = sock___pre_5_6::from_ptr(self.as_ptr() as *const gen::sock___pre_5_6);
os.sk_protocol()
.map(u16::from)
.or_else(|| self._sk_protocol())
}

rust_shim_kernel_impl!(pub, sock, sk_receive_queue, sk_buff_head);
}

Expand Down
16 changes: 16 additions & 0 deletions kunai-common/src/co_re/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,19 @@ pub struct sock {
pub sk_type: __u16,
pub sk_receive_queue: sk_buff_head,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct sock___pre_5_6 {
pub sk_protocol: __u8,
}
extern "C" {
pub fn shim_sock___pre_5_6_sk_protocol(
sock___pre_5_6: *mut sock___pre_5_6,
) -> ::core::ffi::c_uchar;
}
extern "C" {
pub fn shim_sock___pre_5_6_sk_protocol_exists(sock___pre_5_6: *mut sock___pre_5_6) -> bool;
}
extern "C" {
pub fn shim_sock___sk_common(sock: *mut sock) -> *mut sock_common;
}
Expand All @@ -1491,6 +1504,9 @@ extern "C" {
extern "C" {
pub fn shim_sock_sk_protocol(sock: *mut sock) -> ::core::ffi::c_uchar;
}
extern "C" {
pub fn shim_sock_sk_protocol_user(sock: *mut sock) -> ::core::ffi::c_uchar;
}
extern "C" {
pub fn shim_sock_sk_protocol_exists(sock: *mut sock) -> bool;
}
Expand Down
60 changes: 55 additions & 5 deletions kunai-common/src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ pub enum IpType {

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct IpPort {
pub struct SockAddr {
pub ty: IpType,
data: [u32; 4],
port: u16,
}

impl Default for IpPort {
impl Default for SockAddr {
fn default() -> Self {
Self {
ty: IpType::V4,
Expand All @@ -70,17 +70,17 @@ impl Default for IpPort {
}
}

impl IpPort {
impl SockAddr {
pub fn new_v4_from_be(addr: u32, port: u16) -> Self {
IpPort {
SockAddr {
ty: IpType::V4,
data: [addr, 0, 0, 0],
port,
}
}

pub fn new_v6_from_be(addr: [u32; 4], port: u16) -> Self {
IpPort {
SockAddr {
ty: IpType::V6,
data: addr,
port,
Expand Down Expand Up @@ -200,13 +200,63 @@ impl SockType {
}
}

// IPPROTO_ macros defined in the Linux kernel
// even though some IPPROTO_ are u16 those can
// be casted to their u8 counterpart probably
// because in IP header the protocol is u8
// https://elixir.bootlin.com/linux/v6.11/source/include/uapi/linux/in.h#L29
// https://elixir.bootlin.com/linux/v6.11/source/include/uapi/linux/in6.h#L132
#[repr(u16)]
#[derive(StrEnum, Debug, PartialEq, PartialOrd)]
#[allow(non_camel_case_types)]
pub enum IpProto {
IP = 0, /* Dummy protocol for TCP */
ICMP = 1, /* Internet Control Message Protocol */
IGMP = 2, /* Internet Group Management Protocol */
IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
TCP = 6, /* Transmission Control Protocol */
EGP = 8, /* Exterior Gateway Protocol */
PUP = 12, /* PUP protocol */
UDP = 17, /* User Datagram Protocol */
IDP = 22, /* XNS IDP protocol */
TP = 29, /* SO Transport Protocol Class 4 */
DCCP = 33, /* Datagram Congestion Control Protocol */
IPV6 = 41, /* IPv6-in-IPv4 tunnelling */
RSVP = 46, /* RSVP Protocol */
GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */
ESP = 50, /* Encapsulation Security Payload protocol */
AH = 51, /* Authentication Header protocol */
MTP = 92, /* Multicast Transport Protocol */
BEETPH = 94, /* IP option pseudo header for BEET */
ENCAP = 98, /* Encapsulation Header */
PIM = 103, /* Protocol Independent Multicast */
COMP = 108, /* Compression Header Protocol */
L2TP = 115, /* Layer 2 Tunnelling Protocol */
SCTP = 132, /* Stream Control Transport Protocol */
UDPLITE = 136, /* UDP-Lite (RFC 3828) */
MPLS = 137, /* MPLS in IP (RFC 4023) */
ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation */
RAW = 255, /* Raw IP packets */
SMC = 256, /* Shared Memory Communications */
MPTCP = 262, /* Multipath TCP connection */
// IPv6 related
ROUTING = 43, /* IPv6 routing header */
FRAGMENT = 44, /* IPv6 fragmentation header */
ICMPV6 = 58, /* ICMPv6 */
NONE = 59, /* IPv6 no next header */
DSTOPTS = 60, /* IPv6 destination options */
MH = 135, /* IPv6 mobility header */
}

#[repr(C)]
#[derive(Default, Debug, Clone, Copy)]
pub struct SocketInfo {
/// Must be [SaFamily] value
pub domain: u16,
/// Must be [SockType] value
pub ty: u16,
/// Value of socket.sk_protocol
pub proto: u16,
}

impl SocketInfo {
Expand Down
Loading
Loading