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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(event): create net_flow_tcp_begin event #3750

Merged
merged 5 commits into from Dec 18, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions .revive.toml
Expand Up @@ -69,8 +69,7 @@ enableAllRules = true
[rule.flag-parameter]
Disabled = true
[rule.function-result-limit]
Disabled = false
Arguments = [3]
Disabled = true
[rule.function-length]
Disabled = true
[rule.get-return]
Expand Down
64 changes: 64 additions & 0 deletions docs/docs/events/builtin/extra/net_tcp_connect.md
@@ -0,0 +1,64 @@

# NetTCPConnect

## Intro

NetTCPConnect - An event that monitors the `connect()` system call, providing
detailed information about destination addresses including DNS resolutions.

## Description

`NetTCPConnect` is a high-level event derived from the underlying
`security_socket_connect` LSM (Linux Security Module) hook. This event is
triggered whenever the `connect()` system call is invoked in the system,
capturing attempts by sockets to establish a connection.

Unlike direct kernel probes, this LSM-based approach is not susceptible to
Time-Of-Check to Time-Of-Use (TOCTOU) race conditions, making it a reliable
source for monitoring socket connections.

## Arguments

1. **dstIP** (`string`): The destination IP address to which the socket is attempting to connect. 2. **dstPort** (`int`): The port number at the destination.
3. **results** (`[]string`): DNS resolutions made to the destination IP, providing contextual information about the connection attempt.

## Origin

### Derived from `security_socket_connect`

#### Source

This event is derived from the `security_socket_connect` LSM hook. The LSM
framework provides a way to track and control various aspects of system
behavior, and `security_socket_connect` specifically monitors socket connection
attempts.

#### Purpose

The purpose of deriving `NetTCPConnect` from `security_socket_connect` is to
provide a more user-friendly and context-enriched view of socket connection
attempts. This includes not only the basic connection details but also DNS
resolution information, offering a comprehensive overview of network activities
for security monitoring.

## Example Use Case

`NetTCPConnect` can be used by security applications to monitor and log all
outbound connection attempts in a system. It is particularly useful for
detecting unusual network patterns or connections to suspicious endpoints,
playing a crucial role in intrusion detection and network behavior analysis.

## Issues

While `NetTCPConnect` offers detailed information about connection attempts,
it's important to consider the volume of data generated, especially in systems
with high network activity. Efficient data handling and analysis are key to
leveraging the full potential of this event without overwhelming system
resources or analysts.

## Related Events

* `net_flow_tcp_begin` - similar event, based on network packet flows.
* `security_socket_connect`

> This document was automatically generated by OpenAI and reviewed by a Human.
70 changes: 70 additions & 0 deletions docs/docs/events/builtin/network/net_flow_tcp_begin.md
@@ -0,0 +1,70 @@

# NetFlowTCPBegin

## Intro

NetFlowTCPBegin - An event derived from a base network raw event, originated
from cgroup skb eBPF programs, specifically designed to monitor the initiation
of TCP flows by analyzing IP and TCP headers data.

## Description

`NetFlowTCPBegin` leverages cgroup skb eBPF programs to capture raw network
events at the kernel level, focusing on the TCP protocol's initiation phase.

This event parses IP and TCP headers, identifying the start of TCP
communication flows based on SYN, ACK, and FIN flag statuses. By concentrating
on these flags, `NetFlowTCPBegin` efficiently discerns the commencement of TCP
connections, providing critical data for network monitoring and security
analysis.

## Arguments

1. **connectionDirection** (`string`): Classifies the connection as 'incoming' or 'outgoing', based on the packet's direction and SYN flag status.
2. **srcIP** (`string`): The source IP address extracted directly from the IP header.
3. **dstIP** (`string`): The destination IP address, ascertained from the IP header.
4. **srcPort** (`uint16`): The source port, derived from the TCP header.
5. **dstPort** (`uint16`): The destination port, obtained from the TCP header.
6. **srcDomains** (`[]string`): Domain names related to the source IP, resolved through DNS cache.
7. **dstDomains** (`[]string`): Domain names associated with the destination IP, also resolved via DNS cache.

## Origin

### Derived from cgroup skb eBPF Programs

#### Source

The `NetFlowTCPBegin` event originates from cgroup skb eBPF programs, which
capture and process raw network packets at the kernel level. This sophisticated
capture mechanism is specifically tailored for dissecting and analyzing TCP
traffic, particularly at the initiation stage of TCP connections.

#### Purpose

The event's primary goal is to provide in-depth visibility into the initiation
of TCP connections. By focusing on SYN/ACK/FIN flags within TCP headers,
`NetFlowTCPBegin` offers an efficient and accurate method for identifying the
start of TCP communication flows, crucial for network security and performance
analysis.

## Example Use Case

Network administrators and security professionals can utilize `NetFlowTCPBegin`
to track the initiation of TCP connections, aiding in the early detection of
unusual traffic patterns or unauthorized communication attempts. This
information is vital for maintaining network integrity and preempting potential
security breaches.

