Skip to content

Commit

Permalink
configurable promisc mode
Browse files Browse the repository at this point in the history
  • Loading branch information
michalpristas committed Apr 8, 2019
1 parent 93e48ac commit 23d5948
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 22 deletions.
23 changes: 12 additions & 11 deletions packetbeat/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
18 changes: 18 additions & 0 deletions packetbeat/docs/packetbeat-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
5 changes: 5 additions & 0 deletions packetbeat/packetbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
29 changes: 20 additions & 9 deletions packetbeat/sniffer/afpacket_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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'")
Expand Down
2 changes: 1 addition & 1 deletion packetbeat/sniffer/afpacket_nonlinux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
2 changes: 1 addition & 1 deletion packetbeat/sniffer/sniffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
1 change: 1 addition & 0 deletions packetbeat/tests/system/config/packetbeat.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down

0 comments on commit 23d5948

Please sign in to comment.