diff --git a/packetbeat/config/config.go b/packetbeat/config/config.go index 1c40aa8226e..46f0ba4ff43 100644 --- a/packetbeat/config/config.go +++ b/packetbeat/config/config.go @@ -36,17 +36,18 @@ type Config struct { } type InterfacesConfig struct { - Device string `config:"device"` - Type string `config:"type"` - File string `config:"file"` - WithVlans bool `config:"with_vlans"` - BpfFilter string `config:"bpf_filter"` - Snaplen int `config:"snaplen"` - BufferSizeMb int `config:"buffer_size_mb"` - TopSpeed bool - Dumpfile string - OneAtATime bool - Loop int + Device string `config:"device"` + Type string `config:"type"` + File string `config:"file"` + WithVlans bool `config:"with_vlans"` + BpfFilter string `config:"bpf_filter"` + Snaplen int `config:"snaplen"` + BufferSizeMb int `config:"buffer_size_mb"` + EnableAutoPromiscMode bool `config:"auto_promisc_mode"` + TopSpeed bool + Dumpfile string + OneAtATime bool + Loop int } type Flows struct { diff --git a/packetbeat/docs/packetbeat-options.asciidoc b/packetbeat/docs/packetbeat-options.asciidoc index 09922d62923..a53219ea28d 100644 --- a/packetbeat/docs/packetbeat-options.asciidoc +++ b/packetbeat/docs/packetbeat-options.asciidoc @@ -176,6 +176,24 @@ packetbeat.interfaces.type: af_packet packetbeat.interfaces.buffer_size_mb: 100 ------------------------------------------------------------------------------ +[float] +==== `auto_promisc_mode` + +With `auto_promisc_mode` Packetbeat puts interface in promiscuous mode automatically on startup. +This option does not work with `any` interface device. +The default option is false and requires manual set-up of promiscuous mode. + +Example: + +[source,yaml] +------------------------------------------------------------------------------ +packetbeat.interfaces.device: eth0 +packetbeat.interfaces.type: af_packet +packetbeat.interfaces.buffer_size_mb: 100 +packetbeat.interfaces.auto_promisc_mode: true +------------------------------------------------------------------------------ + + [float] ==== `with_vlans` diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 410d56139a1..43eeaa91552 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -40,6 +40,11 @@ packetbeat.interfaces.device: any # Use this setting to override the automatically generated BPF filter. #packetbeat.interfaces.bpf_filter: +# With `auto_promisc_mode` Packetbeat puts interface in promiscuous mode automatically on startup. +# This option does not work with `any` interface device. +# The default option is false and requires manual set-up of promiscuous mode. +#packetbeat.interfaces.auto_promisc_mode: true + #================================== Flows ===================================== packetbeat.flows: diff --git a/packetbeat/sniffer/afpacket_linux.go b/packetbeat/sniffer/afpacket_linux.go index 15ca387d454..d377543c417 100644 --- a/packetbeat/sniffer/afpacket_linux.go +++ b/packetbeat/sniffer/afpacket_linux.go @@ -40,21 +40,28 @@ type afpacketHandle struct { } func newAfpacketHandle(device string, snaplen int, block_size int, num_blocks int, - timeout time.Duration) (*afpacketHandle, error) { + timeout time.Duration, autoPromiscMode bool) (*afpacketHandle, error) { - promiscEnabled, err := isPromiscEnabled(device) - if err != nil { - logp.Err("Failed to get promiscuous mode for device '%s': %v", device, err) + var err error + var promiscEnabled bool + + if autoPromiscMode { + promiscEnabled, err = isPromiscEnabled(device) + if err != nil { + logp.Err("Failed to get promiscuous mode for device '%s': %v", device, err) + } + + if !promiscEnabled { + if setPromiscErr := setPromiscMode(device, true); setPromiscErr != nil { + logp.Warn("Failed to set promiscuous mode for device '%s'. Packetbeat may be unable to see any network traffic. Please follow packetbeat FAQ to learn about mitigation: Error: %v", device, err) + } + } } h := &afpacketHandle{ promiscPreviousState: promiscEnabled, device: device, - promiscPreviousStateDetected: err == nil, - } - - if err := setPromiscMode(device, true); err != nil { - logp.Warn("Failed to set promiscuous mode for device '%s'. Packetbeat may be unable to see any network traffic. Please follow packetbeat FAQ to learn about mitigation: Error: %v", device, err) + promiscPreviousStateDetected: autoPromiscMode && err != nil, } if device == "any" { @@ -89,6 +96,7 @@ func (h *afpacketHandle) LinkType() layers.LinkType { func (h *afpacketHandle) Close() { h.TPacket.Close() + // previous state detected only if auto mode was on if h.promiscPreviousStateDetected { if err := setPromiscMode(h.device, h.promiscPreviousState); err != nil { logp.Warn("Failed to reset promiscuous mode for device '%s'. Your device might be in promiscuous mode.: %v", h.device, err) @@ -122,6 +130,9 @@ func isPromiscEnabled(device string) (bool, error) { return ifreq.flags&uint16(syscall.IFF_PROMISC) != 0, nil } +// setPromiscMode enables promisc mode if configured. +// this makes maintenance for user simpler without any additional manual steps +// issue [700](https://github.com/elastic/beats/issues/700) func setPromiscMode(device string, enabled bool) error { if device == "any" { logp.Warn("Cannot set promiscuous mode to device 'any'") diff --git a/packetbeat/sniffer/afpacket_nonlinux.go b/packetbeat/sniffer/afpacket_nonlinux.go index 2daa64520bf..7d1e423c40d 100644 --- a/packetbeat/sniffer/afpacket_nonlinux.go +++ b/packetbeat/sniffer/afpacket_nonlinux.go @@ -31,7 +31,7 @@ type afpacketHandle struct { } func newAfpacketHandle(device string, snaplen int, blockSize int, numBlocks int, - timeout time.Duration) (*afpacketHandle, error) { + timeout time.Duration, enableAutoPromiscMode bool) (*afpacketHandle, error) { return nil, fmt.Errorf("Afpacket MMAP sniffing is only available on Linux") } diff --git a/packetbeat/sniffer/sniffer.go b/packetbeat/sniffer/sniffer.go index 714d2c46d31..d38101c4b20 100644 --- a/packetbeat/sniffer/sniffer.go +++ b/packetbeat/sniffer/sniffer.go @@ -305,7 +305,7 @@ func openAFPacket(filter string, cfg *config.InterfacesConfig) (snifferHandle, e } timeout := 500 * time.Millisecond - h, err := newAfpacketHandle(cfg.Device, szFrame, szBlock, numBlocks, timeout) + h, err := newAfpacketHandle(cfg.Device, szFrame, szBlock, numBlocks, timeout, cfg.EnableAutoPromiscMode) if err != nil { return nil, err } diff --git a/packetbeat/tests/system/config/packetbeat.yml.j2 b/packetbeat/tests/system/config/packetbeat.yml.j2 index 394ef449840..2715634e4e5 100644 --- a/packetbeat/tests/system/config/packetbeat.yml.j2 +++ b/packetbeat/tests/system/config/packetbeat.yml.j2 @@ -7,6 +7,7 @@ packetbeat.interfaces.device: {{ iface_device|default("any") }} {% if af_packet %} packetbeat.interfaces.type: af_packet packetbeat.interfaces.buffer_size_mb: 100 +packetbeat.interfaces.auto_promisc_mode: true {% endif %} {% if bpf_filter %}