diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 478edebc5a4..2c84fa59eeb 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -116,20 +116,18 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Change cloud.provider from googlecloud to gcp. {pull}21775[21775] - API address and shard ID are required settings in the Cloud Foundry module. {pull}21759[21759] - Rename googlecloud module to gcp module. {pull}22246[22246] +- Fix ECS compliance of user.id field in system/users metricset {pull}19019[19019] - Use ingress/egress instead of inbound/outbound for system/socket metricset. {pull}22992[22992] - -*Packetbeat* - -- Redis: fix incorrectly handle with two-words redis command. {issue}14872[14872] {pull}14873[14873] -- `event.category` no longer contains the value `network_traffic` because this is not a valid ECS event category value. {pull}20556[20556] - Add new dashboard for VSphere host cluster and virtual machine {pull}14135[14135] - kubernetes.container.cpu.limit.cores and kubernetes.container.cpu.requests.cores are now floats. {issue}11975[11975] -- Fix ECS compliance of user.id field in system/users metricset {pull}19019[19019] *Packetbeat* +- Redis: fix incorrectly handle with two-words redis command. {issue}14872[14872] {pull}14873[14873] +- `event.category` no longer contains the value `network_traffic` because this is not a valid ECS event category value. {pull}20556[20556] - Added redact_headers configuration option, to allow HTTP request headers to be redacted whilst keeping the header field included in the beat. {pull}15353[15353] - Add dns.question.subdomain and dns.question.top_level_domain fields. {pull}14578[14578] +- Update how Packetbeat classifies network directionality to bring it in line with ECS 1.7 {pull}22996[22996] *Winlogbeat* diff --git a/packetbeat/_meta/config/beat.reference.yml.tmpl b/packetbeat/_meta/config/beat.reference.yml.tmpl index 5ccc9bf5a92..77a1de3c876 100644 --- a/packetbeat/_meta/config/beat.reference.yml.tmpl +++ b/packetbeat/_meta/config/beat.reference.yml.tmpl @@ -13,6 +13,16 @@ # keyword to sniff on all connected interfaces. packetbeat.interfaces.device: {{ call .device .GOOS }} +# The network CIDR blocks that are considered "internal" networks for +# the purpose of network perimeter boundary classification. The valid +# values for internal_networks are the same as those that can be used +# with processor network conditions. +# +# For a list of available values see: +# https://www.elastic.co/guide/en/beats/packetbeat/current/defining-processors.html#condition-network +packetbeat.interfaces.internal_networks: + - private + # Packetbeat supports three sniffer types: # * pcap, which uses the libpcap library and works on most platforms, but it's # not the fastest option. diff --git a/packetbeat/_meta/config/beat.yml.tmpl b/packetbeat/_meta/config/beat.yml.tmpl index c5f9cfc0c23..c1ad53bf9e9 100644 --- a/packetbeat/_meta/config/beat.yml.tmpl +++ b/packetbeat/_meta/config/beat.yml.tmpl @@ -13,6 +13,16 @@ # "any" keyword to sniff on all connected interfaces. packetbeat.interfaces.device: {{ call .device .GOOS }} +# The network CIDR blocks that are considered "internal" networks for +# the purpose of network perimeter boundary classification. The valid +# values for internal_networks are the same as those that can be used +# with processor network conditions. +# +# For a list of available values see: +# https://www.elastic.co/guide/en/beats/packetbeat/current/defining-processors.html#condition-network +packetbeat.interfaces.internal_networks: + - private + {{header "Flows"}} # Set `enabled: false` or comment out all options to disable flows reporting. diff --git a/packetbeat/beater/processor.go b/packetbeat/beater/processor.go index d6aafbb1a7f..a228c90ba09 100644 --- a/packetbeat/beater/processor.go +++ b/packetbeat/beater/processor.go @@ -118,6 +118,7 @@ func (p *processorFactory) Create(pipeline beat.PipelineConnector, cfg *common.C p.beat.Publisher, config.IgnoreOutgoing, config.Interfaces.File == "", + config.Interfaces.InternalNetworks, ) if err != nil { return nil, err diff --git a/packetbeat/config/config.go b/packetbeat/config/config.go index 9d3818d4aa4..173e507fc40 100644 --- a/packetbeat/config/config.go +++ b/packetbeat/config/config.go @@ -75,14 +75,15 @@ func (c Config) ICMP() (*common.Config, error) { } 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"` - EnableAutoPromiscMode bool `config:"auto_promisc_mode"` + 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"` + InternalNetworks []string `config:"internal_networks"` TopSpeed bool Dumpfile string OneAtATime bool diff --git a/packetbeat/docs/packetbeat-options.asciidoc b/packetbeat/docs/packetbeat-options.asciidoc index d3777c594c4..6c062187494 100644 --- a/packetbeat/docs/packetbeat-options.asciidoc +++ b/packetbeat/docs/packetbeat-options.asciidoc @@ -270,6 +270,16 @@ see the following published transactions (when `ignore_outgoing` is true): - Beat2: t1 - Beat3: t2 + [float] +==== `internal_networks` + +If the `internal_networks` option is specified, when monitoring network taps or mirror ports, Packetbeat +will attempt to classify the network directionality of traffic not intended for this host as it +relates to a network perimeter. Any CIDR block specified in `internal_networks` is treated internal to +the perimeter, and any IP address falling outside of these CIDR blocks is considered external. + +This is useful when Packetbeat is running on an appliance that sits at a network boundary such as +a firewall or VPN. Note that this only affects how the directionality of network traffic is classified. [[configuration-flows]] == Configure flows to monitor network traffic diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 76ecadf4a2c..c811a8f0c04 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -13,6 +13,16 @@ # keyword to sniff on all connected interfaces. packetbeat.interfaces.device: any +# The network CIDR blocks that are considered "internal" networks for +# the purpose of network perimeter boundary classification. The valid +# values for internal_networks are the same as those that can be used +# with processor network conditions. +# +# For a list of available values see: +# https://www.elastic.co/guide/en/beats/packetbeat/current/defining-processors.html#condition-network +packetbeat.interfaces.internal_networks: + - private + # Packetbeat supports three sniffer types: # * pcap, which uses the libpcap library and works on most platforms, but it's # not the fastest option. diff --git a/packetbeat/packetbeat.yml b/packetbeat/packetbeat.yml index 102ba0fb045..2ac9186d43e 100644 --- a/packetbeat/packetbeat.yml +++ b/packetbeat/packetbeat.yml @@ -13,6 +13,16 @@ # "any" keyword to sniff on all connected interfaces. packetbeat.interfaces.device: any +# The network CIDR blocks that are considered "internal" networks for +# the purpose of network perimeter boundary classification. The valid +# values for internal_networks are the same as those that can be used +# with processor network conditions. +# +# For a list of available values see: +# https://www.elastic.co/guide/en/beats/packetbeat/current/defining-processors.html#condition-network +packetbeat.interfaces.internal_networks: + - private + # =================================== Flows ==================================== # Set `enabled: false` or comment out all options to disable flows reporting. diff --git a/packetbeat/pb/event.go b/packetbeat/pb/event.go index cd652756f3e..cf86ab27a16 100644 --- a/packetbeat/pb/event.go +++ b/packetbeat/pb/event.go @@ -29,6 +29,7 @@ import ( "github.com/elastic/beats/v7/libbeat/beat" "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/common/flowhash" + "github.com/elastic/beats/v7/libbeat/conditions" "github.com/elastic/ecs/code/go/ecs" ) @@ -42,6 +43,10 @@ const ( Inbound = "inbound" Outbound = "outbound" Internal = "internal" + External = "external" + Egress = "egress" + Ingress = "ingress" + Unknown = "unknown" ) // Fields contains common fields used in Packetbeat events. Protocol @@ -216,7 +221,7 @@ func makeProcess(p *common.Process) *ecs.Process { } // ComputeValues computes derived values like network.bytes and writes them to f. -func (f *Fields) ComputeValues(localIPs []net.IP) error { +func (f *Fields) ComputeValues(localIPs []net.IP, internalNetworks []string) error { var flow flowhash.Flow // network.bytes @@ -266,27 +271,16 @@ func (f *Fields) ComputeValues(localIPs []net.IP) error { } // network.direction - if len(localIPs) > 0 && f.Network.Direction == "" { - if flow.SourceIP != nil { - for _, ip := range localIPs { - if flow.SourceIP.Equal(ip) { - f.Network.Direction = Outbound - break - } - } - } - if flow.DestinationIP != nil { - for _, ip := range localIPs { - if flow.DestinationIP.Equal(ip) { - if f.Network.Direction == Outbound { - f.Network.Direction = Internal - } else { - f.Network.Direction = Inbound - } - break - } + if f.Network.Direction == "" { + direction := hostBasedDirection(flow.SourceIP, flow.DestinationIP, localIPs) + if len(internalNetworks) > 0 && direction == Unknown { + var err error + direction, err = perimeterBasedDirection(flow.SourceIP, flow.DestinationIP, internalNetworks) + if err != nil { + return err } } + f.Network.Direction = direction } // process (dest process will take priority) @@ -323,6 +317,51 @@ func (f *Fields) ComputeValues(localIPs []net.IP) error { return nil } +func hostBasedDirection(source, destination net.IP, ips []net.IP) string { + if destination != nil { + if destination.IsLoopback() || destination.IsLinkLocalUnicast() || destination.IsLinkLocalMulticast() { + return Ingress + } + for _, ip := range ips { + if destination.Equal(ip) { + return Ingress + } + } + } + if source != nil { + if source.IsLoopback() || source.IsLinkLocalUnicast() || source.IsLinkLocalMulticast() { + return Egress + } + for _, ip := range ips { + if source.Equal(ip) { + return Egress + } + } + } + return Unknown +} + +func perimeterBasedDirection(source, destination net.IP, internalNetworks []string) (string, error) { + sourceInternal, err := conditions.NetworkContains(source, internalNetworks...) + if err != nil { + return Unknown, err + } + destinationInternal, err := conditions.NetworkContains(destination, internalNetworks...) + if err != nil { + return Unknown, err + } + if sourceInternal && destinationInternal { + return Internal, nil + } + if sourceInternal { + return Outbound, nil + } + if destinationInternal { + return Inbound, nil + } + return External, nil +} + // MarshalMapStr marshals the fields into MapStr. It returns an error if there // is a problem writing the keys to the given map (like if an intermediate key // exists and is not a map). diff --git a/packetbeat/pb/event_test.go b/packetbeat/pb/event_test.go index 5722d6d9faa..c1347ed25a4 100644 --- a/packetbeat/pb/event_test.go +++ b/packetbeat/pb/event_test.go @@ -57,7 +57,7 @@ func TestComputeValues(t *testing.T) { localAddrs := []net.IP{net.ParseIP("127.0.0.1")} - if err := f.ComputeValues(localAddrs); err != nil { + if err := f.ComputeValues(localAddrs, nil); err != nil { t.Fatal(err) } @@ -66,7 +66,7 @@ func TestComputeValues(t *testing.T) { assert.EqualValues(t, f.Network.Bytes, 300) assert.NotZero(t, f.Network.CommunityID) assert.Equal(t, f.Network.Type, "ipv4") - assert.Equal(t, f.Network.Direction, "outbound") + assert.Equal(t, f.Network.Direction, "ingress") } func TestIsEmptyValue(t *testing.T) { diff --git a/packetbeat/protos/amqp/amqp_test.go b/packetbeat/protos/amqp/amqp_test.go index 19002b60941..725de0f3d11 100644 --- a/packetbeat/protos/amqp/amqp_test.go +++ b/packetbeat/protos/amqp/amqp_test.go @@ -38,7 +38,7 @@ type eventStore struct { } func (e *eventStore) publish(event beat.Event) { - publish.MarshalPacketbeatFields(&event, nil) + publish.MarshalPacketbeatFields(&event, nil, nil) e.events = append(e.events, event) } diff --git a/packetbeat/protos/dhcpv4/dhcpv4_test.go b/packetbeat/protos/dhcpv4/dhcpv4_test.go index e695ecf00cf..0b07ab88ea2 100644 --- a/packetbeat/protos/dhcpv4/dhcpv4_test.go +++ b/packetbeat/protos/dhcpv4/dhcpv4_test.go @@ -126,6 +126,7 @@ func TestParseDHCPRequest(t *testing.T) { }, "network": common.MapStr{ "type": "ipv4", + "direction": "unknown", "transport": "udp", "protocol": "dhcpv4", "bytes": 272, @@ -159,7 +160,7 @@ func TestParseDHCPRequest(t *testing.T) { actual := p.parseDHCPv4(pkt) if assert.NotNil(t, actual) { - publish.MarshalPacketbeatFields(actual, nil) + publish.MarshalPacketbeatFields(actual, nil, nil) t.Logf("DHCP event: %+v", actual) assertEqual(t, expected, *actual) } @@ -210,6 +211,7 @@ func TestParseDHCPACK(t *testing.T) { }, "network": common.MapStr{ "type": "ipv4", + "direction": "unknown", "transport": "udp", "protocol": "dhcpv4", "bytes": 300, @@ -241,7 +243,7 @@ func TestParseDHCPACK(t *testing.T) { actual := p.parseDHCPv4(pkt) if assert.NotNil(t, actual) { - publish.MarshalPacketbeatFields(actual, nil) + publish.MarshalPacketbeatFields(actual, nil, nil) t.Logf("DHCP event: %+v", actual) assertEqual(t, expected, *actual) } diff --git a/packetbeat/protos/dns/dns_test.go b/packetbeat/protos/dns/dns_test.go index 17303783fca..3b87ecb2e72 100644 --- a/packetbeat/protos/dns/dns_test.go +++ b/packetbeat/protos/dns/dns_test.go @@ -82,7 +82,7 @@ type eventStore struct { } func (e *eventStore) publish(event beat.Event) { - publish.MarshalPacketbeatFields(&event, nil) + publish.MarshalPacketbeatFields(&event, nil, nil) e.events = append(e.events, event) } diff --git a/packetbeat/protos/http/http_test.go b/packetbeat/protos/http/http_test.go index 53f55214851..0fcf94a3f39 100644 --- a/packetbeat/protos/http/http_test.go +++ b/packetbeat/protos/http/http_test.go @@ -51,7 +51,7 @@ type eventStore struct { } func (e *eventStore) publish(event beat.Event) { - publish.MarshalPacketbeatFields(&event, nil) + publish.MarshalPacketbeatFields(&event, nil, nil) e.events = append(e.events, event) } diff --git a/packetbeat/protos/mysql/mysql_test.go b/packetbeat/protos/mysql/mysql_test.go index 4e9123c5617..a188fd1a3aa 100644 --- a/packetbeat/protos/mysql/mysql_test.go +++ b/packetbeat/protos/mysql/mysql_test.go @@ -44,7 +44,7 @@ type eventStore struct { } func (e *eventStore) publish(event beat.Event) { - publish.MarshalPacketbeatFields(&event, nil) + publish.MarshalPacketbeatFields(&event, nil, nil) e.events = append(e.events, event) } diff --git a/packetbeat/protos/pgsql/pgsql_test.go b/packetbeat/protos/pgsql/pgsql_test.go index 737f2905a91..99acf54e15c 100644 --- a/packetbeat/protos/pgsql/pgsql_test.go +++ b/packetbeat/protos/pgsql/pgsql_test.go @@ -41,7 +41,7 @@ type eventStore struct { } func (e *eventStore) publish(event beat.Event) { - publish.MarshalPacketbeatFields(&event, nil) + publish.MarshalPacketbeatFields(&event, nil, nil) e.events = append(e.events, event) } diff --git a/packetbeat/protos/tls/tls_test.go b/packetbeat/protos/tls/tls_test.go index 90aadb07a95..d384be4aad9 100644 --- a/packetbeat/protos/tls/tls_test.go +++ b/packetbeat/protos/tls/tls_test.go @@ -40,7 +40,7 @@ type eventStore struct { } const ( - expectedClientHello = `{"client":{"ip":"192.168.0.1","port":6512},"destination":{"domain":"example.org","ip":"192.168.0.2","port":27017},"event":{"category":["network"],"dataset":"tls","kind":"event","type":["connection","protocol"]},"network":{"community_id":"1:jKfewJN/czjTuEpVvsKdYXXiMzs=","protocol":"tls","transport":"tcp","type":"ipv4"},"related":{"ip":["192.168.0.1","192.168.0.2"]},"server":{"domain":"example.org","ip":"192.168.0.2","port":27017},"source":{"ip":"192.168.0.1","port":6512},"status":"Error","tls":{"client":{"ja3":"94c485bca29d5392be53f2b8cf7f4304","server_name":"example.org","supported_ciphers":["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_AES_128_GCM_SHA256","TLS_RSA_WITH_AES_256_GCM_SHA384","TLS_RSA_WITH_AES_128_CBC_SHA","TLS_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_3DES_EDE_CBC_SHA"]},"detailed":{"client_certificate_requested":false,"client_hello":{"extensions":{"_unparsed_":["renegotiation_info","23","status_request","18","30032"],"application_layer_protocol_negotiation":["h2","http/1.1"],"ec_points_formats":["uncompressed"],"server_name_indication":["example.org"],"session_ticket":"","signature_algorithms":["ecdsa_secp256r1_sha256","rsa_pss_sha256","rsa_pkcs1_sha256","ecdsa_secp384r1_sha384","rsa_pss_sha384","rsa_pkcs1_sha384","rsa_pss_sha512","rsa_pkcs1_sha512","rsa_pkcs1_sha1"],"supported_groups":["x25519","secp256r1","secp384r1"]},"supported_compression_methods":["NULL"],"version":"3.3"},"version":"TLS 1.2"},"established":false,"resumed":false,"version":"1.2","version_protocol":"tls"},"type":"tls"}` + expectedClientHello = `{"client":{"ip":"192.168.0.1","port":6512},"destination":{"domain":"example.org","ip":"192.168.0.2","port":27017},"event":{"category":["network"],"dataset":"tls","kind":"event","type":["connection","protocol"]},"network":{"community_id":"1:jKfewJN/czjTuEpVvsKdYXXiMzs=","direction":"unknown","protocol":"tls","transport":"tcp","type":"ipv4"},"related":{"ip":["192.168.0.1","192.168.0.2"]},"server":{"domain":"example.org","ip":"192.168.0.2","port":27017},"source":{"ip":"192.168.0.1","port":6512},"status":"Error","tls":{"client":{"ja3":"94c485bca29d5392be53f2b8cf7f4304","server_name":"example.org","supported_ciphers":["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_AES_128_GCM_SHA256","TLS_RSA_WITH_AES_256_GCM_SHA384","TLS_RSA_WITH_AES_128_CBC_SHA","TLS_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_3DES_EDE_CBC_SHA"]},"detailed":{"client_certificate_requested":false,"client_hello":{"extensions":{"_unparsed_":["renegotiation_info","23","status_request","18","30032"],"application_layer_protocol_negotiation":["h2","http/1.1"],"ec_points_formats":["uncompressed"],"server_name_indication":["example.org"],"session_ticket":"","signature_algorithms":["ecdsa_secp256r1_sha256","rsa_pss_sha256","rsa_pkcs1_sha256","ecdsa_secp384r1_sha384","rsa_pss_sha384","rsa_pkcs1_sha384","rsa_pss_sha512","rsa_pkcs1_sha512","rsa_pkcs1_sha1"],"supported_groups":["x25519","secp256r1","secp384r1"]},"supported_compression_methods":["NULL"],"version":"3.3"},"version":"TLS 1.2"},"established":false,"resumed":false,"version":"1.2","version_protocol":"tls"},"type":"tls"}` expectedServerHello = `{"extensions":{"_unparsed_":["renegotiation_info","status_request"],"application_layer_protocol_negotiation":["h2"],"ec_points_formats":["uncompressed","ansiX962_compressed_prime","ansiX962_compressed_char2"],"session_ticket":""},"selected_compression_method":"NULL","version":"3.3"}` rawClientHello = "16030100c2010000be03033367dfae0d46ec0651e49cca2ae47317e8989df710" + "ee7570a88b9a7d5d56b3af00001c3a3ac02bc02fc02cc030cca9cca8c013c014" + @@ -57,7 +57,7 @@ const ( ) func (e *eventStore) publish(event beat.Event) { - publish.MarshalPacketbeatFields(&event, nil) + publish.MarshalPacketbeatFields(&event, nil, nil) e.events = append(e.events, event) } diff --git a/packetbeat/publish/publish.go b/packetbeat/publish/publish.go index bd904030b59..d968bbcc0d8 100644 --- a/packetbeat/publish/publish.go +++ b/packetbeat/publish/publish.go @@ -37,9 +37,10 @@ type TransactionPublisher struct { } type transProcessor struct { - ignoreOutgoing bool - localIPs []net.IP // TODO: Periodically update this list. - name string + ignoreOutgoing bool + localIPs []net.IP // TODO: Periodically update this list. + internalNetworks []string + name string } var debugf = logp.MakeDebug("publish") @@ -49,6 +50,7 @@ func NewTransactionPublisher( pipeline beat.Pipeline, ignoreOutgoing bool, canDrop bool, + internalNetworks []string, ) (*TransactionPublisher, error) { addrs, err := common.LocalIPAddrs() if err != nil { @@ -66,9 +68,10 @@ func NewTransactionPublisher( pipeline: pipeline, canDrop: canDrop, processor: transProcessor{ - localIPs: localIPs, - name: name, - ignoreOutgoing: ignoreOutgoing, + localIPs: localIPs, + internalNetworks: internalNetworks, + name: name, + ignoreOutgoing: ignoreOutgoing, }, } return p, nil @@ -150,13 +153,13 @@ func (p *transProcessor) Run(event *beat.Event) (*beat.Event, error) { return nil, nil } - fields, err := MarshalPacketbeatFields(event, p.localIPs) + fields, err := MarshalPacketbeatFields(event, p.localIPs, p.internalNetworks) if err != nil { return nil, err } if fields != nil { - if p.ignoreOutgoing && fields.Network.Direction == "outbound" { + if p.ignoreOutgoing && fields.Network.Direction == pb.Egress { debugf("Ignore outbound transaction on: %s -> %s", fields.Source.IP, fields.Destination.IP) return nil, nil @@ -195,7 +198,7 @@ func validateEvent(event *beat.Event) error { // MarshalPacketbeatFields marshals data contained in the _packetbeat field // into the event and removes the _packetbeat key. -func MarshalPacketbeatFields(event *beat.Event, localIPs []net.IP) (*pb.Fields, error) { +func MarshalPacketbeatFields(event *beat.Event, localIPs []net.IP, internalNetworks []string) (*pb.Fields, error) { defer delete(event.Fields, pb.FieldsKey) fields, err := pb.GetFields(event.Fields) @@ -203,7 +206,7 @@ func MarshalPacketbeatFields(event *beat.Event, localIPs []net.IP) (*pb.Fields, return nil, err } - if err = fields.ComputeValues(localIPs); err != nil { + if err = fields.ComputeValues(localIPs, internalNetworks); err != nil { return nil, err } diff --git a/packetbeat/publish/publish_test.go b/packetbeat/publish/publish_test.go index 711758187b0..9b802bdb2d7 100644 --- a/packetbeat/publish/publish_test.go +++ b/packetbeat/publish/publish_test.go @@ -125,7 +125,7 @@ func TestPublish(t *testing.T) { } dir, _ := res.GetValue("network.direction") - assert.Equal(t, "inbound", dir) + assert.Equal(t, "ingress", dir) }) t.Run("direction/outbound", func(t *testing.T) { @@ -140,7 +140,7 @@ func TestPublish(t *testing.T) { } dir, _ := res.GetValue("network.direction") - assert.Equal(t, "outbound", dir) + assert.Equal(t, "egress", dir) }) t.Run("direction/internal", func(t *testing.T) { @@ -155,7 +155,7 @@ func TestPublish(t *testing.T) { } dir, _ := res.GetValue("network.direction") - assert.Equal(t, "internal", dir) + assert.Equal(t, "ingress", dir) }) t.Run("direction/none", func(t *testing.T) { @@ -170,7 +170,7 @@ func TestPublish(t *testing.T) { } dir, _ := res.GetValue("network.direction") - assert.Nil(t, dir) + assert.Equal(t, "unknown", dir) }) t.Run("ignore_outgoing", func(t *testing.T) { diff --git a/packetbeat/tests/system/config/packetbeat.yml.j2 b/packetbeat/tests/system/config/packetbeat.yml.j2 index cee36a769d9..0eca011cf33 100644 --- a/packetbeat/tests/system/config/packetbeat.yml.j2 +++ b/packetbeat/tests/system/config/packetbeat.yml.j2 @@ -3,6 +3,8 @@ # Select the network interfaces to sniff the data. You can use the "any" # keyword to sniff on all connected interfaces. packetbeat.interfaces.device: {{ iface_device|default("any") }} +packetbeat.interfaces.internal_networks: + - private {% if af_packet %} packetbeat.interfaces.type: af_packet diff --git a/x-pack/packetbeat/packetbeat.reference.yml b/x-pack/packetbeat/packetbeat.reference.yml index 76ecadf4a2c..c811a8f0c04 100644 --- a/x-pack/packetbeat/packetbeat.reference.yml +++ b/x-pack/packetbeat/packetbeat.reference.yml @@ -13,6 +13,16 @@ # keyword to sniff on all connected interfaces. packetbeat.interfaces.device: any +# The network CIDR blocks that are considered "internal" networks for +# the purpose of network perimeter boundary classification. The valid +# values for internal_networks are the same as those that can be used +# with processor network conditions. +# +# For a list of available values see: +# https://www.elastic.co/guide/en/beats/packetbeat/current/defining-processors.html#condition-network +packetbeat.interfaces.internal_networks: + - private + # Packetbeat supports three sniffer types: # * pcap, which uses the libpcap library and works on most platforms, but it's # not the fastest option. diff --git a/x-pack/packetbeat/packetbeat.yml b/x-pack/packetbeat/packetbeat.yml index 102ba0fb045..2ac9186d43e 100644 --- a/x-pack/packetbeat/packetbeat.yml +++ b/x-pack/packetbeat/packetbeat.yml @@ -13,6 +13,16 @@ # "any" keyword to sniff on all connected interfaces. packetbeat.interfaces.device: any +# The network CIDR blocks that are considered "internal" networks for +# the purpose of network perimeter boundary classification. The valid +# values for internal_networks are the same as those that can be used +# with processor network conditions. +# +# For a list of available values see: +# https://www.elastic.co/guide/en/beats/packetbeat/current/defining-processors.html#condition-network +packetbeat.interfaces.internal_networks: + - private + # =================================== Flows ==================================== # Set `enabled: false` or comment out all options to disable flows reporting.