Skip to content

Commit 1a6bdaf

Browse files
committed
eguard: dns lpm match fix
1 parent efa1520 commit 1a6bdaf

File tree

9 files changed

+8157
-8172
lines changed

9 files changed

+8157
-8172
lines changed

plugins/eguard/config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ dns:
2727
- name: "eguard_egress_test_dns_1"
2828
action: DENY
2929
domain: "*.baidu.com"
30+
- name: "eguard_egress_test_dns_2"
31+
action: DENY
32+
domain: "*.loooooooooooooooooooooooooooooooooooog.com"
3033
file:
3134
- name: "file_test_1"
3235
action: DENY

plugins/eguard/src/bpf/eguard.skel.rs

Lines changed: 8082 additions & 8042 deletions
Large diffs are not rendered by default.

plugins/eguard/src/bpf/rules/l7_acl.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
#include "common/general.h"
88
#include "vmlinux.h"
99

10-
#define DNS_OFFSET (sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr))
11-
#define TYPE_DNS 3201
12-
#define MAX_DNS_NAME 255
10+
#define TYPE_DNS 3201
11+
#define DNS_OFFSET (sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr))
12+
#define DNS_MAX_LEN 256
13+
#define DNS_MAX_PRELEN (DNS_MAX_LEN) * 8
1314

1415
// The header contains the following fields:
1516
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
@@ -38,7 +39,7 @@ struct dnshdr _dnshdr = {0};
3839
// DNS ACL structs
3940
struct dns_policy_key {
4041
__u32 prefixlen;
41-
char domain[255];
42+
char domain[DNS_MAX_LEN];
4243
};
4344