## Issues

Although `NetFlowTCPBegin` is optimized for low overhead, its efficiency
depends on the network traffic volume and the complexity of the TCP flows being
monitored. Proper management and analysis of the generated data are essential
to maximize the benefits of this event without impacting system performance.

## Related Events

* `net_tcp_connect` - similar event, based on the `security_socket_connect` calls.
* `security_socket_connect`

> This document was automatically generated by OpenAI and reviewed by a Human.
68 changes: 68 additions & 0 deletions docs/docs/events/builtin/network/net_flow_tcp_end.md
@@ -0,0 +1,68 @@

# NetFlowTCPEnd

## Intro

NetFlowTCPEnd - An event derived from base network raw event, designed to
monitor the termination of TCP flows. It leverages cgroup skb eBPF programs,
focusing specifically on the TCP protocol's termination phase, and is
instrumental in analyzing IP and TCP headers data to detect the end of TCP
connections.

## Description

`NetFlowTCPEnd` utilizes cgroup skb eBPF programs to intercept and analyze raw
network events at the kernel level, with a particular emphasis on the TCP
protocol's termination phase. It processes IP and TCP headers to pinpoint the
conclusion of TCP communication flows. The event identifies the termination of
TCP connections by analyzing the status of TCP flags, primarily focusing on the
FIN and RST flags.

By examining these flags, `NetFlowTCPEnd` provides valuable insights into the
end of TCP connections, a critical component for comprehensive network
monitoring and security analysis.

## Arguments

1. **connectionDirection** (`string`): Indicates whether the terminated connection was 'incoming' or 'outgoing'.
2. **srcIP** (`string`): The source IP address, extracted from the IP header, from the side terminating the connection.
3. **dstIP** (`string`): The destination IP address, obtained from the IP header, of the side receiving the termination.
4. **srcPort** (`uint16`): The source port number, derived from the TCP header.
5. **dstPort** (`uint16`): The destination port number, ascertained from the TCP header.
6. **srcDomains** (`[]string`): Associated domain names for the source IP, resolved using DNS cache.
7. **dstDomains** (`[]string`): Related domain names for the destination IP, determined through DNS cache.

## Origin

### Derived from cgroup skb eBPF Programs

#### Source

`NetFlowTCPEnd` originates from cgroup skb eBPF programs, enabling the tracing
of raw network packets at the kernel level. This advanced mechanism is adept at
dissecting TCP traffic, particularly focusing on the termination stage of TCP
connections.

#### Purpose

The primary aim of `NetFlowTCPEnd` is to provide detailed visibility into the
termination of TCP connections. By concentrating on FIN and RST flags within TCP
headers, it offers an effective and precise approach to identifying the
conclusion of TCP communication flows, crucial for network security and
performance monitoring.

## Example Use Case

Network administrators and security experts can use `NetFlowTCPEnd` to monitor
the termination of TCP connections. This capability is essential for detecting
unusual traffic patterns, potential security threats, or abrupt end of
communication, which are vital for ensuring network security and efficiency.

## Issues

While `NetFlowTCPEnd` is designed to minimize system overhead, its performance
may vary based on the volume of network traffic and the complexity of monitored
TCP flows. Efficient data management and analysis are key to leveraging the full
potential of this event without affecting system performance adversely.

> This document was automatically generated by OpenAI and reviewed by a Human.
3 changes: 3 additions & 0 deletions mkdocs.yml
Expand Up @@ -68,6 +68,8 @@ nav:
- SysRQ Modification: docs/events/builtin/signatures/system_request_key_config_modification.md
- Network Events:
- Overview: docs/events/builtin/network/index.md
- net_flow_tcp_begin: docs/events/builtin/network/net_flow_tcp_begin.md
- net_flow_tcp_end: docs/events/builtin/network/net_flow_tcp_end.md
- net_packet_ipv4: docs/events/builtin/network/net_packet_ipv4.md
- net_packet_ipv6: docs/events/builtin/network/net_packet_ipv6.md
- net_packet_tcp: docs/events/builtin/network/net_packet_tcp.md
Expand Down Expand Up @@ -95,6 +97,7 @@ nav:
- kallsysm_lookup_name: docs/events/builtin/extra/kallsyms_lookup_name.md
- magic_write: docs/events/builtin/extra/magic_write.md
- mem_prot_alert: docs/events/builtin/extra/mem_prot_alert.md
- net_tcp_connect: docs/events/builtin/extra/net_tcp_connect.md
- process_execute_failed: docs/events/builtin/extra/process_execute_failed.md
- sched_process_exec: docs/events/builtin/extra/sched_process_exec.md
- security_bpf_prog: docs/events/builtin/extra/security_bpf_prog.md
Expand Down
103 changes: 87 additions & 16 deletions pkg/ebpf/c/common/network.h
@@ -1,6 +1,7 @@
#ifndef __COMMON_NETWORK_H__
#define __COMMON_NETWORK_H__

