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-1754 Add flow filter capability to filter on TCP flags #367

Merged
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
2 changes: 1 addition & 1 deletion bpf/flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) {
id.direction = direction;

// check if this packet need to be filtered if filtering feature is enabled
bool skip = check_and_do_flow_filtering(&id);
bool skip = check_and_do_flow_filtering(&id, pkt.flags);
if (skip) {
return TC_ACT_OK;
}
Expand Down
21 changes: 17 additions & 4 deletions bpf/flows_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ static __always_inline int is_equal_ip(u8 *ip1, u8 *ip2, u8 len) {
}

static __always_inline int do_flow_filter_lookup(flow_id *id, struct filter_key_t *key,
filter_action *action, u8 len, u8 offset) {
filter_action *action, u8 len, u8 offset,
u16 flags) {
int result = 0;

struct filter_value_t *rule = (struct filter_value_t *)bpf_map_lookup_elem(&filter_map, key);
Expand Down Expand Up @@ -115,6 +116,18 @@ static __always_inline int do_flow_filter_lookup(flow_id *id, struct filter_key_
goto end;
}
}
// for TCP only check TCP flags if its set
if (id->transport_protocol == IPPROTO_TCP) {
if (rule->tcpFlags != 0) {
if (rule->tcpFlags == flags) {
BPF_PRINTK("tcpFlags matched\n");
result++;
} else {
result = 0;
goto end;
}
}
}
break;
case IPPROTO_ICMP:
case IPPROTO_ICMPV6:
Expand Down Expand Up @@ -210,7 +223,7 @@ static __always_inline int flow_filter_setup_lookup_key(flow_id *id, struct filt
/*
* check if the flow match filter rule and return >= 1 if the flow is to be dropped
*/
static __always_inline int is_flow_filtered(flow_id *id, filter_action *action) {
static __always_inline int is_flow_filtered(flow_id *id, filter_action *action, u16 flags) {
struct filter_key_t key;
u8 len, offset;
int result = 0;
Expand All @@ -224,7 +237,7 @@ static __always_inline int is_flow_filtered(flow_id *id, filter_action *action)
return result;
}

result = do_flow_filter_lookup(id, &key, action, len, offset);
result = do_flow_filter_lookup(id, &key, action, len, offset, flags);
// we have a match so return
if (result > 0) {
return result;
Expand All @@ -236,7 +249,7 @@ static __always_inline int is_flow_filtered(flow_id *id, filter_action *action)
return result;
}

return do_flow_filter_lookup(id, &key, action, len, offset);
return do_flow_filter_lookup(id, &key, action, len, offset, flags);
}

#endif //__FLOWS_FILTER_H__
2 changes: 1 addition & 1 deletion bpf/pca.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static inline bool validate_pca_filter(struct __sk_buff *skb, direction dir) {
id.direction = dir;

// check if this packet need to be filtered if filtering feature is enabled
bool skip = check_and_do_flow_filtering(&id);
bool skip = check_and_do_flow_filtering(&id, pkt.flags);
if (skip) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion bpf/pkt_drops.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static inline int trace_pkt_drop(void *ctx, u8 state, struct sk_buff *skb,
}

// check if this packet need to be filtered if filtering feature is enabled
bool skip = check_and_do_flow_filtering(&id);
bool skip = check_and_do_flow_filtering(&id, flags);
if (skip) {
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion bpf/rtt_tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static inline int calculate_flow_rtt_tcp(struct sock *sk, struct sk_buff *skb) {
rtt *= 1000u;

// check if this packet need to be filtered if filtering feature is enabled
bool skip = check_and_do_flow_filtering(&id);
bool skip = check_and_do_flow_filtering(&id, flags);
if (skip) {
return 0;
}
Expand Down
29 changes: 17 additions & 12 deletions bpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@
#define SUBMIT 0

// Flags according to RFC 9293 & https://www.iana.org/assignments/ipfix/ipfix.xhtml
#define FIN_FLAG 0x01
#define SYN_FLAG 0x02
#define RST_FLAG 0x04
#define PSH_FLAG 0x08
#define ACK_FLAG 0x10
#define URG_FLAG 0x20
#define ECE_FLAG 0x40
#define CWR_FLAG 0x80
// Custom flags exported
#define SYN_ACK_FLAG 0x100
#define FIN_ACK_FLAG 0x200
#define RST_ACK_FLAG 0x400
typedef enum tcp_flags_t {
FIN_FLAG = 0x01,
SYN_FLAG = 0x02,
RST_FLAG = 0x04,
PSH_FLAG = 0x08,
ACK_FLAG = 0x10,
URG_FLAG = 0x20,
ECE_FLAG = 0x40,
CWR_FLAG = 0x80,
// Custom flags exported
SYN_ACK_FLAG = 0x100,
FIN_ACK_FLAG = 0x200,
RST_ACK_FLAG = 0x400,
} tcp_flags;
// Force emitting enum tcp_flags_t into the ELF.
const enum tcp_flags_t *unused10 __attribute__((unused));

#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Expand Down Expand Up @@ -216,6 +220,7 @@ struct filter_value_t {
u8 icmpCode;
direction direction;
filter_action action;
tcp_flags tcpFlags;
u8 ip[IP_MAX_LEN];
} __attribute__((packed));
// Force emitting struct filter_value_t into the ELF.
Expand Down
4 changes: 2 additions & 2 deletions bpf/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,13 @@ static inline long pkt_drop_lookup_and_update_flow(struct sk_buff *skb, flow_id
/*
* check if flow filter is enabled and if we need to continue processing the packet or not
*/
static inline bool check_and_do_flow_filtering(flow_id *id) {
static inline bool check_and_do_flow_filtering(flow_id *id, u16 flags) {
// check if this packet need to be filtered if filtering feature is enabled
if (enable_flows_filtering || enable_pca) {
filter_action action = ACCEPT;
u32 *filter_counter_p = NULL;
u32 initVal = 1, key = 0;
if (is_flow_filtered(id, &action) != 0 && action != MAX_FILTER_ACTIONS) {
if (is_flow_filtered(id, &action, flags) != 0 && action != MAX_FILTER_ACTIONS) {
// we have matching rules follow through the actions to decide if we should accept or reject the flow
// and update global counter for both cases
u32 reject_key = FILTER_REJECT_KEY, accept_key = FILTER_ACCEPT_KEY;
Expand Down
5 changes: 3 additions & 2 deletions docs/flow_filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ Rule-base filtering is a method to control the flow of packets cached in the eBP
- `FILTER_SOURCE_PORT_RANGE` - Source port range of the flow filter rule. using "80-100" format.
- `FILTER_DESTINATION_PORT` - Single Destination port of the flow filter rule.
- `FILTER_DESTINATION_PORT_RANGE` - Destination port range of the flow filter rule. using "80-100" format.
- `FILTER_PORT` - Single L4 port of the flow filter rule, can be either source or destination port.
- `FILTER_PORT_RANGE` - L4 port range of the flow filter rule. using "80-100" format can be either source or destination ports range.
- `FILTER_PORT` - Single L4 port of the flow filter rule can be either source or destination port.
- `FILTER_PORT_RANGE` - L4 port range of the flow filter rule. using "80100" format can be either a source or destination ports range.
- `FILTER_ICMP_TYPE` - ICMP type of the flow filter rule.
- `FILTER_ICMP_CODE` - ICMP code of the flow filter rule.
- `FILTER_PEER_IP` - Specific Peer IP address of the flow filter rule.
- `FILTER_TCP_FLAGS` - Filter based on TCP flags Possible values are SYN, SYN-ACK, ACK, FIN, RST, PSH, URG, ECE, CWR, FIN-ACK, RST_ACK

Note:
- for L4 ports configuration, you can use either single port config options or the range but not both.
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) {
FilterDestinationPort: ebpf.ConvertFilterPortsToInstr(cfg.FilterDestinationPort, cfg.FilterDestinationPortRange),
FilterSourcePort: ebpf.ConvertFilterPortsToInstr(cfg.FilterSourcePort, cfg.FilterSourcePortRange),
FilterPort: ebpf.ConvertFilterPortsToInstr(cfg.FilterPort, cfg.FilterPortRange),
FilterTCPFLags: cfg.FilterTCPFlags,
},
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ type Config struct {
// FilterAction is the action to filter flows.
// Possible values are "Accept" or "Reject".
FilterAction string `env:"FILTER_ACTION" envDefault:"Accept"`
// FilterTCPFlags is the TCP flags to filter flows.
// possible values are: SYN, SYN-ACK, ACK, FIN, RST, PSH, URG, ECE, CWR, FIN-ACK, RST-ACK
FilterTCPFlags string `env:"FILTER_TCP_FLAGS"`

/* Deprecated configs are listed below this line
* See manageDeprecatedConfigs function for details
Expand Down
17 changes: 17 additions & 0 deletions pkg/ebpf/bpf_arm64_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_arm64_bpfel.o
Binary file not shown.
17 changes: 17 additions & 0 deletions pkg/ebpf/bpf_powerpc_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_powerpc_bpfel.o
Binary file not shown.
17 changes: 17 additions & 0 deletions pkg/ebpf/bpf_s390_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_s390_bpfeb.o
Binary file not shown.
17 changes: 17 additions & 0 deletions pkg/ebpf/bpf_x86_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_x86_bpfel.o
Binary file not shown.
28 changes: 28 additions & 0 deletions pkg/ebpf/flow_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type FilterConfig struct {
FilterIcmpCode int
FilterPeerIP string
FilterAction string
FilterTCPFLags string
}

type Filter struct {
Expand Down Expand Up @@ -77,6 +78,7 @@ func (f *Filter) getFilterKey(config *FilterConfig) (BpfFilterKeyT, error) {
return key, nil
}

// nolint:cyclop
func (f *Filter) getFilterValue(config *FilterConfig) (BpfFilterValueT, error) {
val := BpfFilterValueT{}

Expand Down Expand Up @@ -132,6 +134,32 @@ func (f *Filter) getFilterValue(config *FilterConfig) (BpfFilterValueT, error) {
copy(val.Ip[:], ip.To16())
}
}

switch config.FilterTCPFLags {
case "SYN":
val.TcpFlags = BpfTcpFlagsTSYN_FLAG
case "SYN-ACK":
val.TcpFlags = BpfTcpFlagsTSYN_ACK_FLAG
case "ACK":
val.TcpFlags = BpfTcpFlagsTACK_FLAG
case "FIN":
val.TcpFlags = BpfTcpFlagsTFIN_FLAG
case "RST":
val.TcpFlags = BpfTcpFlagsTRST_FLAG
case "PUSH":
val.TcpFlags = BpfTcpFlagsTPSH_FLAG
case "URG":
val.TcpFlags = BpfTcpFlagsTURG_FLAG
case "ECE":
val.TcpFlags = BpfTcpFlagsTECE_FLAG
case "CWR":
val.TcpFlags = BpfTcpFlagsTCWR_FLAG
case "FIN-ACK":
val.TcpFlags = BpfTcpFlagsTFIN_ACK_FLAG
case "RST-ACK":
val.TcpFlags = BpfTcpFlagsTRST_ACK_FLAG
}

return val, nil
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
)

// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
//go:generate bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -target amd64,arm64,ppc64le,s390x -type flow_metrics_t -type flow_id_t -type flow_record_t -type pkt_drops_t -type dns_record_t -type global_counters_key_t -type direction_t -type filter_action_t Bpf ../../bpf/flows.c -- -I../../bpf/headers
//go:generate bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -target amd64,arm64,ppc64le,s390x -type flow_metrics_t -type flow_id_t -type flow_record_t -type pkt_drops_t -type dns_record_t -type global_counters_key_t -type direction_t -type filter_action_t -type tcp_flags_t Bpf ../../bpf/flows.c -- -I../../bpf/headers

const (
qdiscType = "clsact"
Expand Down
Loading