mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 08:34:40 +01:00
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.
This commit is contained in:
parent
5184c45086
commit
ced8410d43
2 changed files with 76 additions and 47 deletions
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/evilsocket/opensnitch/daemon/conman"
|
"github.com/evilsocket/opensnitch/daemon/conman"
|
||||||
"github.com/evilsocket/opensnitch/daemon/core"
|
"github.com/evilsocket/opensnitch/daemon/core"
|
||||||
"github.com/evilsocket/opensnitch/daemon/log"
|
"github.com/evilsocket/opensnitch/daemon/log"
|
||||||
|
"github.com/evilsocket/opensnitch/daemon/procmon"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type is the type of rule.
|
// Type is the type of rule.
|
||||||
|
@ -64,8 +65,9 @@ const (
|
||||||
OpDomainsRegexpLists = Operand("lists.domains_regexp")
|
OpDomainsRegexpLists = Operand("lists.domains_regexp")
|
||||||
OpIPLists = Operand("lists.ips")
|
OpIPLists = Operand("lists.ips")
|
||||||
OpNetLists = Operand("lists.nets")
|
OpNetLists = Operand("lists.nets")
|
||||||
|
OpHashMD5Lists = Operand("lists.hash.md5")
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
//OpHashMD5Lists = Operand("lists.hash.md5")
|
|
||||||
//OpQuota = Operand("quota")
|
//OpQuota = Operand("quota")
|
||||||
//OpQuotaTxOver = Operand("quota.sent.over") // 1000b, 1kb, 1mb, 1gb, ...
|
//OpQuotaTxOver = Operand("quota.sent.over") // 1000b, 1kb, 1mb, 1gb, ...
|
||||||
//OpQuotaRxOver = Operand("quota.recv.over") // 1000b, 1kb, 1mb, 1gb, ...
|
//OpQuotaRxOver = Operand("quota.recv.over") // 1000b, 1kb, 1mb, 1gb, ...
|
||||||
|
@ -225,7 +227,7 @@ func (o *Operator) Compile() error {
|
||||||
return fmt.Errorf("Operand lists is empty, nothing to load: %s", o)
|
return fmt.Errorf("Operand lists is empty, nothing to load: %s", o)
|
||||||
}
|
}
|
||||||
o.loadLists()
|
o.loadLists()
|
||||||
o.cb = o.domainsListCmp
|
o.cb = o.domainsListsCmp
|
||||||
} else if o.Operand == OpDomainsRegexpLists {
|
} else if o.Operand == OpDomainsRegexpLists {
|
||||||
if o.Data == "" {
|
if o.Data == "" {
|
||||||
return fmt.Errorf("Operand regexp lists is empty, nothing to load: %s", o)
|
return fmt.Errorf("Operand regexp lists is empty, nothing to load: %s", o)
|
||||||
|
@ -237,13 +239,19 @@ func (o *Operator) Compile() error {
|
||||||
return fmt.Errorf("Operand ip lists is empty, nothing to load: %s", o)
|
return fmt.Errorf("Operand ip lists is empty, nothing to load: %s", o)
|
||||||
}
|
}
|
||||||
o.loadLists()
|
o.loadLists()
|
||||||
o.cb = o.ipListCmp
|
o.cb = o.simpleListsCmp
|
||||||
} else if o.Operand == OpNetLists {
|
} else if o.Operand == OpNetLists {
|
||||||
if o.Data == "" {
|
if o.Data == "" {
|
||||||
return fmt.Errorf("Operand net lists is empty, nothing to load: %s", o)
|
return fmt.Errorf("Operand net lists is empty, nothing to load: %s", o)
|
||||||
}
|
}
|
||||||
o.loadLists()
|
o.loadLists()
|
||||||
o.cb = o.ipNetCmp
|
o.cb = o.ipNetCmp
|
||||||
|
} else if o.Operand == OpHashMD5Lists {
|
||||||
|
if o.Data == "" {
|
||||||
|
return fmt.Errorf("Operand lists.hash.md5 is empty, nothing to load: %s", o)
|
||||||
|
}
|
||||||
|
o.loadLists()
|
||||||
|
o.cb = o.simpleListsCmp
|
||||||
} else if o.Operand == OpProcessHashMD5 || o.Operand == OpProcessHashSHA1 {
|
} else if o.Operand == OpProcessHashMD5 || o.Operand == OpProcessHashSHA1 {
|
||||||
o.cb = o.hashCmp
|
o.cb = o.hashCmp
|
||||||
}
|
}
|
||||||
|
@ -288,7 +296,15 @@ func (o *Operator) cmpNetwork(destIP interface{}) bool {
|
||||||
return o.netMask.Contains(destIP.(net.IP))
|
return o.netMask.Contains(destIP.(net.IP))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operator) domainsListCmp(v interface{}) bool {
|
func (o *Operator) matchListsCmp(msg, what string) bool {
|
||||||
|
if item, found := o.lists[what]; found {
|
||||||
|
log.Debug("%s: %s, %s", log.Red(msg), what, item)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operator) domainsListsCmp(v interface{}) bool {
|
||||||
dstHost := v.(string)
|
dstHost := v.(string)
|
||||||
if dstHost == "" {
|
if dstHost == "" {
|
||||||
return false
|
return false
|
||||||
|
@ -299,26 +315,18 @@ func (o *Operator) domainsListCmp(v interface{}) bool {
|
||||||
o.RLock()
|
o.RLock()
|
||||||
defer o.RUnlock()
|
defer o.RUnlock()
|
||||||
|
|
||||||
if _, found := o.lists[dstHost]; found {
|
return o.matchListsCmp("domains list match", dstHost)
|
||||||
log.Debug("%s: %s, %s", log.Red("domain list match"), dstHost, o.lists[dstHost])
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operator) ipListCmp(v interface{}) bool {
|
func (o *Operator) simpleListsCmp(v interface{}) bool {
|
||||||
dstIP := v.(string)
|
what := v.(string)
|
||||||
if dstIP == "" {
|
if what == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
o.RLock()
|
o.RLock()
|
||||||
defer o.RUnlock()
|
defer o.RUnlock()
|
||||||
|
|
||||||
if _, found := o.lists[dstIP]; found {
|
return o.matchListsCmp("simple list match", what)
|
||||||
log.Debug("%s: %s, %s", log.Red("IP list match"), dstIP, o.lists[dstIP].(string))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operator) ipNetCmp(dstIP interface{}) bool {
|
func (o *Operator) ipNetCmp(dstIP interface{}) bool {
|
||||||
|
@ -393,6 +401,8 @@ func (o *Operator) Match(con *conman.Connection, hasChecksums bool) bool {
|
||||||
return o.cb(con.DstHost)
|
return o.cb(con.DstHost)
|
||||||
} else if o.Operand == OpIPLists {
|
} else if o.Operand == OpIPLists {
|
||||||
return o.cb(con.DstIP.String())
|
return o.cb(con.DstIP.String())
|
||||||
|
} else if o.Operand == OpHashMD5Lists {
|
||||||
|
return o.cb(con.Process.Checksums[procmon.HashMD5])
|
||||||
} else if o.Operand == OpUserID || o.Operand == OpUserName {
|
} else if o.Operand == OpUserID || o.Operand == OpUserName {
|
||||||
return o.cb(strconv.Itoa(con.Entry.UserId))
|
return o.cb(strconv.Itoa(con.Entry.UserId))
|
||||||
} else if o.Operand == OpDstNetwork {
|
} else if o.Operand == OpDstNetwork {
|
||||||
|
|
|
@ -104,32 +104,46 @@ func (o *Operator) StopMonitoringLists() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operator) readDomainsList(raw, fileName string) (dups uint64) {
|
func filterDomains(line, defValue string) (bool, string, string) {
|
||||||
log.Debug("Loading domains list: %s, size: %d", fileName, len(raw))
|
if len(line) < 9 {
|
||||||
lines := strings.Split(string(raw), "\n")
|
return true, line, defValue
|
||||||
for _, domain := range lines {
|
}
|
||||||
if len(domain) < 9 {
|
// exclude not valid lines
|
||||||
continue
|
if line[:7] != "0.0.0.0" && line[:9] != "127.0.0.1" {
|
||||||
}
|
return true, line, defValue
|
||||||
// exclude not valid lines
|
}
|
||||||
if domain[:7] != "0.0.0.0" && domain[:9] != "127.0.0.1" {
|
host := line[8:]
|
||||||
continue
|
// exclude localhost entries
|
||||||
}
|
if line[:9] == "127.0.0.1" {
|
||||||
host := domain[8:]
|
host = line[10:]
|
||||||
// exclude localhost entries
|
}
|
||||||
if domain[:9] == "127.0.0.1" {
|
if host == "local" || host == "localhost" || host == "localhost.localdomain" || host == "broadcasthost" {
|
||||||
host = domain[10:]
|
return true, line, defValue
|
||||||
}
|
}
|
||||||
if host == "local" || host == "localhost" || host == "localhost.localdomain" || host == "broadcasthost" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
host = core.Trim(host)
|
return false, host, defValue
|
||||||
if _, found := o.lists[host]; found {
|
}
|
||||||
|
|
||||||
|
func filterSimple(line, hashPath string) (bool, string, string) {
|
||||||
|
// XXX: some lists may use TABs as separator
|
||||||
|
hash := strings.SplitN(line, " ", 2)
|
||||||
|
return false, hash[0], hash[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operator) readTupleList(raw, fileName string, filter func(line, defValue string) (bool, string, string)) (dups uint64) {
|
||||||
|
log.Debug("Loading list: %s, size: %d", fileName, len(raw))
|
||||||
|
lines := strings.Split(string(raw), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
skip, key, value := filter(line, fileName)
|
||||||
|
if skip || len(line) < 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key = core.Trim(key)
|
||||||
|
if _, found := o.lists[key]; found {
|
||||||
dups++
|
dups++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
o.lists[host] = fileName
|
o.lists[key] = value
|
||||||
}
|
}
|
||||||
lines = nil
|
lines = nil
|
||||||
log.Info("%d domains loaded, %s", len(o.lists), fileName)
|
log.Info("%d domains loaded, %s", len(o.lists), fileName)
|
||||||
|
@ -187,22 +201,25 @@ func (o *Operator) readRegexpList(raw, fileName string) (dups uint64) {
|
||||||
return dups
|
return dups
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operator) readIPList(raw, fileName string) (dups uint64) {
|
// A simple list is a list composed of one column with several entries, that
|
||||||
log.Debug("Loading IPs list: %s, size: %d", fileName, len(raw))
|
// don't require manipulation.
|
||||||
|
// It can be a list of IPs, domains, etc.
|
||||||
|
func (o *Operator) readSimpleList(raw, fileName string) (dups uint64) {
|
||||||
|
log.Debug("Loading simple list: %s, size: %d", fileName, len(raw))
|
||||||
lines := strings.Split(string(raw), "\n")
|
lines := strings.Split(string(raw), "\n")
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
if line == "" || line[0] == '#' {
|
if line == "" || line[0] == '#' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ip := core.Trim(line)
|
what := core.Trim(line)
|
||||||
if _, found := o.lists[ip]; found {
|
if _, found := o.lists[what]; found {
|
||||||
dups++
|
dups++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
o.lists[ip] = fileName
|
o.lists[what] = fileName
|
||||||
}
|
}
|
||||||
lines = nil
|
lines = nil
|
||||||
log.Info("%d IPs loaded, %s", len(o.lists), fileName)
|
log.Info("%d entries loaded, %s", len(o.lists), fileName)
|
||||||
|
|
||||||
return dups
|
return dups
|
||||||
}
|
}
|
||||||
|
@ -236,13 +253,15 @@ func (o *Operator) readLists() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.Operand == OpDomainsLists {
|
if o.Operand == OpDomainsLists {
|
||||||
dups += o.readDomainsList(string(raw), fileName)
|
dups += o.readTupleList(string(raw), fileName, filterDomains)
|
||||||
} else if o.Operand == OpDomainsRegexpLists {
|
} else if o.Operand == OpDomainsRegexpLists {
|
||||||
dups += o.readRegexpList(string(raw), fileName)
|
dups += o.readRegexpList(string(raw), fileName)
|
||||||
} else if o.Operand == OpNetLists {
|
} else if o.Operand == OpNetLists {
|
||||||
dups += o.readNetList(string(raw), fileName)
|
dups += o.readNetList(string(raw), fileName)
|
||||||
} else if o.Operand == OpIPLists {
|
} else if o.Operand == OpIPLists {
|
||||||
dups += o.readIPList(string(raw), fileName)
|
dups += o.readSimpleList(string(raw), fileName)
|
||||||
|
} else if o.Operand == OpHashMD5Lists {
|
||||||
|
dups += o.readSimpleList(string(raw), fileName)
|
||||||
} else {
|
} else {
|
||||||
log.Warning("Unknown lists operand type: %s", o.Operand)
|
log.Warning("Unknown lists operand type: %s", o.Operand)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue