Skip to content

Commit ced8410

Browse files
allow to use lists of md5s to block connections
Besides domains, net ranges and IPs, now it's possible to filter connections by the MD5 of a binary, if it's enabled.
1 parent 5184c45 commit ced8410

File tree

2 files changed

+74
-45
lines changed

2 files changed

+74
-45
lines changed

daemon/rule/operator.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/evilsocket/opensnitch/daemon/conman"
1616
"github.com/evilsocket/opensnitch/daemon/core"
1717
"github.com/evilsocket/opensnitch/daemon/log"
18+
"github.com/evilsocket/opensnitch/daemon/procmon"
1819
)
1920

2021
// Type is the type of rule.
@@ -64,8 +65,9 @@ const (
6465
OpDomainsRegexpLists = Operand("lists.domains_regexp")
6566
OpIPLists = Operand("lists.ips")
6667
OpNetLists = Operand("lists.nets")
68+
OpHashMD5Lists = Operand("lists.hash.md5")
69+
6770
// TODO
68-
//OpHashMD5Lists = Operand("lists.hash.md5")
6971
//OpQuota = Operand("quota")
7072
//OpQuotaTxOver = Operand("quota.sent.over") // 1000b, 1kb, 1mb, 1gb, ...
7173
//OpQuotaRxOver = Operand("quota.recv.over") // 1000b, 1kb, 1mb, 1gb, ...
@@ -225,7 +227,7 @@ func (o *Operator) Compile() error {
225227
return fmt.Errorf("Operand lists is empty, nothing to load: %s", o)
226228
}
227229
o.loadLists()
228-
o.cb = o.domainsListCmp
230+
o.cb = o.domainsListsCmp
229231
} else if o.Operand == OpDomainsRegexpLists {
230232
if o.Data == "" {
231233
return fmt.Errorf("Operand regexp lists is empty, nothing to load: %s", o)
@@ -237,13 +239,19 @@ func (o *Operator) Compile() error {
237239
return fmt.Errorf("Operand ip lists is empty, nothing to load: %s", o)
238240
}
239241
o.loadLists()
240-
o.cb = o.ipListCmp
242+
o.cb = o.simpleListsCmp
241243
} else if o.Operand == OpNetLists {
242244
if o.Data == "" {
243245
return fmt.Errorf("Operand net lists is empty, nothing to load: %s", o)
244246
}
245247
o.loadLists()
246248
o.cb = o.ipNetCmp
249+
} else if o.Operand == OpHashMD5Lists {
250+
if o.Data == "" {
251+
return fmt.Errorf("Operand lists.hash.md5 is empty, nothing to load: %s", o)
252+
}
253+
o.loadLists()
254+
o.cb = o.simpleListsCmp
247255
} else if o.Operand == OpProcessHashMD5 || o.Operand == OpProcessHashSHA1 {
248256
o.cb = o.hashCmp
249257
}
@@ -288,7 +296,15 @@ func (o *Operator) cmpNetwork(destIP interface{}) bool {
288296
return o.netMask.Contains(destIP.(net.IP))
289297
}
290298

291-
func (o *Operator) domainsListCmp(v interface{}) bool {
299+
func (o *Operator) matchListsCmp(msg, what string) bool {
300+
if item, found := o.lists[what]; found {
301+
log.Debug("%s: %s, %s", log.Red(msg), what, item)
302+
return true
303+
}
304+
return false
305+
}
306+
307+
func (o *Operator) domainsListsCmp(v interface{}) bool {
292308
dstHost := v.(string)
293309
if dstHost == "" {
294310
return false
@@ -299,26 +315,18 @@ func (o *Operator) domainsListCmp(v interface{}) bool {
299315
o.RLock()
300316
defer o.RUnlock()
301317

302-
if _, found := o.lists[dstHost]; found {
303-
log.Debug("%s: %s, %s", log.Red("domain list match"), dstHost, o.lists[dstHost])
304-
return true
305-
}
306-
return false
318+
return o.matchListsCmp("domains list match", dstHost)
307319
}
308320

309-
func (o *Operator) ipListCmp(v interface{}) bool {
310-
dstIP := v.(string)
311-
if dstIP == "" {
321+
func (o *Operator) simpleListsCmp(v interface{}) bool {
322+
what := v.(string)
323+
if what == "" {
312324
return false
313325
}
314326
o.RLock()
315327
defer o.RUnlock()
316328

317-
if _, found := o.lists[dstIP]; found {
318-
log.Debug("%s: %s, %s", log.Red("IP list match"), dstIP, o.lists[dstIP].(string))
319-
return true
320-
}
321-
return false
329+
return o.matchListsCmp("simple list match", what)
322330
}
323331

324332
func (o *Operator) ipNetCmp(dstIP interface{}) bool {
@@ -393,6 +401,8 @@ func (o *Operator) Match(con *conman.Connection, hasChecksums bool) bool {
393401
return o.cb(con.DstHost)
394402
} else if o.Operand == OpIPLists {
395403
return o.cb(con.DstIP.String())
404+
} else if o.Operand == OpHashMD5Lists {
405+
return o.cb(con.Process.Checksums[procmon.HashMD5])
396406
} else if o.Operand == OpUserID || o.Operand == OpUserName {
397407
return o.cb(strconv.Itoa(con.Entry.UserId))
398408
} else if o.Operand == OpDstNetwork {

daemon/rule/operator_lists.go

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -104,32 +104,46 @@ func (o *Operator) StopMonitoringLists() {
104104
}
105105
}
106106

107-
func (o *Operator) readDomainsList(raw, fileName string) (dups uint64) {
108-
log.Debug("Loading domains list: %s, size: %d", fileName, len(raw))
107+
func filterDomains(line, defValue string) (bool, string, string) {
108+
if len(line) < 9 {
109+
return true, line, defValue
110+
}
111+
// exclude not valid lines
112+
if line[:7] != "0.0.0.0" && line[:9] != "127.0.0.1" {
113+
return true, line, defValue
114+
}
115+
host := line[8:]
116+
// exclude localhost entries
117+
if line[:9] == "127.0.0.1" {
118+
host = line[10:]
119+
}
120+
if host == "local" || host == "localhost" || host == "localhost.localdomain" || host == "broadcasthost" {
121+
return true, line, defValue
122+
}
123+
124+
return false, host, defValue
125+
}
126+
127+
func filterSimple(line, hashPath string) (bool, string, string) {
128+
// XXX: some lists may use TABs as separator
129+
hash := strings.SplitN(line, " ", 2)
130+
return false, hash[0], hash[1]
131+
}
132+
133+
func (o *Operator) readTupleList(raw, fileName string, filter func(line, defValue string) (bool, string, string)) (dups uint64) {
134+
log.Debug("Loading list: %s, size: %d", fileName, len(raw))
109135
lines := strings.Split(string(raw), "\n")
110-
for _, domain := range lines {
111-
if len(domain) < 9 {
112-
continue
113-
}
114-
// exclude not valid lines
115-
if domain[:7] != "0.0.0.0" && domain[:9] != "127.0.0.1" {
116-
continue
117-
}
118-
host := domain[8:]
119-
// exclude localhost entries
120-
if domain[:9] == "127.0.0.1" {
121-
host = domain[10:]
122-
}
123-
if host == "local" || host == "localhost" || host == "localhost.localdomain" || host == "broadcasthost" {
136+
for _, line := range lines {
137+
skip, key, value := filter(line, fileName)
138+
if skip || len(line) < 9 {
124139
continue
125140
}
126-
127-
host = core.Trim(host)
128-
if _, found := o.lists[host]; found {
141+
key = core.Trim(key)
142+
if _, found := o.lists[key]; found {
129143
dups++
130144
continue
131145
}
132-
o.lists[host] = fileName
146+
o.lists[key] = value
133147
}
134148
lines = nil
135149
log.Info("%d domains loaded, %s", len(o.lists), fileName)
@@ -187,22 +201,25 @@ func (o *Operator) readRegexpList(raw, fileName string) (dups uint64) {
187201
return dups
188202
}
189203

190-
func (o *Operator) readIPList(raw, fileName string) (dups uint64) {
191-
log.Debug("Loading IPs list: %s, size: %d", fileName, len(raw))
204+
// A simple list is a list composed of one column with several entries, that
205+
// don't require manipulation.
206+
// It can be a list of IPs, domains, etc.
207+
func (o *Operator) readSimpleList(raw, fileName string) (dups uint64) {
208+
log.Debug("Loading simple list: %s, size: %d", fileName, len(raw))
192209
lines := strings.Split(string(raw), "\n")
193210
for _, line := range lines {
194211
if line == "" || line[0] == '#' {
195212
continue
196213
}
197-
ip := core.Trim(line)
198-
if _, found := o.lists[ip]; found {
214+
what := core.Trim(line)
215+
if _, found := o.lists[what]; found {
199216
dups++
200217
continue
201218
}
202-
o.lists[ip] = fileName
219+
o.lists[what] = fileName
203220
}
204221
lines = nil
205-
log.Info("%d IPs loaded, %s", len(o.lists), fileName)
222+
log.Info("%d entries loaded, %s", len(o.lists), fileName)
206223

207224
return dups
208225
}
@@ -236,13 +253,15 @@ func (o *Operator) readLists() error {
236253
}
237254

238255
if o.Operand == OpDomainsLists {
239-
dups += o.readDomainsList(string(raw), fileName)
256+
dups += o.readTupleList(string(raw), fileName, filterDomains)
240257
} else if o.Operand == OpDomainsRegexpLists {
241258
dups += o.readRegexpList(string(raw), fileName)
242259
} else if o.Operand == OpNetLists {
243260
dups += o.readNetList(string(raw), fileName)
244261
} else if o.Operand == OpIPLists {
245-
dups += o.readIPList(string(raw), fileName)
262+
dups += o.readSimpleList(string(raw), fileName)
263+
} else if o.Operand == OpHashMD5Lists {
264+
dups += o.readSimpleList(string(raw), fileName)
246265
} else {
247266
log.Warning("Unknown lists operand type: %s", o.Operand)
248267
}

0 commit comments

Comments
 (0)