diff --git a/daemon/dns/systemd/monitor.go b/daemon/dns/systemd/monitor.go index 15ef2ec1..648eb094 100644 --- a/daemon/dns/systemd/monitor.go +++ b/daemon/dns/systemd/monitor.go @@ -43,14 +43,16 @@ const ( DNSTypeAAAA = 28 // DNSTypeCNAME cname DNSTypeCNAME = 5 + // DNSTypeSOA soa + DNSTypeSOA = 6 ) // QuestionMonitorResponse represents a DNS query // "question": [{"class": 1, "type": 28,"name": "images.site.com"}], type QuestionMonitorResponse struct { + Name string `json:"name"` Class int `json:"class"` Type int `json:"type"` - Name string `json:"name"` } // KeyType holds question that generated the answer @@ -67,23 +69,23 @@ type QuestionMonitorResponse struct { "ifindex": 3 }]*/ type KeyType struct { + Name string `json:"name"` Class int `json:"class"` Type int `json:"type"` - Name string `json:"name"` } // RRType represents a DNS answer // if the response is a CNAME, Address will be nil, and Name a domain name. type RRType struct { - Key QuestionMonitorResponse `json:"key"` - Address []byte `json:"address"` Name string `json:"name"` + Address []byte `json:"address"` + Key QuestionMonitorResponse `json:"key"` } // AnswerMonitorResponse represents the DNS answer of a DNS query. type AnswerMonitorResponse struct { - RR RRType `json:"rr"` Raw string `json:"raw"` + RR RRType `json:"rr"` Ifindex int `json:"ifindex"` } @@ -105,9 +107,7 @@ type ResolvedMonitor struct { // connection with the systemd-resolved unix socket: // /run/systemd/resolve/io.systemd.Resolve.Monitor - Conn *varlink.Connection - connected bool - + Conn *varlink.Connection // channel where all the DNS respones will be sent ChanResponse chan *MonitorResponse @@ -116,8 +116,8 @@ type ResolvedMonitor struct { // callback that is emited when systemd-resolved resolves a domain name. receiverCb resolvedCallback - - mu *sync.RWMutex + mu *sync.RWMutex + connected bool } // NewResolvedMonitor returns a new ResolvedMonitor object. diff --git a/daemon/firewall/common/common.go b/daemon/firewall/common/common.go index 9c858940..42038ddd 100644 --- a/daemon/firewall/common/common.go +++ b/daemon/firewall/common/common.go @@ -29,9 +29,9 @@ type ( // iptables and nftables. Common struct { RulesChecker *time.Ticker - RulesCheckInterval time.Duration ErrChan chan string stopChecker chan bool + RulesCheckInterval time.Duration QueueNum uint16 Running bool Intercepting bool diff --git a/daemon/firewall/config/config.go b/daemon/firewall/config/config.go index 63b1aa07..6486156b 100644 --- a/daemon/firewall/config/config.go +++ b/daemon/firewall/config/config.go @@ -5,7 +5,6 @@ // The firewall rules defined by the user are reloaded in these cases: // - When the file system-fw.json changes. // - When the firewall rules are not present when listing them. -// package config import ( @@ -59,21 +58,18 @@ type Expressions struct { // FwRule holds the fields of a rule type FwRule struct { + *sync.RWMutex // we need to keep old fields in the struct. Otherwise when receiving a conf from the GUI, the legacy rules would be deleted. - Chain string // TODO: deprecated, remove - Table string // TODO: deprecated, remove - Parameters string // TODO: deprecated: remove - + Chain string // TODO: deprecated, remove + Table string // TODO: deprecated, remove + Parameters string // TODO: deprecated, remove UUID string Description string - Expressions []*Expressions Target string TargetParameters string - - Position uint64 `json:",string"` - Enabled bool - - *sync.RWMutex + Expressions []*Expressions + Position uint64 `json:",string"` + Enabled bool } // FwChain holds the information that defines a firewall chain. @@ -102,33 +98,32 @@ type rulesList struct { } type chainsList struct { - Chains []*FwChain Rule *FwRule // TODO: deprecated, remove + Chains []*FwChain } // SystemConfig holds the list of rules to be added to the system type SystemConfig struct { - sync.RWMutex SystemRules []*chainsList - Version uint32 - Enabled bool + sync.RWMutex + Version uint32 + Enabled bool } // Config holds the functionality to re/load the firewall configuration from disk. // This is the configuration to manage the system firewall (iptables, nftables). type Config struct { - sync.Mutex watcher *fsnotify.Watcher - SysConfig SystemConfig monitorExitChan chan bool - file string - // preloadCallback is called before reloading the configuration, // in order to delete old fw rules. preloadCallback func() // reloadCallback is called after the configuration is written. reloadCallback func() // preload will be called after daemon startup, whilst reload when a modification is performed. + file string + SysConfig SystemConfig + sync.Mutex } // NewSystemFwConfig initializes config fields diff --git a/daemon/firewall/iptables/iptables.go b/daemon/firewall/iptables/iptables.go index 8bc861cb..90ea6de3 100644 --- a/daemon/firewall/iptables/iptables.go +++ b/daemon/firewall/iptables/iptables.go @@ -41,9 +41,9 @@ const ( // SystemRule blabla type SystemRule struct { + Rule *config.FwRule Table string Chain string - Rule *config.FwRule } // SystemChains keeps track of the fw rules that have been added to the system. @@ -54,16 +54,13 @@ type SystemChains struct { // Iptables struct holds the fields of the iptables fw type Iptables struct { - config.Config - common.Common - - bin string - bin6 string - regexRulesQuery *regexp.Regexp regexSystemRulesQuery *regexp.Regexp - - chains SystemChains + bin string + bin6 string + chains SystemChains + common.Common + config.Config sync.Mutex } diff --git a/daemon/firewall/nftables/nftables.go b/daemon/firewall/nftables/nftables.go index 32b91938..525b1345 100644 --- a/daemon/firewall/nftables/nftables.go +++ b/daemon/firewall/nftables/nftables.go @@ -41,12 +41,12 @@ var ( // Nft holds the fields of our nftables firewall type Nft struct { - sync.Mutex - config.Config - common.Common - Conn *nftables.Conn chains iptables.SystemChains + + common.Common + config.Config + sync.Mutex } // NewNft creates a new nftables object diff --git a/daemon/log/formats/json.go b/daemon/log/formats/json.go index 6baab583..438c032b 100644 --- a/daemon/log/formats/json.go +++ b/daemon/log/formats/json.go @@ -19,9 +19,9 @@ const ( // JSONEventFormat object to be sent to the remote service. // TODO: Expand as needed: ebpf events, etc. type JSONEventFormat struct { + Event interface{} `json:"Event"` Rule string `json:"Rule"` Action string `json:"Action"` - Event interface{} `json:"Event"` Type uint8 `json:"Type"` } diff --git a/daemon/log/loggers/remote.go b/daemon/log/loggers/remote.go index 7936c2fc..637fbfe3 100644 --- a/daemon/log/loggers/remote.go +++ b/daemon/log/loggers/remote.go @@ -22,20 +22,18 @@ const ( // It can write to the local or a remote daemon, UDP or TCP. // It supports writing events in RFC5424, RFC3164, CSV and JSON formats. type Remote struct { - Name string - Tag string - Hostname string - + mu *sync.RWMutex Writer *syslog.Writer - logFormat formats.LoggerFormat cfg *LoggerConfig + logFormat formats.LoggerFormat netConn net.Conn + Name string + Tag string + Hostname string Timeout time.Duration errors uint32 maxErrors uint32 status uint32 - - mu *sync.RWMutex } // NewRemote returns a new object that manipulates and prints outbound connections diff --git a/daemon/log/loggers/remote_syslog.go b/daemon/log/loggers/remote_syslog.go index e67b86e3..a3424222 100644 --- a/daemon/log/loggers/remote_syslog.go +++ b/daemon/log/loggers/remote_syslog.go @@ -30,14 +30,12 @@ const ( // It can write to the local or a remote daemon. type RemoteSyslog struct { Syslog - - Hostname string + mu *sync.RWMutex netConn net.Conn + Hostname string Timeout time.Duration errors uint32 status uint32 - - mu *sync.RWMutex } // NewRemoteSyslog returns a new object that manipulates and prints outbound connections diff --git a/daemon/log/loggers/syslog.go b/daemon/log/loggers/syslog.go index d0ea929d..d562376a 100644 --- a/daemon/log/loggers/syslog.go +++ b/daemon/log/loggers/syslog.go @@ -14,11 +14,11 @@ const ( // Syslog defines the logger that writes traces to the syslog. // It can write to the local or a remote daemon. type Syslog struct { - Name string - Writer *syslog.Writer - Tag string - logFormat formats.LoggerFormat cfg *LoggerConfig + Writer *syslog.Writer + logFormat formats.LoggerFormat + Name string + Tag string } // NewSyslog returns a new object that manipulates and prints outbound connections diff --git a/daemon/netfilter/queue.go b/daemon/netfilter/queue.go index 7d84611f..ac4cf7ae 100644 --- a/daemon/netfilter/queue.go +++ b/daemon/netfilter/queue.go @@ -57,8 +57,8 @@ type VerdictContainerC C.verdictContainer type Queue struct { h *C.struct_nfq_handle qh *C.struct_nfq_q_handle - fd C.int packets chan Packet + fd C.int idx uint32 } diff --git a/daemon/netstat/entry.go b/daemon/netstat/entry.go index 6214a00e..8ef132d0 100644 --- a/daemon/netstat/entry.go +++ b/daemon/netstat/entry.go @@ -11,8 +11,8 @@ import ( type Entry struct { Proto string SrcIP net.IP - SrcPort uint DstIP net.IP + SrcPort uint DstPort uint UserId int INode int diff --git a/daemon/procmon/cache.go b/daemon/procmon/cache.go index 395fc422..ff347efb 100644 --- a/daemon/procmon/cache.go +++ b/daemon/procmon/cache.go @@ -12,35 +12,33 @@ import ( // InodeItem represents an item of the InodesCache. type InodeItem struct { - sync.RWMutex - - Pid int FdPath string + Pid int LastSeen int64 + sync.RWMutex } // ProcItem represents an item of the pidsCache type ProcItem struct { - sync.RWMutex - - Pid int FdPath string Descriptors []string + Pid int LastSeen int64 + sync.RWMutex } // CacheProcs holds the cache of processes that have established connections. type CacheProcs struct { - sync.RWMutex items []*ProcItem + sync.RWMutex } // CacheInodes holds the cache of Inodes. // The key is formed as follow: // inode+srcip+srcport+dstip+dstport type CacheInodes struct { - sync.RWMutex items map[string]*InodeItem + sync.RWMutex } var ( diff --git a/daemon/rule/loader.go b/daemon/rule/loader.go index 85f46f82..55a4c1f7 100644 --- a/daemon/rule/loader.go +++ b/daemon/rule/loader.go @@ -23,14 +23,15 @@ import ( // Loader is the object that holds the rules loaded from disk, as well as the // rules watcher. type Loader struct { - sync.RWMutex + watcher *fsnotify.Watcher rules map[string]*Rule path string - watcher *fsnotify.Watcher rulesKeys []string liveReload bool liveReloadRunning bool checkSums bool + + sync.RWMutex } // NewLoader loads rules from disk, and watches for changes made to the rules files diff --git a/daemon/rule/operator.go b/daemon/rule/operator.go index ea0f4eab..338f9ead 100644 --- a/daemon/rule/operator.go +++ b/daemon/rule/operator.go @@ -60,27 +60,31 @@ const ( OpIPLists = Operand("lists.ips") OpNetLists = Operand("lists.nets") // TODO - // OpHashMD5 = Operand("lists.hash.md5") + //OpHashMD5Lists = Operand("lists.hash.md5") + //OpQuota = Operand("quota") + //OpQuotaTxOver = Operand("quota.sent.over") // 1000b, 1kb, 1mb, 1gb, ... + //OpQuotaRxOver = Operand("quota.recv.over") // 1000b, 1kb, 1mb, 1gb, ... ) type opCallback func(value interface{}) bool // Operator represents what we want to filter of a connection, and how. type Operator struct { - Type Type `json:"type"` - Operand Operand `json:"operand"` - Sensitive Sensitive `json:"sensitive"` - Data string `json:"data"` - List []Operator `json:"list"` + cb opCallback + re *regexp.Regexp + netMask *net.IPNet + lists map[string]interface{} + exitMonitorChan chan (bool) - sync.RWMutex - re *regexp.Regexp - netMask *net.IPNet - lists map[string]interface{} - cb opCallback - exitMonitorChan chan (bool) + Operand Operand `json:"operand"` + Data string `json:"data"` + Type Type `json:"type"` + List []Operator `json:"list"` + Sensitive Sensitive `json:"sensitive"` isCompiled bool listsMonitorRunning bool + + sync.RWMutex } // NewOperator returns a new operator object diff --git a/daemon/rule/rule.go b/daemon/rule/rule.go index f743069a..242df0b8 100644 --- a/daemon/rule/rule.go +++ b/daemon/rule/rule.go @@ -37,12 +37,12 @@ type Rule struct { Updated time.Time `json:"updated"` Name string `json:"name"` Description string `json:"description"` - Enabled bool `json:"enabled"` - Precedence bool `json:"precedence"` - Nolog bool `json:"nolog"` Action Action `json:"action"` Duration Duration `json:"duration"` Operator Operator `json:"operator"` + Enabled bool `json:"enabled"` + Precedence bool `json:"precedence"` + Nolog bool `json:"nolog"` } // Create creates a new rule object with the specified parameters. diff --git a/daemon/statistics/stats.go b/daemon/statistics/stats.go index c561ce72..91c60191 100644 --- a/daemon/statistics/stats.go +++ b/daemon/statistics/stats.go @@ -29,32 +29,32 @@ type conEvent struct { // Statistics holds the connections and statistics the daemon intercepts. // The connections are stored in the Events slice. type Statistics struct { - sync.RWMutex - Started time.Time - DNSResponses int - Connections int - Ignored int - Accepted int - Dropped int - RuleHits int - RuleMisses int - Events []*Event - ByProto map[string]uint64 - ByAddress map[string]uint64 - ByHost map[string]uint64 - ByPort map[string]uint64 - ByUID map[string]uint64 + logger *loggers.LoggerManager + rules *rule.Loader ByExecutable map[string]uint64 + ByUID map[string]uint64 + ByAddress map[string]uint64 + ByPort map[string]uint64 + ByHost map[string]uint64 + ByProto map[string]uint64 + jobs chan conEvent + Events []*Event - rules *rule.Loader - jobs chan conEvent + RuleHits int + Accepted int + Ignored int + Connections int + RuleMisses int + DNSResponses int // max number of events to keep in the buffer maxEvents int // max number of entries for each By* map - maxStats int + maxStats int + maxWorkers int + Dropped int - logger *loggers.LoggerManager + sync.RWMutex } // New returns a new Statistics object and initializes the go routines to update the stats. @@ -93,12 +93,12 @@ func (s *Statistics) SetLimits(config StatsConfig) { if config.MaxStats > 0 { s.maxStats = config.MaxStats } - wrks := config.Workers - if wrks == 0 { - wrks = 6 + s.maxWorkers = config.Workers + if s.maxWorkers == 0 { + s.maxWorkers = 6 } - log.Info("Stats, max events: %d, max stats: %d, max workers: %d", s.maxStats, s.maxEvents, wrks) - for i := 0; i < wrks; i++ { + log.Info("Stats, max events: %d, max stats: %d, max workers: %d", s.maxStats, s.maxEvents, s.maxWorkers) + for i := 0; i < s.maxWorkers; i++ { go s.eventWorker(i) } diff --git a/daemon/ui/client.go b/daemon/ui/client.go index 3dbef3cf..68354c99 100644 --- a/daemon/ui/client.go +++ b/daemon/ui/client.go @@ -38,25 +38,27 @@ var ( // Client holds the connection information of a client. type Client struct { - sync.RWMutex - clientCtx context.Context - clientCancel context.CancelFunc + client protocol.UIClient + streamNotifications protocol.UI_NotificationsClient + clientCtx context.Context + clientCancel context.CancelFunc + + stats *statistics.Statistics + rules *rule.Loader + con *grpc.ClientConn + configWatcher *fsnotify.Watcher + + alertsChan chan protocol.Alert + isConnected chan bool - stats *statistics.Statistics - rules *rule.Loader socketPath string unixSockPrefix string - isUnixSocket bool - con *grpc.ClientConn - client protocol.UIClient - configWatcher *fsnotify.Watcher - - isConnected chan bool - alertsChan chan protocol.Alert - streamNotifications protocol.UI_NotificationsClient //isAsking is set to true if the client is awaiting a decision from the GUI - isAsking bool + isAsking bool + isUnixSocket bool + + sync.RWMutex } // NewClient creates and configures a new client. diff --git a/daemon/ui/config/config.go b/daemon/ui/config/config.go index 2645612b..44a2f6de 100644 --- a/daemon/ui/config/config.go +++ b/daemon/ui/config/config.go @@ -20,11 +20,10 @@ type ( ServerKey string `json:"ServerKey"` ClientCert string `json:"ClientCert"` ClientKey string `json:"ClientKey"` - // https://pkg.go.dev/crypto/tls#Config - SkipVerify bool `json:"SkipVerify"` // https://pkg.go.dev/crypto/tls#ClientAuthType ClientAuthType string `json:"ClientAuthType"` - + // https://pkg.go.dev/crypto/tls#Config + SkipVerify bool `json:"SkipVerify"` // https://pkg.go.dev/crypto/tls#Conn.VerifyHostname // VerifyHostname bool // https://pkg.go.dev/crypto/tls#example-Config-VerifyConnection @@ -64,20 +63,21 @@ type ( // Config holds the values loaded from configFile type Config struct { - sync.RWMutex - Server serverConfig `json:"Server"` - Stats statistics.StatsConfig `json:"Stats"` - Rules rulesOptions `json:"Rules"` - Ebpf ebpfOptions `json:"Ebpf"` + LogLevel *int32 `json:"LogLevel"` FwOptions fwOptions `json:"FwOptions"` + Firewall string `json:"Firewall"` + Ebpf ebpfOptions `json:"Ebpf"` DefaultAction string `json:"DefaultAction"` DefaultDuration string `json:"DefaultDuration"` ProcMonitorMethod string `json:"ProcMonitorMethod"` - Firewall string `json:"Firewall"` - LogLevel *int32 `json:"LogLevel"` - InterceptUnknown bool `json:"InterceptUnknown"` - LogUTC bool `json:"LogUTC"` - LogMicro bool `json:"LogMicro"` + Server serverConfig `json:"Server"` + Rules rulesOptions `json:"Rules"` + Stats statistics.StatsConfig `json:"Stats"` + sync.RWMutex + + InterceptUnknown bool `json:"InterceptUnknown"` + LogUTC bool `json:"LogUTC"` + LogMicro bool `json:"LogMicro"` } // Parse determines if the given configuration is ok.