#include "types.h"
#include <vmlinux.h>
#include <vmlinux_flavors.h>

Expand All @@ -17,6 +18,65 @@ typedef union iphdrs_t {
struct ipv6hdr ipv6hdr;
} iphdrs;

// network flow events

typedef struct netflow {
u32 host_pid;
u8 proto;
union {
__u8 u6_addr8[16];
__be16 u6_addr16[8];
__be32 u6_addr32[4];
} src, dst;
u16 srcport;
u16 dstport;
} __attribute__((__packed__)) netflow_t;

#define copy_netflow(flow) \
(netflow_t) { \
.host_pid = flow.host_pid, \
.proto = flow.proto, \
.src = flow.src, \
.dst = flow.dst, \
.srcport = flow.srcport, \
.dstport = flow.dstport, \
}

#define invert_netflow(flow) \
(netflow_t) { \
.host_pid = flow.host_pid, \
.proto = flow.proto, \
.src = flow.dst, \
.dst = flow.src, \
.srcport = flow.dstport, \
.dstport = flow.srcport, \
}

#define flow_unknown 0
#define flow_incoming 1
#define flow_outgoing 2

// TODO: per flow statistics can be added later
typedef struct netflowvalue {
u8 direction; // 0 = flow_unknown, 1 = flow_incoming, 2 = flow_outgoing
NDStrahilevitz marked this conversation as resolved.
Show resolved Hide resolved
u64 last_update; // last time this flow was updated
// u64 bytes; // total bytes sent/received
// u64 packets; // total packets sent/received
// u64 events; // total events sent/received
// u64 last_bytes; // last bytes sent/received
// u64 last_packets; // last packets sent/received
// u64 last_events; // last events sent/received
} __attribute__((__packed__)) netflowvalue_t;

// netflowmap (keep track of network flows)

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 65535); // simultaneous network flows being tracked
__type(key, netflow_t); // the network flow ...
__type(value, netflowvalue_t); // ... linked to flow stats
} netflowmap SEC(".maps"); // relate sockets and tasks

// NOTE: proto header structs need full type in vmlinux.h (for correct skb copy)

typedef union protohdrs_t {
Expand All @@ -42,18 +102,19 @@ typedef enum net_packet {
SUB_NET_PACKET_IP = 1 << 1,
// Layer 4
SUB_NET_PACKET_TCP = 1 << 2,
SUB_NET_PACKET_UDP = 1<<3,
SUB_NET_PACKET_ICMP = 1 <<4,
SUB_NET_PACKET_ICMPV6 = 1<<5,
SUB_NET_PACKET_UDP = 1 << 3,
SUB_NET_PACKET_ICMP = 1 << 4,
SUB_NET_PACKET_ICMPV6 = 1 << 5,
// Layer 7
SUB_NET_PACKET_DNS = 1<< 6,
SUB_NET_PACKET_HTTP = 1<<7,
SUB_NET_PACKET_DNS = 1 << 6,
SUB_NET_PACKET_HTTP = 1 << 7,
} net_packet_t;

typedef struct net_event_contextmd {
u8 submit; // keeping this for a TODO (check should_submit_net_event)
u8 should_flow; // Cache result from should_submit_flow_event
u32 header_size;
u8 captured;
u8 captured; // packet has already been captured
netflow_t flow;
} __attribute__((__packed__)) net_event_contextmd_t;

typedef struct net_event_context {
Expand All @@ -73,8 +134,8 @@ typedef struct net_event_context {
typedef struct {
u64 ts;
u16 ip_csum;
struct in6_addr ip_saddr;
struct in6_addr ip_daddr;
struct in6_addr src;
struct in6_addr dst;
} indexer_t;

typedef struct {
Expand Down Expand Up @@ -152,13 +213,23 @@ struct {

// CONSTANTS

// network retval values
#define family_ipv4 (1 << 0)
#define family_ipv6 (1 << 1)
#define proto_http_req (1 << 2)
#define proto_http_resp (1 << 3)
#define packet_ingress (1 << 4)
#define packet_egress (1 << 5)
// Network return value (retval) codes

// Layer 3 Protocol (since no Layer 2 is available)
#define family_ipv4 (1 << 0)
#define family_ipv6 (1 << 1)
// HTTP Direction (request/response) Flag
#define proto_http_req (1 << 2)
#define proto_http_resp (1 << 3)
// Packet Direction (ingress/egress) Flag
#define packet_ingress (1 << 4)
#define packet_egress (1 << 5)
// Flows (begin/end) Flags per Protocol
#define flow_tcp_begin (1 << 6) // syn+ack flag or first flow packet
#define flow_tcp_end (1 << 7) // fin flag or last flow packet
#define flow_udp_begin (1 << 8) // first flow packet
#define flow_udp_end (1 << 9) // last flow packet
#define flow_src_initiator (1 << 10) // src is the flow initiator

// payload size: full packets, only headers
#define FULL 65536 // 1 << 16
Expand Down