diff options
Diffstat (limited to 'listener/godo.go')
-rw-r--r-- | listener/godo.go | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/listener/godo.go b/listener/godo.go new file mode 100644 index 0000000..efe9585 --- /dev/null +++ b/listener/godo.go | |||
@@ -0,0 +1,176 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "flag" | ||
6 | "fmt" | ||
7 | "log" | ||
8 | "netlink" | ||
9 | "os" | ||
10 | "os/exec" | ||
11 | "strings" | ||
12 | "syscall" | ||
13 | "time" | ||
14 | |||
15 | "github.com/elastic/go-libaudit/v2" | ||
16 | ) | ||
17 | |||
18 | var ( | ||
19 | fs = flag.NewFlagSet("audit", flag.ExitOnError) | ||
20 | diag = fs.String("diag", "", "dump raw information from kernel to file") | ||
21 | rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)") | ||
22 | backlog = fs.Uint("backlog", 8192, "backlog limit") | ||
23 | immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)") | ||
24 | receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+") | ||
25 | ) | ||
26 | |||
27 | func main() { | ||
28 | // 检查用户身份,并添加auditd规则,监听所有syscall | ||
29 | if os.Geteuid() != 0 { | ||
30 | fmt.Fprintf(os.Stderr, "Err: Please run me as root, %d!\n", os.Getegid()) | ||
31 | return | ||
32 | } | ||
33 | |||
34 | // 所有的系统调用号与名称的关系 | ||
35 | err := figureOutSyscalls() | ||
36 | if err != nil { | ||
37 | fmt.Fprintf(os.Stderr, "Error figuring out syscall numbers: %v\n", err) | ||
38 | } | ||
39 | |||
40 | exec.Command("auditctl", "-D").Run() | ||
41 | exec.Command("auditctl", "-b", "1000000000").Run() | ||
42 | exec.Command("auditctl", "--reset-lost").Run() | ||
43 | |||
44 | var auditCmd *exec.Cmd | ||
45 | |||
46 | pidSyscall := []string{"execve", "pivot_root"} | ||
47 | // // 设置监听规则 | ||
48 | for i := 0; i < len(pidSyscall); i++ { | ||
49 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i]) | ||
50 | auditCmd.Run() | ||
51 | } | ||
52 | |||
53 | // 监听文件的消息 | ||
54 | fileSyscall := []string{"open", "close", "write"} | ||
55 | // fileSyscall := []string{"open", "write", "creat", "unlink", "opendir", "mkdir", "rmdir", "chmod", "fchmod", "chown", "fchown", "lchown", "flock"} | ||
56 | for i := 0; i < len(fileSyscall); i++ { | ||
57 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", fileSyscall[i]) | ||
58 | auditCmd.Run() | ||
59 | } | ||
60 | |||
61 | // 查找pid | ||
62 | containerdPid, err = getPid() | ||
63 | if err != nil { | ||
64 | fmt.Fprintf(os.Stderr, "Error finding containerd: %v\n", err) | ||
65 | return | ||
66 | } | ||
67 | |||
68 | // 开始运行,解析命令行参数后监听 | ||
69 | if err := fs.Parse(os.Args[1:]); err != nil { | ||
70 | log.Fatal(err) | ||
71 | } | ||
72 | |||
73 | if err := read(); err != nil { | ||
74 | log.Fatalf("error: %v", err) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | func coroutine(client *libaudit.AuditClient) { | ||
79 | // 各协程至此开始 | ||
80 | rawChan = make(chan interface{}, 65536) | ||
81 | cookedChan = make(chan Event, 65536) | ||
82 | |||
83 | wg.Add(1) | ||
84 | go procWatch() | ||
85 | |||
86 | wg.Add(1) | ||
87 | go receive(client) | ||
88 | wg.Add(1) | ||
89 | go orgnaze() | ||
90 | wg.Add(1) | ||
91 | go deal() | ||
92 | |||
93 | wg.Wait() | ||
94 | time.Sleep(2 * time.Second) | ||
95 | } | ||
96 | |||
97 | func procWatch() error { | ||
98 | ns, err := netlink.NewNetlinkSocket(syscall.NETLINK_CONNECTOR, 12345) | ||
99 | if err != nil { | ||
100 | fmt.Fprintf(os.Stderr, "Error creating socket: %v\n", err) | ||
101 | return err | ||
102 | } | ||
103 | defer ns.Close() | ||
104 | for { | ||
105 | res, err := ns.Receive(20) | ||
106 | if err != nil { | ||
107 | fmt.Fprintf(os.Stderr, "Error recv: %v\n", err) | ||
108 | continue | ||
109 | } | ||
110 | for i := 0; i < len(res); i++ { | ||
111 | procEvent := netlink.ParseProcEvent(res[i].Data) | ||
112 | switch procEvent.What { | ||
113 | case netlink.PROC_EVENT_FORK: | ||
114 | data := procEvent.Data.(netlink.ProcEventFork) | ||
115 | cooked := Event{ | ||
116 | tag: NEWPID, | ||
117 | timestamp: time.Now(), | ||
118 | pid: int(data.ChildPid), | ||
119 | tgid: int(data.ChildTgid), | ||
120 | ppid: int(data.ParentPid), | ||
121 | parentTgid: int(data.ParentTgid), | ||
122 | } | ||
123 | checkProc(&cooked) | ||
124 | cookedChan <- cooked | ||
125 | case netlink.PROC_EVENT_EXIT: | ||
126 | data := procEvent.Data.(netlink.ProcEventExit) | ||
127 | cooked := Event{ | ||
128 | tag: PIDEXIT, | ||
129 | timestamp: time.Now(), | ||
130 | pid: int(data.ProcessPid), | ||
131 | exit_code: int(data.ExitCode), | ||
132 | exit_signal: int(data.ExitSignal), | ||
133 | } | ||
134 | cookedChan <- cooked | ||
135 | default: | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | |||
141 | func checkProc(pCooked *Event) { | ||
142 | fileName := fmt.Sprintf("/proc/%d/task/%d/", pCooked.tgid, pCooked.pid) | ||
143 | fd, err := os.Open(fileName + "cmdline") | ||
144 | if err != nil { | ||
145 | fmt.Fprintf(os.Stderr, "Err: %v\n", err) | ||
146 | return | ||
147 | } | ||
148 | |||
149 | scanner := bufio.NewScanner(fd) | ||
150 | scanner.Split(bufio.ScanLines) | ||
151 | for scanner.Scan() { | ||
152 | line := scanner.Text() | ||
153 | pCooked.argv = append(pCooked.argv, strings.Split(line, "\x00")...) | ||
154 | } | ||
155 | pCooked.argc = len(pCooked.argv) | ||
156 | fd.Close() | ||
157 | |||
158 | fd, err = os.Open(fileName + "comm") | ||
159 | if err != nil { | ||
160 | fmt.Fprintf(os.Stderr, "Err: %v\n", err) | ||
161 | return | ||
162 | } | ||
163 | scanner = bufio.NewScanner(fd) | ||
164 | scanner.Split(bufio.ScanLines) | ||
165 | for scanner.Scan() { | ||
166 | line := scanner.Text() | ||
167 | pCooked.comm = line | ||
168 | } | ||
169 | fd.Close() | ||
170 | |||
171 | pCooked.cwd, err = os.Readlink(fileName + "cwd") | ||
172 | if err != nil { | ||
173 | fmt.Fprintf(os.Stderr, "Err: %v\n", err) | ||
174 | pCooked.cwd = "" | ||
175 | } | ||
176 | } | ||