diff options
Diffstat (limited to '')
-rw-r--r-- | src/audit.go | 84 | ||||
-rw-r--r-- | src/basefunc.go | 115 | ||||
-rw-r--r-- | src/deal.go | 97 | ||||
-rw-r--r-- | src/global.go | 10 | ||||
-rw-r--r-- | src/go.mod (renamed from go.mod) | 0 | ||||
-rw-r--r-- | src/go.sum (renamed from go.sum) | 0 | ||||
-rw-r--r-- | src/godo.go | 116 | ||||
-rw-r--r-- | src/organize.go | 124 | ||||
-rw-r--r-- | src/receive.go | 29 |
9 files changed, 575 insertions, 0 deletions
diff --git a/src/audit.go b/src/audit.go new file mode 100644 index 0000000..ed48691 --- /dev/null +++ b/src/audit.go | |||
@@ -0,0 +1,84 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io" | ||
6 | "log" | ||
7 | "os" | ||
8 | |||
9 | "github.com/elastic/go-libaudit/v2" | ||
10 | ) | ||
11 | |||
12 | func read() error { | ||
13 | // Write netlink response to a file for further analysis or for writing | ||
14 | // tests cases. | ||
15 | var diagWriter io.Writer | ||
16 | if *diag != "" { | ||
17 | f, err := os.OpenFile(*diag, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600) | ||
18 | if err != nil { | ||
19 | return err | ||
20 | } | ||
21 | defer f.Close() | ||
22 | diagWriter = f | ||
23 | } | ||
24 | |||
25 | log.Println("starting netlink client") | ||
26 | |||
27 | var err error | ||
28 | var client *libaudit.AuditClient | ||
29 | if *receiveOnly { | ||
30 | client, err = libaudit.NewMulticastAuditClient(diagWriter) | ||
31 | if err != nil { | ||
32 | return fmt.Errorf("failed to create receive-only audit client: %w", err) | ||
33 | } | ||
34 | defer client.Close() | ||
35 | } else { | ||
36 | client, err = libaudit.NewAuditClient(diagWriter) | ||
37 | if err != nil { | ||
38 | return fmt.Errorf("failed to create audit client: %w", err) | ||
39 | } | ||
40 | defer client.Close() | ||
41 | |||
42 | status, err := client.GetStatus() | ||
43 | if err != nil { | ||
44 | return fmt.Errorf("failed to get audit status: %w", err) | ||
45 | } | ||
46 | log.Printf("received audit status=%+v", status) | ||
47 | |||
48 | if status.Enabled == 0 { | ||
49 | log.Println("enabling auditing in the kernel") | ||
50 | if err = client.SetEnabled(true, libaudit.WaitForReply); err != nil { | ||
51 | return fmt.Errorf("failed to set enabled=true: %w", err) | ||
52 | } | ||
53 | } | ||
54 | |||
55 | if status.RateLimit != uint32(*rate) { | ||
56 | log.Printf("setting rate limit in kernel to %v", *rate) | ||
57 | if err = client.SetRateLimit(uint32(*rate), libaudit.NoWait); err != nil { | ||
58 | return fmt.Errorf("failed to set rate limit to unlimited: %w", err) | ||
59 | } | ||
60 | } | ||
61 | |||
62 | if status.BacklogLimit != uint32(*backlog) { | ||
63 | log.Printf("setting backlog limit in kernel to %v", *backlog) | ||
64 | if err = client.SetBacklogLimit(uint32(*backlog), libaudit.NoWait); err != nil { | ||
65 | return fmt.Errorf("failed to set backlog limit: %w", err) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | if status.Enabled != 2 && *immutable { | ||
70 | log.Printf("setting kernel settings as immutable") | ||
71 | if err = client.SetImmutable(libaudit.NoWait); err != nil { | ||
72 | return fmt.Errorf("failed to set kernel as immutable: %w", err) | ||
73 | } | ||
74 | } | ||
75 | |||
76 | log.Printf("sending message to kernel registering our PID (%v) as the audit daemon", os.Getpid()) | ||
77 | if err = client.SetPID(libaudit.NoWait); err != nil { | ||
78 | return fmt.Errorf("failed to set audit PID: %w", err) | ||
79 | } | ||
80 | } | ||
81 | |||
82 | coroutine(client) | ||
83 | return nil | ||
84 | } | ||
diff --git a/src/basefunc.go b/src/basefunc.go new file mode 100644 index 0000000..5fff3e8 --- /dev/null +++ b/src/basefunc.go | |||
@@ -0,0 +1,115 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "fmt" | ||
6 | "os" | ||
7 | "path/filepath" | ||
8 | "regexp" | ||
9 | "strconv" | ||
10 | "strings" | ||
11 | "time" | ||
12 | ) | ||
13 | |||
14 | func figureOutSyscalls() error { | ||
15 | NRRegex := regexp.MustCompile(`#define __NR_(.*?) (\d+)$`) | ||
16 | file, err := os.Open("/usr/include/asm/unistd_64.h") | ||
17 | if err != nil { | ||
18 | return err | ||
19 | } | ||
20 | defer file.Close() | ||
21 | |||
22 | scanner := bufio.NewScanner(file) | ||
23 | for scanner.Scan() { | ||
24 | line := scanner.Text() | ||
25 | if NRRegex.MatchString(line) { | ||
26 | match := NRRegex.FindStringSubmatch(line) | ||
27 | num, err := strconv.Atoi(match[2]) | ||
28 | if err != nil { | ||
29 | return err | ||
30 | } | ||
31 | syscallTable[num] = match[1] | ||
32 | } | ||
33 | } | ||
34 | return nil | ||
35 | } | ||
36 | |||
37 | func getPid() (int, error) { | ||
38 | // 指定要搜索的关键词 | ||
39 | keyword := "/usr/bin/containerd" | ||
40 | |||
41 | // 获取/proc目录下的所有子目录 | ||
42 | procDir, err := filepath.Glob("/proc/*") | ||
43 | if err != nil { | ||
44 | return 0, err | ||
45 | } | ||
46 | |||
47 | // 遍历子目录,查找包含关键词的进程 | ||
48 | for _, dir := range procDir { | ||
49 | pid, err := strconv.Atoi(filepath.Base(dir)) | ||
50 | if err != nil { | ||
51 | continue // 跳过非PID的目录 | ||
52 | } | ||
53 | |||
54 | // 检查进程是否包含关键词 | ||
55 | if containsKeyword(pid, keyword) { | ||
56 | return pid, nil | ||
57 | } | ||
58 | } | ||
59 | err = fmt.Errorf("Error: no containerd process found.") | ||
60 | return 0, err | ||
61 | } | ||
62 | |||
63 | func containsKeyword(pid int, keyword string) bool { | ||
64 | // 构造完整的进程命令路径 | ||
65 | cmdPath := fmt.Sprintf("/proc/%d/cmdline", pid) | ||
66 | |||
67 | // 打开文件 | ||
68 | file, err := os.Open(cmdPath) | ||
69 | if err != nil { | ||
70 | return false | ||
71 | } | ||
72 | defer file.Close() | ||
73 | |||
74 | // 读取文件内容 | ||
75 | scanner := bufio.NewScanner(file) | ||
76 | scanner.Split(bufio.ScanLines) | ||
77 | for scanner.Scan() { | ||
78 | line := scanner.Text() | ||
79 | if strings.Contains(line, keyword) { | ||
80 | return true | ||
81 | } | ||
82 | } | ||
83 | return false | ||
84 | } | ||
85 | |||
86 | func getTimeFromStr(timeStr string) (time.Time, error) { | ||
87 | timestampFloat, err := strconv.ParseFloat(timeStr, 64) | ||
88 | if err != nil { | ||
89 | return time.Unix(0, 0), err | ||
90 | } | ||
91 | secs := int64(timestampFloat) | ||
92 | nsecs := int64((timestampFloat - float64(secs)) * 1e9) | ||
93 | |||
94 | // 只精确到毫秒就够了 | ||
95 | t := time.Unix(secs, nsecs).Truncate(time.Millisecond) | ||
96 | return t, nil | ||
97 | } | ||
98 | |||
99 | func hexToAscii(hexString string) string { | ||
100 | bytes := []byte{} | ||
101 | for i := 0; i < len(hexString); i += 2 { | ||
102 | hexPair := hexString[i : i+2] | ||
103 | // 将十六进制数转换为十进制数 | ||
104 | decimal, err := strconv.ParseInt(hexPair, 16, 8) | ||
105 | if err != nil { | ||
106 | return "Invalid hex string" | ||
107 | } | ||
108 | char := byte(decimal) | ||
109 | bytes = append(bytes, char) | ||
110 | } | ||
111 | |||
112 | asciiString := strings.ReplaceAll(string(bytes), "\000", " ") | ||
113 | |||
114 | return asciiString | ||
115 | } | ||
diff --git a/src/deal.go b/src/deal.go new file mode 100644 index 0000000..fd9f788 --- /dev/null +++ b/src/deal.go | |||
@@ -0,0 +1,97 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "time" | ||
6 | ) | ||
7 | |||
8 | func deal() { | ||
9 | defer wg.Done() | ||
10 | var cooked Event | ||
11 | var ok bool | ||
12 | for { | ||
13 | cooked, ok = <-cookedChan | ||
14 | if !ok { | ||
15 | break | ||
16 | } | ||
17 | // type Event struct { | ||
18 | // timestamp time.Time | ||
19 | // pid, ppid int | ||
20 | // syscall int | ||
21 | // argc int | ||
22 | // args []string | ||
23 | // cwd string | ||
24 | // } | ||
25 | // type process struct { | ||
26 | // timestamp time.Time | ||
27 | // pid, ppid int | ||
28 | // argv []string | ||
29 | // cwd string | ||
30 | // rootfs string | ||
31 | // children []int | ||
32 | // } | ||
33 | switch syscallTable[cooked.syscall] { | ||
34 | case "fork", "vfork", "clone": | ||
35 | ppid := cooked.ppid | ||
36 | pid := cooked.pid | ||
37 | parent, ok := pids.Load(ppid) | ||
38 | if !ok { | ||
39 | break | ||
40 | } | ||
41 | parent.(*process).children = append(parent.(*process).children, pid) | ||
42 | pids.Store(pid, &process{ | ||
43 | timestamp: cooked.timestamp, | ||
44 | pid: cooked.pid, | ||
45 | ppid: cooked.ppid, | ||
46 | argv: cooked.argv, | ||
47 | cwd: cooked.cwd, | ||
48 | children: make([]int, 0), | ||
49 | }) | ||
50 | fmt.Printf("%v syscall=%d, ppid=%d, pid=%d, cwd=\"%s\", argc=%d, ", cooked.timestamp, cooked.syscall, cooked.ppid, cooked.pid, cooked.cwd, cooked.argc) | ||
51 | for i := 0; i < cooked.argc; i++ { | ||
52 | fmt.Printf("arg[%d]=\"%s\", ", i, cooked.argv[i]) | ||
53 | } | ||
54 | fmt.Printf("\n") | ||
55 | case "exit", "exit_group": | ||
56 | _, ok := pids.Load(cooked.pid) | ||
57 | if !ok { | ||
58 | break | ||
59 | } | ||
60 | go deletePid(cooked) | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | func deletePid(cooked Event) { | ||
66 | time.Sleep(1 * time.Second) | ||
67 | Process, ok := pids.Load(cooked.pid) | ||
68 | if !ok { | ||
69 | return | ||
70 | } | ||
71 | pProcess := Process.(*process) | ||
72 | |||
73 | // 先从爹那里注销户籍 | ||
74 | parent, ok := pids.Load(pProcess.ppid) | ||
75 | if ok { | ||
76 | pParent := parent.(*process) | ||
77 | for i, child := range pParent.children { | ||
78 | if child == pProcess.pid { | ||
79 | pParent.children = append(pParent.children[:i], pParent.children[i+1:]...) | ||
80 | break | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | // 子进程需要收容 | ||
86 | for i := 0; i < len(pProcess.children); i++ { | ||
87 | child, ok := pids.Load(pProcess.children[i]) | ||
88 | if ok { | ||
89 | child.(*process).ppid = 1 | ||
90 | } | ||
91 | } | ||
92 | |||
93 | // 可以去死了 | ||
94 | pids.Delete(cooked.pid) | ||
95 | _, ok = pids.Load(cooked.pid) | ||
96 | fmt.Printf("%v Goodbye, %d! ok = %v\n", time.Now(), cooked.pid, ok) | ||
97 | } | ||
diff --git a/src/global.go b/src/global.go new file mode 100644 index 0000000..4e08866 --- /dev/null +++ b/src/global.go | |||
@@ -0,0 +1,10 @@ | |||
1 | package main | ||
2 | |||
3 | import "sync" | ||
4 | |||
5 | var pids sync.Map // 古希腊掌管进程的神,int->*process | ||
6 | var wg sync.WaitGroup // 掌管协程 | ||
7 | var rawChan chan interface{} // 从接收到整理的管道 | ||
8 | var cookedChan chan Event // 整理好的信息的管道 | ||
9 | var syscallTable [500]string //记录一下系统调用 | ||
10 | var containerdPid int | ||
diff --git a/src/godo.go b/src/godo.go new file mode 100644 index 0000000..6f73893 --- /dev/null +++ b/src/godo.go | |||
@@ -0,0 +1,116 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "flag" | ||
5 | "fmt" | ||
6 | "log" | ||
7 | "os" | ||
8 | "os/exec" | ||
9 | "time" | ||
10 | |||
11 | "github.com/elastic/go-libaudit/v2" | ||
12 | ) | ||
13 | |||
14 | var ( | ||
15 | fs = flag.NewFlagSet("audit", flag.ExitOnError) | ||
16 | diag = fs.String("diag", "", "dump raw information from kernel to file") | ||
17 | rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)") | ||
18 | backlog = fs.Uint("backlog", 8192, "backlog limit") | ||
19 | immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)") | ||
20 | receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+") | ||
21 | ) | ||
22 | |||
23 | type Event struct { | ||
24 | timestamp time.Time | ||
25 | pid, ppid int | ||
26 | syscall int | ||
27 | argc int | ||
28 | argv []string | ||
29 | cwd string | ||
30 | } | ||
31 | |||
32 | type process struct { | ||
33 | timestamp time.Time | ||
34 | pid, ppid int | ||
35 | argv []string | ||
36 | cwd string | ||
37 | rootfs string | ||
38 | children []int | ||
39 | } | ||
40 | |||
41 | func main() { | ||
42 | // 检查用户身份,并添加auditd规则,监听所有syscall | ||
43 | if os.Geteuid() != 0 { | ||
44 | fmt.Printf("Err: Please run me as root, %d!\n", os.Getegid()) | ||
45 | return | ||
46 | } | ||
47 | |||
48 | // 所有的系统调用号与名称的关系 | ||
49 | err := figureOutSyscalls() | ||
50 | if err != nil { | ||
51 | fmt.Printf("Error figuring out syscall numbers: %v\n", err) | ||
52 | } | ||
53 | |||
54 | syscall := [6]string{"fork", "vfork", "clone", "execve", "exit", "exit_group"} | ||
55 | var auditCmd *exec.Cmd | ||
56 | auditCmd = exec.Command("auditctl", "-D") // 清空所有规则 | ||
57 | auditCmd.Run() | ||
58 | // 设置监听规则 | ||
59 | for i := 0; i < len(syscall); i++ { | ||
60 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", syscall[i]) | ||
61 | auditCmd.Run() | ||
62 | } | ||
63 | |||
64 | // 查找pid | ||
65 | containerdPid, err = getPid() | ||
66 | if err != nil { | ||
67 | fmt.Printf("Error finding containerd: %v\n", err) | ||
68 | return | ||
69 | } | ||
70 | |||
71 | // 创世之神,1号进程 | ||
72 | // pids[1] = &process{rootfs: "/", children: make([]int, 0)} | ||
73 | // pids[1].children = append(pids[1].children, containerdPid) | ||
74 | // 1号进程还是不要在进程树上直接出现了,不然它的小儿子们都会出现 | ||
75 | |||
76 | // /usr/bin/containerd,也就是我们最关注的进程 | ||
77 | // pids[containerdPid] = &process{rootfs: "/", children: make([]int, 0)} | ||
78 | pids.Store(containerdPid, &process{ | ||
79 | ppid: 1, | ||
80 | pid: containerdPid, | ||
81 | argv: make([]string, 0), | ||
82 | cwd: "/", | ||
83 | rootfs: "/", | ||
84 | children: make([]int, 0), | ||
85 | }) | ||
86 | p, ok := pids.Load(containerdPid) | ||
87 | if !ok { | ||
88 | fmt.Printf("???\n") | ||
89 | return | ||
90 | } | ||
91 | p.(*process).argv = append(p.(*process).argv, "/usr/bin/containerd") | ||
92 | |||
93 | // 开始运行,解析命令行参数后监听 | ||
94 | if err := fs.Parse(os.Args[1:]); err != nil { | ||
95 | log.Fatal(err) | ||
96 | } | ||
97 | |||
98 | if err := read(); err != nil { | ||
99 | log.Fatalf("error: %v", err) | ||
100 | } | ||
101 | } | ||
102 | |||
103 | func coroutine(client *libaudit.AuditClient) { | ||
104 | // 各协程至此开始 | ||
105 | rawChan = make(chan interface{}) | ||
106 | cookedChan = make(chan Event) | ||
107 | wg.Add(1) | ||
108 | go receive(client) | ||
109 | wg.Add(1) | ||
110 | go orgnaze() | ||
111 | wg.Add(1) | ||
112 | go deal() | ||
113 | |||
114 | wg.Wait() | ||
115 | time.Sleep(2 * time.Second) | ||
116 | } | ||
diff --git a/src/organize.go b/src/organize.go new file mode 100644 index 0000000..025d8c0 --- /dev/null +++ b/src/organize.go | |||
@@ -0,0 +1,124 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "regexp" | ||
5 | "strconv" | ||
6 | "strings" | ||
7 | |||
8 | "github.com/elastic/go-libaudit/v2" | ||
9 | "github.com/elastic/go-libaudit/v2/auparse" | ||
10 | ) | ||
11 | |||
12 | func orgnaze() { | ||
13 | defer wg.Done() | ||
14 | defer close(cookedChan) | ||
15 | // 接收信息 | ||
16 | var raw interface{} | ||
17 | var ok bool | ||
18 | var rawEvent libaudit.RawAuditMessage | ||
19 | // 事件信息 | ||
20 | var eventId, argc int | ||
21 | var err [6]error | ||
22 | var event, cooked Event | ||
23 | // 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的 | ||
24 | eventTable := make(map[int]*Event) | ||
25 | // 要用的正则匹配列表 | ||
26 | syscallRegex := regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?ppid=(\d+) pid=(\d+).*?$`) | ||
27 | execveRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) | ||
28 | argsRegex := regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) | ||
29 | cwdRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`) | ||
30 | proctitleRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`) | ||
31 | eoeRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`) | ||
32 | for { | ||
33 | raw, ok = <-rawChan | ||
34 | if !ok { | ||
35 | break | ||
36 | } | ||
37 | rawEvent = raw.(libaudit.RawAuditMessage) | ||
38 | |||
39 | // type Event struct { | ||
40 | // timestamp time.Time | ||
41 | // pid, ppid int | ||
42 | // syscall int | ||
43 | // argc int | ||
44 | // args []string | ||
45 | // cwd string | ||
46 | // } | ||
47 | switch rawEvent.Type { | ||
48 | case auparse.AUDIT_SYSCALL: | ||
49 | if syscallRegex.Match(rawEvent.Data) { | ||
50 | match := syscallRegex.FindSubmatch(rawEvent.Data) | ||
51 | event.timestamp, err[0] = getTimeFromStr(string(match[1])) | ||
52 | eventId, err[1] = strconv.Atoi(string(match[2])) | ||
53 | event.syscall, err[2] = strconv.Atoi(string(match[3])) | ||
54 | event.ppid, err[3] = strconv.Atoi(string(match[4])) | ||
55 | event.pid, err[4] = strconv.Atoi(string(match[5])) | ||
56 | eventTable[eventId] = &Event{ | ||
57 | timestamp: event.timestamp, | ||
58 | syscall: event.syscall, | ||
59 | ppid: event.ppid, | ||
60 | pid: event.pid, | ||
61 | argc: 0, | ||
62 | argv: make([]string, 0), | ||
63 | cwd: "", | ||
64 | } | ||
65 | } | ||
66 | case auparse.AUDIT_EXECVE: | ||
67 | if execveRegex.Match(rawEvent.Data) { | ||
68 | match := execveRegex.FindSubmatch(rawEvent.Data) | ||
69 | eventId, err[0] = strconv.Atoi(string(match[1])) | ||
70 | argc, err[1] = strconv.Atoi(string(match[2])) | ||
71 | if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) { | ||
72 | match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) | ||
73 | for i := 0; i < argc; i++ { | ||
74 | if len(match[i][2]) == 0 { | ||
75 | // 代表着匹配到的是十六进制数 | ||
76 | str := hexToAscii(string(match[i][3])) | ||
77 | eventTable[eventId].argv = append(eventTable[eventId].argv, str) | ||
78 | } else { | ||
79 | eventTable[eventId].argv = append(eventTable[eventId].argv, string(match[i][2])) | ||
80 | } | ||
81 | } | ||
82 | eventTable[eventId].argc = argc | ||
83 | } | ||
84 | } | ||
85 | // case auparse.AUDIT_PATH: | ||
86 | case auparse.AUDIT_CWD: | ||
87 | if cwdRegex.Match(rawEvent.Data) { | ||
88 | match := cwdRegex.FindSubmatch(rawEvent.Data) | ||
89 | eventId, err[0] = strconv.Atoi(string(match[1])) | ||
90 | eventTable[eventId].cwd = string(match[2]) | ||
91 | } | ||
92 | case auparse.AUDIT_PROCTITLE: | ||
93 | if proctitleRegex.Match(rawEvent.Data) { | ||
94 | var cmdline string | ||
95 | var pEvent *Event | ||
96 | match := proctitleRegex.FindSubmatch(rawEvent.Data) | ||
97 | eventId, err[0] = strconv.Atoi(string(match[1])) | ||
98 | pEvent = eventTable[eventId] | ||
99 | if pEvent.argc == 0 { | ||
100 | // 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数 | ||
101 | if match[3] == nil { | ||
102 | // PROCTITLE写的是十六进制,转换为字符串 | ||
103 | cmdline = hexToAscii(string(match[4])) | ||
104 | } else { | ||
105 | cmdline = string(match[3]) | ||
106 | } | ||
107 | pEvent.argv = strings.Split(cmdline, " ") | ||
108 | pEvent.argc = len(eventTable[eventId].argv) | ||
109 | } | ||
110 | } | ||
111 | case auparse.AUDIT_EOE: | ||
112 | if eoeRegex.Match(rawEvent.Data) { | ||
113 | match := eoeRegex.FindSubmatch(rawEvent.Data) | ||
114 | eventId, err[0] = strconv.Atoi(string(match[1])) | ||
115 | // ATTENTION: 事件整理完毕,即刻发出,是否合理呢? | ||
116 | cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验 | ||
117 | cookedChan <- cooked | ||
118 | delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地 | ||
119 | } | ||
120 | default: | ||
121 | // ATTENTION: 这里也需要做防护 | ||
122 | } | ||
123 | } | ||
124 | } | ||
diff --git a/src/receive.go b/src/receive.go new file mode 100644 index 0000000..c0dea00 --- /dev/null +++ b/src/receive.go | |||
@@ -0,0 +1,29 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/elastic/go-libaudit/v2" | ||
7 | "github.com/elastic/go-libaudit/v2/auparse" | ||
8 | "github.com/mohae/deepcopy" | ||
9 | ) | ||
10 | |||
11 | func receive(r *libaudit.AuditClient) error { | ||
12 | defer wg.Done() | ||
13 | defer close(rawChan) | ||
14 | for { | ||
15 | rawEvent, err := r.Receive(false) | ||
16 | if err != nil { | ||
17 | return fmt.Errorf("receive failed: %w", err) | ||
18 | } | ||
19 | |||
20 | // Messages from 1300-2999 are valid audit messages. | ||
21 | if rawEvent.Type < auparse.AUDIT_USER_AUTH || | ||
22 | rawEvent.Type > auparse.AUDIT_LAST_USER_MSG2 { | ||
23 | continue | ||
24 | } | ||
25 | |||
26 | rawEventMessage := deepcopy.Copy(*rawEvent) | ||
27 | rawChan <- rawEventMessage | ||
28 | } | ||
29 | } | ||