Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suricata ips configurator #60

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 40 additions & 28 deletions pkg/netconf/configurator.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ type (
FirewallConfigurator struct {
CommonConfigurator
EnableDNSProxy bool
EnableIDS bool
EnableIPS bool
}
)

type unitConfiguration struct {
type UnitConfiguration struct {
unit string
templateFile string
constructApplier func(kb KnowledgeBase, v ServiceValidator) (net.Applier, error)
Expand Down Expand Up @@ -96,7 +98,7 @@ func (configurator FirewallConfigurator) Configure() {
kb := configurator.Kb
applyCommonConfiguration(Firewall, kb)

configurator.ConfugureNftables()
configurator.ConfigureNftables()

chrony, err := NewChronyServiceEnabler(configurator.Kb)
if err != nil {
Expand All @@ -109,49 +111,59 @@ func (configurator FirewallConfigurator) Configure() {
}

for _, u := range configurator.getUnits() {
src := mustTmpFile(u.unit)
validatorService := ServiceValidator{src}
nfe, err := u.constructApplier(configurator.Kb, validatorService)

if err != nil {
log.Warnf("failed to deploy %s service : %v", u.unit, err)
}
configurator.ApplySystemdUnit(u)
}

applyAndCleanUp(nfe, u.templateFile, src, path.Join(SystemdUnitPath, u.unit), FileModeSystemd)
configurator.ConfigureSuricataDefaults()
configurator.ConfigureSuricata()
}

if u.enabled {
mustEnableUnit(u.unit)
}
}
func (configurator FirewallConfigurator) ConfigureNftables() {
src := mustTmpFile("nftrules_")
validator := NftablesValidator{src}
applier := NewNftablesConfigApplier(configurator.Kb, validator, configurator.EnableDNSProxy)
applyAndCleanUp(applier, TplNftables, src, "/etc/nftables/rules", FileModeDefault)
}

func (configurator FirewallConfigurator) ConfigureSuricataDefaults() {
src := mustTmpFile("suricata_")
applier, err := NewSuricataDefaultsApplier(kb, src)

applier, err := NewSuricataDefaultsApplier(configurator.Kb, src)
if err != nil {
log.Warnf("failed to configure suricata defaults: %v", err)
}

applyAndCleanUp(applier, tplSuricataDefaults, src, "/etc/default/suricata", FileModeSixFourFour)
}

src = mustTmpFile("suricata.yaml_")
applier, err = NewSuricataConfigApplier(kb, src)

func (configurator FirewallConfigurator) ConfigureSuricata() {
src := mustTmpFile("suricata.yaml_")
applier, err := NewSuricataConfigApplier(configurator.Kb, src, configurator.EnableIDS)
if err != nil {
log.Warnf("failed to configure suricata: %v", err)
}

applyAndCleanUp(applier, TplSuricataConfig, src, "/etc/suricata/suricata.yaml", FileModeSixFourFour)

// update systemd unit file to run suricata in correct mode(IDS/IPS)
configurator.ApplySystemdUnit(GetSystemdUnitConfig(configurator.EnableIPS))
}

func (configurator FirewallConfigurator) ConfugureNftables() {
src := mustTmpFile("nftrules_")
validator := NftablesValidator{src}
applier := NewNftablesConfigApplier(configurator.Kb, validator, configurator.EnableDNSProxy)
applyAndCleanUp(applier, TplNftables, src, "/etc/nftables/rules", FileModeDefault)
func (configurator FirewallConfigurator) ApplySystemdUnit(u UnitConfiguration) {
src := mustTmpFile(u.unit)
validatorService := ServiceValidator{src}
nfe, err := u.constructApplier(configurator.Kb, validatorService)

if err != nil {
log.Warnf("failed to deploy %s service : %v", u.unit, err)
}

applyAndCleanUp(nfe, u.templateFile, src, path.Join(SystemdUnitPath, u.unit), FileModeSystemd)

if u.enabled {
mustEnableUnit(u.unit)
}
}

func (configurator FirewallConfigurator) getUnits() []unitConfiguration {
return []unitConfiguration{
func (configurator FirewallConfigurator) getUnits() []UnitConfiguration {
return []UnitConfiguration{
{
unit: systemdUnitDroptailer,
templateFile: tplDroptailer,
Expand Down
3 changes: 2 additions & 1 deletion pkg/netconf/nftables.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import (
"fmt"

"github.com/metal-stack/metal-go/api/models"
"github.com/metal-stack/metal-networker/pkg/exec"
"inet.af/netaddr"

"github.com/metal-stack/metal-networker/pkg/exec"

"github.com/metal-stack/metal-networker/pkg/net"

mn "github.com/metal-stack/metal-lib/pkg/net"
Expand Down
32 changes: 32 additions & 0 deletions pkg/netconf/suricata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package netconf

import (
"github.com/metal-stack/metal-networker/pkg/net"
)

// tplSuricata is the name of the template for the suricata service.
const tplSuricata = "suricata.service.tpl"

// systemdUnitSuricata is the name of the systemd unit for the suricata.
const systemdUnitSuricata = "suricata.service"

// SuricataData contains the data to render the suricata service template.
type SuricataData struct {
EnableIPS bool
}

// NewSuricataServiceApplier constructs a new instance of this type.
func NewSuricataServiceApplier(kb KnowledgeBase, v net.Validator, enableIPS bool) (net.Applier, error) {
data := SuricataData{EnableIPS: enableIPS}
return net.NewNetworkApplier(data, v, nil), nil
}

func GetSystemdUnitConfig(enableIPS bool) UnitConfiguration {
return UnitConfiguration{
unit: systemdUnitSuricata,
templateFile: tplSuricata,
constructApplier: func(kb KnowledgeBase, v ServiceValidator) (net.Applier, error) {
return NewSuricataServiceApplier(kb, v, enableIPS)
},
}
}
10 changes: 8 additions & 2 deletions pkg/netconf/suricata_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type SuricataConfigData struct {
Comment string
DefaultRouteVrf string
Interface string
EnableIDS bool
}

// SuricataConfigValidator can validate configuration for suricata.
Expand All @@ -22,14 +23,19 @@ type SuricataConfigValidator struct {
}

// NewSuricataConfigApplier constructs a new instance of this type.
func NewSuricataConfigApplier(kb KnowledgeBase, tmpFile string) (net.Applier, error) {
func NewSuricataConfigApplier(kb KnowledgeBase, tmpFile string, enableIDS bool) (net.Applier, error) {
defaultRouteVrf, err := kb.getDefaultRouteVRFName()
if err != nil {
return nil, err
}

i := strings.Replace(defaultRouteVrf, "vrf", "vlan", 1)
data := SuricataConfigData{Comment: versionHeader(kb.Machineuuid), DefaultRouteVrf: defaultRouteVrf, Interface: i}
data := SuricataConfigData{
Comment: versionHeader(kb.Machineuuid),
DefaultRouteVrf: defaultRouteVrf,
Interface: i,
EnableIDS: enableIDS,
}
validator := SuricataConfigValidator{tmpFile}

return net.NewNetworkApplier(data, validator, nil), nil
Expand Down
18 changes: 18 additions & 0 deletions pkg/netconf/tpl/suricata.service.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Suricata Intrusion Detection Service
After=network.target

[Service]
EnvironmentFile=-/etc/default/suricata
ExecStartPre=/bin/rm -f $PIDFILE
{{- if .EnableIPS }}
ExecStart=/usr/bin/suricata -c $SURCONF --pidfile $PIDFILE -q 0
{{- else }}
ExecStart=/usr/bin/suricata -c $SURCONF --pidfile $PIDFILE -i $IFACE
{{- end }}
ExecReload=/bin/kill -USR2 $MAINPID
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
8 changes: 6 additions & 2 deletions pkg/netconf/tpl/suricata_config.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ outputs:

# Extensible Event Format (nicknamed EVE) event log in JSON format
- eve-log:
{{- if .EnableIDS }}
enabled: yes
filetype: regular
filename: eve.json
Expand Down Expand Up @@ -239,8 +240,8 @@ outputs:
# force logging of checksums, available hash functions are md5,
# sha1 and sha256
#force-hash: [md5]
#- drop:
# alerts: yes # log alerts that caused drops
- drop:
alerts: yes # log alerts that caused drops
# flows: all # start or all: 'start' logs only a single drop
# # per flow direction. All logs each dropped pkt.
- smtp:
Expand Down Expand Up @@ -287,6 +288,9 @@ outputs:
# and will include the pktvars, flowvars, flowbits and
# flowints.
#- metadata
{{- else }}
enabled: no
{{- end }}

# deprecated - unified2 alert format for use with Barnyard2
- unified2-alert:
Expand Down