4445
struct dns_policy_value {
@@ -58,8 +59,6 @@ struct {
5859

5960
#define SIZE_DNSHDR sizeof(struct dnshdr)
6061
#define SIZE_CONTEXT sizeof(net_context_t)
61-
#define DNS_MAX_LEN 255
62-
#define DNS_MAX_READ_LEN 256
6362
#define MID_WAY 8192
6463

6564
static __always_inline int tc_context_fill(net_packet_t pkt);
@@ -84,7 +83,7 @@ static __always_inline int l7_acl_rule(net_packet_t pkt, struct __sk_buff *skb)
8483

8584
// trim key
8685
struct dns_policy_key key = {0};
87-
key.prefixlen = 255;
86+
key.prefixlen = DNS_MAX_PRELEN;
8887

8988
bpf_skb_load_bytes(skb, DNS_OFFSET, (void *)&pkt.buf_p->buf[SIZE_CONTEXT], SIZE_DNSHDR);
9089
int offset = load_dns(pkt, &key, skb);

plugins/eguard/src/config/parser/dns.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,19 @@ pub struct DnsPolicy {
1616
impl CfgTrait for DnsPolicy {
1717
fn to_bytes(&self) -> Result<(Vec<u8>, Vec<u8>)> {
1818
let mut key = eguard_bss_types::dns_policy_key::default();
19+
key.prefixlen = 256;
1920
let mut value = eguard_bss_types::dns_policy_value::default();
2021
let mut domain = self.domain.clone();
21-
if domain.len() == 0 || domain.len() > 255 {
22+
if domain.len() == 0 || domain.len() > 256 {
2223
bail!("domain length error: {}", domain.len());
2324
}
24-
25-
if domain.contains('*') {
25+
if domain.starts_with('*') {
2626
domain.remove(0);
27-
key.prefixlen = domain.len() as u32;
28-
} else {
29-
key.prefixlen = 255;
27+
key.prefixlen = (domain.len() * 8) as u32;
3028
}
31-
3229
let domain_bytes = domain.as_bytes();
33-
let key_domain: [i8; 255] = {
34-
let mut arr = [0; 255];
30+
let key_domain: [i8; 256] = {
31+
let mut arr = [0; 256];
3532
for (i, &byte) in domain_bytes.iter().enumerate() {
3633
arr[domain.len() - i - 1] = byte as i8;
3734
}
@@ -43,7 +40,7 @@ impl CfgTrait for DnsPolicy {
4340
Action::LOG => 1,
4441
};
4542

46-
// flush to the map
43+
// convert into bytes
4744
let key = unsafe { plain::as_bytes(&key) }.to_vec();
4845
let value = unsafe { plain::as_bytes(&value) }.to_vec();
4946
Ok((key, value))

plugins/eguard/src/event/dns.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<'a> BpfProgram for DnsEvent {
5656
Ok(())
5757
}
5858

59-
fn detech(&mut self, _skel: &mut EguardSkel) -> Result<()> {
59+
fn detach(&mut self, _skel: &mut EguardSkel) -> Result<()> {
6060
self.status.store(false, Ordering::SeqCst);
6161
Ok(())
6262
}

plugins/eguard/src/event/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ pub trait BpfProgram: Sync {
2323
/// attach bpf binary
2424
fn attach(&mut self, skel: &mut EguardSkel) -> Result<()>;
2525

26-
/// detech the binary, wrapper the destory method inside if it is needed
27-
fn detech(&mut self, skel: &mut EguardSkel) -> Result<()>;
26+
/// detach the binary, wrapper the destory method inside if it is needed
27+
fn detach(&mut self, skel: &mut EguardSkel) -> Result<()>;
2828

2929
/// status of the bpf program
3030
fn status(&self) -> bool;

plugins/eguard/src/event/tc.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,16 @@ impl<'a> BpfProgram for TcEvent {
101101
Ok(())
102102
}
103103

104-
/// actually, it is destory
105-
fn detech(&mut self, skel: &mut EguardSkel) -> Result<()> {
106-
let mut destroy_all = libbpf_rs::TcHook::new(skel.progs().hades_egress().as_fd());
107-
destroy_all
108-
.ifindex(self.if_idx)
109-
.attach_point(TC_EGRESS | TC_INGRESS);
110-
destroy_all.destroy()?;
104+
/// actually, it is destroy
105+
fn detach(&mut self, _skel: &mut EguardSkel) -> Result<()> {
106+
if let Some(mut egress_hook) = self.egress_hook {
107+
egress_hook.detach()?;
108+
egress_hook.destroy()?;
109+
}
110+
if let Some(mut ingress_hook) = self.ingress_hook {
111+
ingress_hook.detach()?;
112+
ingress_hook.destroy()?;
113+
}
111114
Ok(())
112115
}
113116

plugins/eguard/src/main.rs

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::path::PathBuf;
1010
use std::sync::atomic::{AtomicBool, Ordering};
1111
use std::sync::{Arc, Mutex};
1212
use std::thread;
13-
use std::time::Duration;
13+
use tokio::time::{timeout, Duration};
1414

1515
use crate::config::config::Config as BpfConfig;
1616
use crate::event::dns::DnsEvent;
@@ -23,11 +23,6 @@ mod manager;
2323
pub const TYPE_TC: u32 = 3200;
2424
pub const TYPE_DNS: u32 = 3201;
2525

26-
use std::alloc::System;
27-
28-
#[global_allocator]
29-
static GLOBAL: System = System;
30-
3126
fn main() -> Result<()> {
3227
let mut client = Client::new(false);
3328
set_boxed_logger(Box::new(Logger::new(Config {
@@ -47,6 +42,7 @@ fn main() -> Result<()> {
4742
let control_s = Arc::new(AtomicBool::new(false));
4843
let control_l = control_s.clone();
4944
let control_c = control_s.clone();
45+
let control_r = control_s.clone();
5046
ctrlc::set_handler(move || {
5147
control_c.store(true, Ordering::SeqCst);
5248
})?;
@@ -77,37 +73,8 @@ fn main() -> Result<()> {
7773
}
7874

7975
info!("init bpf program successfully");
80-
// task_receive thread
8176
let mut client_c = client.clone();
82-
let timeout = Duration::from_millis(500);
83-
let _ = thread::Builder::new()
84-
.name("task_receive".to_owned())
85-
.spawn(move || loop {
86-
match client_c.receive() {
87-
Ok(task) => {
88-
let config = match serde_json::from_str::<BpfConfig>(task.get_data()) {
89-
Ok(config) => config,
90-
Err(e) => {
91-
error!("parse task failed: {}", e);
92-
continue;
93-
}
94-
};
95-
96-
if let Err(e) = mgr_c.lock().unwrap().flush_config(config) {
97-
error!("flush task failed: {}", e);
98-
continue;
99-
}
10077

101-
info!("task parse success")
102-
}
103-
Err(e) => {
104-
error!("when receiving task,an error occurred:{}", e);
105-
control_s.store(true, Ordering::Relaxed);
106-
return;
107-
}
108-
}
109-
});
110-
info!("task receive handler is running");
11178
// record_send thread
11279
let record_send = thread::Builder::new()
11380
.name("record_send".to_string())
@@ -116,7 +83,7 @@ fn main() -> Result<()> {
11683
break;
11784
}
11885

119-
let rec = rx.recv_timeout(timeout);
86+
let rec = rx.recv_timeout(std::time::Duration::from_millis(100));
12087
match rec {
12188
Ok(rec) => {
12289
if let Err(err) = client.send_record(&rec) {
@@ -130,6 +97,43 @@ fn main() -> Result<()> {
13097
})
13198
.unwrap();
13299
let _ = record_send.join();
100+
// task_receive thread
101+
let rt = tokio::runtime::Runtime::new()?;
102+
rt.block_on(async {
103+
info!("task receive handler is running");
104+
loop {
105+
if control_r.load(Ordering::SeqCst) {
106+
break;
107+
}
108+
// receive data
109+
let task = match timeout(Duration::from_millis(1000), client_c.receive_async()).await {
110+
Ok(task) => match task {
111+
Ok(task) => task,
112+
Err(_) => {
113+
break;
114+
}
115+
},
116+
Err(_) => {
117+
continue;
118+
}
119+
};
120+
// exit
121+
let config = match serde_json::from_str::<BpfConfig>(task.get_data()) {
122+
Ok(config) => config,
123+
Err(e) => {
124+
error!("parse task failed: {}", e);
125+
continue;
126+
}
127+
};
128+
129+
if let Err(e) = mgr_c.lock().unwrap().flush_config(config) {
130+
error!("flush task failed: {}", e);
131+
continue;
132+
}
133+
134+
info!("task parse success");
135+
}
136+
});
133137
info!("plugin will exit");
134138
Ok(())
135139
}

plugins/eguard/src/manager/manager.rs

Lines changed: 6 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod eguard_skel {
33
}
44
use crate::{
55
config::config::Config,
6-
event::{eguard_skel::eguard_bss_types, event::TX, BpfProgram},
6+
event::{eguard_skel::eguard_bss_types, BpfProgram},
77
TYPE_TC,
88
};
99
use anyhow::{anyhow, bail, Ok, Result};
@@ -26,8 +26,6 @@ use std::{
2626

2727
use crate::event::eguard_skel::{EguardSkel, EguardSkelBuilder};
2828
use byteorder::{LittleEndian, ReadBytesExt};
29-
use coarsetime::Clock;
30-
use sdk::{Payload, Record};
3129
use std::io::Cursor;
3230

3331
lazy_static! {
@@ -67,21 +65,14 @@ impl Bpfmanager<'_> {
6765
// load the skel
6866
let mut skel = EguardSkelBuilder::default().open()?.load()?;
6967

70-
let network_perf = PerfBufferBuilder::new(skel.maps_mut().events())
68+
let perf_buffer = PerfBufferBuilder::new(skel.maps_mut().events())
7169
.sample_cb(Bpfmanager::handle_tc_event)
7270
.lost_cb(Bpfmanager::handle_tc_lost_events)
7371
.build()?;
74-
let exec_perf = PerfBufferBuilder::new(skel.maps_mut().exec_events())
75-
.sample_cb(Bpfmanager::handle_exec_event)
76-
.lost_cb(Bpfmanager::handle_exec_lost_events)
77-
.build()?;
7872

7973
let thread_handle = spawn(move || {
8074
while running.load(Ordering::SeqCst) {
81-
if let Err(_) = network_perf.poll(Duration::from_millis(100)) {
82-
break;
83-
}
84-
if let Err(_) = exec_perf.poll(Duration::from_millis(100)) {
75+
if let Err(_) = perf_buffer.poll(Duration::from_millis(100)) {
8576
break;
8677
}
8778
}
@@ -152,61 +143,17 @@ impl Bpfmanager<'_> {
152143
fn handle_tc_lost_events(cpu: i32, count: u64) {
153144
error!("lost tc {} events on CPU {}", count, cpu);
154145
}
155-
156-
/// working on this
157-
fn handle_exec_event(_cpu: i32, data: &[u8]) {
158-
// parse the context
159-
let mut context = eguard_bss_types::data_context::default();
160-
plain::copy_from_bytes(&mut context, data).expect("context decode failed");
161-
let mut map = HashMap::new();
162-
map.insert("cgroupid".to_string(), context.cgroup_id.to_string());
163-
map.insert("pns".to_string(), context.pns.to_string());
164-
map.insert("pid".to_string(), context.pid.to_string());
165-
map.insert("tid".to_string(), context.tid.to_string());
166-
map.insert("uid".to_string(), context.uid.to_string());
167-
map.insert("gid".to_string(), context.gid.to_string());
168-
map.insert("ppid".to_string(), context.ppid.to_string());
169-
map.insert("pgid".to_string(), context.pgid.to_string());
170-
map.insert("sessionid".to_string(), context.sessionid.to_string());
171-
let comm: &[u8] = unsafe { std::mem::transmute(&context.comm[..]) };
172-
map.insert("comm".to_string(), trim_null_chars(comm));
173-
let pcomm: &[u8] = unsafe { std::mem::transmute(&context.pcomm[..]) };
174-
map.insert("pcomm".to_string(), trim_null_chars(pcomm));
175-
let nodename: &[u8] = unsafe { std::mem::transmute(&context.nodename[..]) };
176-
map.insert("nodename".to_string(), trim_null_chars(nodename));
177-
178-
let mut rec = Record::new();
179-
let mut pld = Payload::new();
180-
pld.set_fields(map);
181-
rec.set_timestamp(Clock::now_since_epoch().as_secs() as i64);
182-
rec.set_data(pld);
183-
rec.data_type = context.dt as i32;
184-
let lock = TX
185-
.lock()
186-
.map_err(|e| error!("unable to acquire notification send channel: {}", e));
187-
match &mut *lock.unwrap() {
188-
Some(sender) => {
189-
if let Err(err) = sender.send(rec) {
190-
error!("send failed: {}", err);
191-
return;
192-
}
193-
}
194-
None => return,
195-
}
196-
}
197-
198-
fn handle_exec_lost_events(cpu: i32, count: u64) {
199-
error!("lost exec_events {} events on CPU {}", count, cpu);
200-
}
201146
}
202147

203148
impl Drop for Bpfmanager<'_> {
204149
fn drop(&mut self) {
205150
let events = &mut *EVENTS.write().unwrap();
206151
for (key, e) in events.iter_mut() {
207152
if let Some(skel) = self.skel.as_mut() {
208-
if let Err(err) = e.detech(skel) {
153+
if let Err(err) = e.detach(skel) {
209154
error!("drop event {} failed: {}", key, err);
155+
} else {
156+
info!("drop event {} success", key);
210157
}
211158
}
212159
}
@@ -215,18 +162,10 @@ impl Drop for Bpfmanager<'_> {
215162
if let Some(thread) = self.thread_handle.take() {
216163
thread.join().ok();
217164
}
218-
219165
debug!("has dropped bpfmanager from thread");
220166
}
221167
}
222168

223-
fn trim_null_chars(data: &[u8]) -> String {
224-
String::from_utf8_lossy(data)
225-
.to_string()
226-
.trim_end_matches('\0')
227-
.to_string()
228-
}
229-
230169
#[cfg(test)]
231170
mod tests {
232171
use super::*;

0 commit comments

Comments
 (0)