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

NETOBSERV-1890: decode TCP flags (new stage/rule) #747

Merged
merged 2 commits into from
Nov 26, 2024
Merged
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
4 changes: 4 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ Following is the supported API format for network transformations:
add_kubernetes_infra: add output kubernetes isInfra field from input
reinterpret_direction: reinterpret flow direction at the node level (instead of net interface), to ease the deduplication process
add_subnet_label: categorize IPs based on known subnets configuration
decode_tcp_flags: decode bitwise TCP flags into a string
kubernetes_infra: Kubernetes infra rule configuration
namespaceNameFields: entries for namespace and name input fields
name: name of the object
Expand Down Expand Up @@ -272,6 +273,9 @@ Following is the supported API format for network transformations:
input: entry input field
output: entry output field
protocol: entry protocol field
decode_tcp_flags: Decode bitwise TCP flags into a string
input: entry input field
output: entry output field
kubeConfig: global configuration related to Kubernetes (optional)
configPath: path to kubeconfig file (optional)
secondaryNetworks: configuration for secondary networks
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/transform_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const (
NetworkAddKubernetesInfra TransformNetworkOperationEnum = "add_kubernetes_infra" // add output kubernetes isInfra field from input
NetworkReinterpretDirection TransformNetworkOperationEnum = "reinterpret_direction" // reinterpret flow direction at the node level (instead of net interface), to ease the deduplication process
NetworkAddSubnetLabel TransformNetworkOperationEnum = "add_subnet_label" // categorize IPs based on known subnets configuration
NetworkDecodeTCPFlags TransformNetworkOperationEnum = "decode_tcp_flags" // decode bitwise TCP flags into a string
)

type NetworkTransformRule struct {
Expand All @@ -69,6 +70,7 @@ type NetworkTransformRule struct {
AddLocation *NetworkGenericRule `yaml:"add_location,omitempty" json:"add_location,omitempty" doc:"Add location rule configuration"`
AddSubnetLabel *NetworkAddSubnetLabelRule `yaml:"add_subnet_label,omitempty" json:"add_subnet_label,omitempty" doc:"Add subnet label rule configuration"`
AddService *NetworkAddServiceRule `yaml:"add_service,omitempty" json:"add_service,omitempty" doc:"Add service rule configuration"`
DecodeTCPFlags *NetworkGenericRule `yaml:"decode_tcp_flags,omitempty" json:"decode_tcp_flags,omitempty" doc:"Decode bitwise TCP flags into a string"`
}

type K8sInfraRule struct {
Expand Down
10 changes: 9 additions & 1 deletion pkg/pipeline/transform/transform_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ func (n *Network) Transform(inputEntry config.GenericMap) (config.GenericMap, bo
}
}
}
case api.NetworkDecodeTCPFlags:
if anyFlags, ok := outputEntry[rule.DecodeTCPFlags.Input]; ok && anyFlags != nil {
if flags, ok := anyFlags.(uint16); ok {
flags := util.DecodeTCPFlags(flags)
outputEntry[rule.DecodeTCPFlags.Output] = flags
}
}

default:
log.Panicf("unknown type %s for transform.Network rule: %v", rule.Type, rule)
Expand Down Expand Up @@ -194,7 +201,8 @@ func NewTransformNetwork(params config.StageParam, opMetrics *operational.Metric
if len(jsonNetworkTransform.SubnetLabels) == 0 {
return nil, fmt.Errorf("a rule '%s' was found, but there are no subnet labels configured", api.NetworkAddSubnetLabel)
}
case api.NetworkAddSubnet:
case api.NetworkAddSubnet, api.NetworkDecodeTCPFlags:
// nothing
}
}

Expand Down
30 changes: 30 additions & 0 deletions pkg/utils/tcp_flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package utils

type tcpFlag struct {
value uint16
name string
}

var tcpFlags = []tcpFlag{
{value: 1, name: "FIN"},
{value: 2, name: "SYN"},
{value: 4, name: "RST"},
{value: 8, name: "PSH"},
{value: 16, name: "ACK"},
{value: 32, name: "URG"},
{value: 64, name: "ECE"},
{value: 128, name: "CWR"},
{value: 256, name: "SYN_ACK"},
{value: 512, name: "FIN_ACK"},
{value: 1024, name: "RST_ACK"},
}

func DecodeTCPFlags(bitfield uint16) []string {
var values []string
for _, flag := range tcpFlags {
if bitfield&flag.value != 0 {
values = append(values, flag.name)
}
}
return values
}
18 changes: 18 additions & 0 deletions pkg/utils/tcp_flags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package utils

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestDecodeFlags(t *testing.T) {
flags528 := DecodeTCPFlags(528)
assert.Equal(t, []string{"ACK", "FIN_ACK"}, flags528)

flags256 := DecodeTCPFlags(256)
assert.Equal(t, []string{"SYN_ACK"}, flags256)

flags666 := DecodeTCPFlags(666)
assert.Equal(t, []string{"SYN", "PSH", "ACK", "CWR", "FIN_ACK"}, flags666)
}
Loading