|
| 1 | +--- |
| 2 | +layout: :theme/post |
| 3 | +title: "Enhancing NetObserv By Introducing Multi Rules Flow filtering capability in eBPF" |
| 4 | +description: NetObserv eBPF Flows Filtering |
| 5 | +tags: eBPF,Monitoring,Troubleshooting |
| 6 | +authors: [msherif1234] |
| 7 | +--- |
| 8 | + |
| 9 | +# Flow Filtering in eBPF: Optimizing Resource Usage by Selecting Critical Flows |
| 10 | + |
| 11 | +## Introduction |
| 12 | + |
| 13 | +In high-traffic environments, processing every network flow can be resource-intensive, |
| 14 | +leading to CPU overload and excessive memory usage. |
| 15 | +eBPF-based flow filtering solves this challenge by selecting only important flows, |
| 16 | +reducing system strain while maintaining visibility. |
| 17 | + |
| 18 | +## Why Flow Filtering |
| 19 | + |
| 20 | +The primary goal of flow filtering is resource efficiency. |
| 21 | +Instead of capturing and analyzing every flow, filtering mechanisms allow us to: |
| 22 | + |
| 23 | +✅ Reduce CPU & Memory Overhead – Process only relevant traffic, avoiding unnecessary computation. |
| 24 | + |
| 25 | +✅ Optimize Storage Usage – Store only meaningful flow records, reducing disk and database load. |
| 26 | + |
| 27 | +✅ Enhance Performance – Minimize packet processing latency and improve system responsiveness. |
| 28 | + |
| 29 | +✅ Focus on Critical Traffic – Prioritize important flows for security, compliance, and performance monitoring. |
| 30 | + |
| 31 | +## How Flow Filtering Works in eBPF |
| 32 | + |
| 33 | +eBPF allows filtering flows at the source, avoiding costly user-space processing. This typically involves: |
| 34 | + |
| 35 | +1- Defining Filtering Rules – Specify criteria such as source/destination IP, port, protocol, |
| 36 | +or application metadata. |
| 37 | +The following table shows all possible filtering options and their default setting: |
| 38 | + |
| 39 | +| Option | Description | Possible values | Default | |
| 40 | +|-------------|----------------------------------------------------------|-------------------------------------------------------------------------|-----------| |
| 41 | +| enable | Enable flow filter | true, false | false | |
| 42 | +| action | Action to apply on the flow | Accept, Reject | Accept | |
| 43 | +| cidr | CIDR to match on the flow | for example 1.1.1.0/24 or 1::100/64 or 0.0.0.0/0 | 0.0.0.0/0 | |
| 44 | +| protocol | Protocol to match on the flow | TCP, UDP, SCTP, ICMP, ICMPv6 | | |
| 45 | +| direction | Direction to match on the flow | Ingress, Egress | | |
| 46 | +| destPorts | Possible options for destination port settings | | | |
| 47 | +| | Single port to match on the flow | for example 80 or 443 or 49051 | | |
| 48 | +| | Range of ports to match on the flow or | for example 80-100 | | |
| 49 | +| | Two ports to match on | for example 80,100 | | |
| 50 | +| sourcePorts | Possible options for source port settings | | | |
| 51 | +| | Single port to match on the flow | for example 80 or 443 or 49051 | | |
| 52 | +| | Range of ports to match on the flow or | for example 80-100 | | |
| 53 | +| | Two ports to match on | for example 80,100 | | |
| 54 | +| ports | Possible options for destination or source port settings | | | |
| 55 | +| | Single port to match on the flow | for example 80 or 443 or 49051 | | |
| 56 | +| | Range of ports to match on the flow or | for example 80-100 | | |
| 57 | +| | Two ports to match on | for example 80,100 | | |
| 58 | +| icmpType | ICMP type to match on the flow | for example 8 or 13 | | |
| 59 | +| icmpCode | ICMP code to match on the flow | for example 0 or 1 | | |
| 60 | +| peerIP | Peer IP to match on the flow | for example 1.1.1.1 or 1::1 | | |
| 61 | +| peerCIDR | Peer IP CIDR to match on the flow | for example 1.1.1.1/24 or 1::1/48 | | |
| 62 | +| pktDrops | filter flows with packets drop | true, false | | |
| 63 | +| sampling | sampling rate to use for filtered flows | for example 10 or 20 (any value >= 1) | | |
| 64 | +| tcpFlags | TCP flags to filter flows by | "SYN";"SYN-ACK";"ACK";"FIN";"RST";"URG";"ECE";"CWR";"FIN-ACK";"RST-ACK" | | |
| 65 | + |
| 66 | +<p style="text-align: center">Table 1: eBPF flow filtering configuration options </p> |
| 67 | + |
| 68 | +Note: |
| 69 | + |
| 70 | +- A rule cannot include both `ports` and either `sourcePorts` or `destPorts` simultaneously. |
| 71 | +- The number of eBPF flow filter rules is capped at `16` to maintain efficient memory usage when this feature is enabled. |
| 72 | +- Validation webhook rejects rules containing duplicate CIDRs. |
| 73 | +- Supports both `IPv4` and `IPv6` formats. |
| 74 | +- If users wish to match any CIDR, the default `0.0.0.0/0` (Null CIDR) can be used. |
| 75 | + |
| 76 | +The example below demonstrates various filtering options using multi-rule filters: |
| 77 | + |
| 78 | +```yaml |
| 79 | +agent: |
| 80 | + type: eBPF |
| 81 | + ebpf: |
| 82 | + flowFilter: |
| 83 | + enable: true |
| 84 | + rules: |
| 85 | + - action: Accept |
| 86 | + cidr: 10.128.0.0/24 |
| 87 | + peerCIDR: 10.129.0.0/24 |
| 88 | + ports: '443,6443' |
| 89 | + protocol: TCP |
| 90 | + sampling: 10 |
| 91 | + - action: Accept |
| 92 | + cidr: 10.129.0.1/24 |
| 93 | + ports: 53 |
| 94 | + protocol: UDP |
| 95 | + sampling: 20 |
| 96 | + - action: Reject |
| 97 | + tcpFlags: SYN |
| 98 | + cidr: 10.130.0.0/24 |
| 99 | + protocol: TCP |
| 100 | + sourcePorts: 80-100 |
| 101 | + - action: Accept |
| 102 | + cidr: 172.30.0.0/16 |
| 103 | + protocol: SCTP |
| 104 | + pktDrops: true |
| 105 | + - action: Reject |
| 106 | + cidr: 8.8.8.8/32 |
| 107 | + protocol: ICMP |
| 108 | + icmpType: 8 // ICMP Echo request packet |
| 109 | +``` |
| 110 | +
|
| 111 | +2- Packet Inspection – Extract relevant packet attributes within an eBPF program. |
| 112 | +
|
| 113 | +3- Early Flow Filtering – |
| 114 | +Skip or Allow packets based on predefined conditions before doing further ebpf packets processing. |
| 115 | +The Following Diagram shows how eBPF filtering is done |
| 116 | +
|
| 117 | +<img src="{page.image('ebpf-flow-filtering/ebpf-flow-filtering.png')}" alt="eBPF Flow Filtering Packet Processing"> |
| 118 | +<p style="text-align: center">Figure 1: eBPF Flow Filtering Packet Processing</p> |
| 119 | +
|
| 120 | +eBPF flow filtering uses a specific map type called `BPF_MAP_TYPE_LPM_TRIE`, which enables prefix-based matching. |
| 121 | +For more details on LPM maps, refer to [BPF_MAP_TYPE_LPM_TRIE](https://docs.ebpf.io/linux/map-type/BPF_MAP_TYPE_LPM_TRIE/). |
| 122 | + |
| 123 | +When a packet traverses the eBPF stack, its `srcIP` undergoes a longest prefix match lookup in the `filter_map`. |
| 124 | +If a specific rule matches, the packet is further evaluated against additional fields, |
| 125 | +potentially triggering another longest prefix match for `dstIP` |
| 126 | +in the `peer_filter_map` only if peer IP filtering is enabled. |
| 127 | +Once all matching criteria are met, the corresponding filter rule action is executed—either |
| 128 | +allowing the flow or rejecting it—while updating global flow filtering metrics for debugging purposes. |
| 129 | + |
| 130 | +This process is then repeated with `dstIP` as the primary lookup key in the `filter_map`. If peer IP filtering is enabled, |
| 131 | +`srcIP` is checked against the `peer_filter_map`. If a match is found, |
| 132 | +the rule’s action is executed, and relevant statistics are updated. |
| 133 | + |
| 134 | +When the `sampling` configuration is specified in a flow filter rule, |
| 135 | +the matching flows will use this sampling rate, overriding the rate |
| 136 | +configured in the `flowcollector` object. |
| 137 | + |
| 138 | +The dual matching approach ensures bidirectional flow tracking, enabling users to correlate and monitor both |
| 139 | +directions of a given flow. |
| 140 | + |
| 141 | +In cases where no matching rules exist, the default behavior is to reject the flow. |
| 142 | +However, users can customize the handling of unmatched flows by adding a catch-all entry |
| 143 | +`(cidr: 0.0.0.0/0)` and specifying a global action to enforce their preferred policy. |
| 144 | + |
| 145 | +## Key Use Cases |
| 146 | + |
| 147 | +🚀 Reducing Observability Overhead – Avoid logging irrelevant flows in high-traffic Kubernetes clusters. |
| 148 | + |
| 149 | +🔐 Security Filtering – Focus on anomalous or suspicious traffic while ignoring normal flows. |
| 150 | + |
| 151 | +🌐 Network Performance Monitoring – Capture only high-latency or dropped-packet flows for troubleshooting. |
| 152 | + |
| 153 | +### Filter EastWest and NorthSouth flows |
| 154 | + |
| 155 | +Given a cluster with Services subnet on `172.30.0.0/16` and Pods subnet on `10.128.0.0/16` and `10.129.0.0/16`, |
| 156 | +we can set specific sampling rates and filters to keep and sample exactly what we want. |
| 157 | +For instance, allow traffic to service IP `172.30.100.64:80` with a sampling rate of `10`. |
| 158 | +Permit communication between pods in the `10.128.0.0/16` and `10.129.0.0/16` subnets with a sampling rate of `20`. |
| 159 | +Also Allow pods within the `10.128.0.0/14` subnet attempt to ping an external IP `8.8.8.8`, |
| 160 | +this flow should be allowed with a sampling rate of `30`. |
| 161 | +Reject all other traffic `default action` |
| 162 | + |
| 163 | +```yaml |
| 164 | +agent: |
| 165 | + type: eBPF |
| 166 | + ebpf: |
| 167 | + flowFilter: |
| 168 | + enable: true |
| 169 | + rules: |
| 170 | + - action: Accept |
| 171 | + cidr: 172.30.0.0/16 |
| 172 | + peerCIDR: 10.128.0.0/14 |
| 173 | + sampling: 10 |
| 174 | + - action: Accept |
| 175 | + cidr: 10.128.0.0/14 |
| 176 | + peerCIDR: 10.128.0.0/14 |
| 177 | + sampling: 20 |
| 178 | + - action: Accept |
| 179 | + cidr: 8.8.8.8/32 |
| 180 | + sampling: 30 |
| 181 | + peerCIDR: 10.128.0.0/14 |
| 182 | + protocol: ICMP |
| 183 | + icmpType: 8 |
| 184 | +``` |
| 185 | + |
| 186 | +<img src="{page.image('ebpf-flow-filtering/ebpf-svc-and-pods-flows.png')}" alt="eBPF Flow Filtering Kubernetes NorthSouth and EastWest Flows"> |
| 187 | +<p style="text-align: center">Figure 2: eBPF Flow Filtering Kubernetes NorthSouth and EastWest Flows</p> |
| 188 | + |
| 189 | +### Filter flows with packet drops |
| 190 | + |
| 191 | +Let's filter Kubernetes service flows that include a packet drop and discard all others. |
| 192 | +For this use case, the `PacketDrop` feature must be enabled with eBPF in `privileged` mode, |
| 193 | +as demonstrated in the configuration below. |
| 194 | + |
| 195 | +```yaml |
| 196 | +agent: |
| 197 | + type: eBPF |
| 198 | + ebpf: |
| 199 | + privileged: true |
| 200 | + features: |
| 201 | + - PacketDrop |
| 202 | + flowFilter: |
| 203 | + enable: true |
| 204 | + rules: |
| 205 | + - action: Accept |
| 206 | + cidr: 172.30.0.0/16 |
| 207 | + pktDrops: true |
| 208 | + - action: Reject |
| 209 | + cidr: 0.0.0.0/0 |
| 210 | +``` |
| 211 | + |
| 212 | +<img src="{page.image('ebpf-flow-filtering/ebpf-filter-svc-pkt-drops.png')}" alt="eBPF Flow Filtering Kubernetes Services with Packet Drop"> |
| 213 | +<p style="text-align: center">Figure 3: eBPF Flow Filtering Kubernetes Services with Packet Drop</p> |
| 214 | + |
| 215 | +### Filter TCP flows using TCP Flags |
| 216 | + |
| 217 | +Filtering based on TCP flags is an effective method to detect and mitigate TCP SYN flood attacks in a cluster. |
| 218 | +A SYN flood is a Denial-of-Service (DoS) attack where an attacker overwhelms a target system by sending a large |
| 219 | +number of SYN packets without completing the three-way handshake, |
| 220 | +depleting system resources and disrupting legitimate connections. |
| 221 | + |
| 222 | +```yaml |
| 223 | +agent: |
| 224 | + type: eBPF |
| 225 | + ebpf: |
| 226 | + flowFilter: |
| 227 | + enable: true |
| 228 | + rules: |
| 229 | + - action: Accept |
| 230 | + cidr: 0.0.0.0/0 |
| 231 | + protocol: TCP |
| 232 | + tcpFlags: SYN |
| 233 | + sampling: 1 |
| 234 | +``` |
| 235 | + |
| 236 | +<img src="{page.image('ebpf-flow-filtering/ebpf-filter-with-tcpflags.png')}" alt="eBPF Flow Filtering TCP flows using TCP flags"> |
| 237 | +<p style="text-align: center">Figure 4: eBPF Flow Filtering TCP flows using TCP flags</p> |
| 238 | + |
| 239 | +### Filter DNS query over ports 53 and 5353 for both TCP and UDP |
| 240 | + |
| 241 | +This Use case involves capturing DNS flows over both `TCP` and `UDP`, |
| 242 | +with the option to enable the `DNSTracking` feature for enhanced DNS latency insights. |
| 243 | + |
| 244 | +```yaml |
| 245 | +agent: |
| 246 | + type: eBPF |
| 247 | + ebpf: |
| 248 | + features: |
| 249 | + - DNSTracking |
| 250 | + flowFilter: |
| 251 | + enable: true |
| 252 | + rules: |
| 253 | + - action: Accept |
| 254 | + cidr: 0.0.0.0/0 |
| 255 | + sourcePorts: '53,5353' |
| 256 | + sampling: 1 |
| 257 | +``` |
| 258 | + |
| 259 | +<img src="{page.image('ebpf-flow-filtering/ebpf-filter-DNS-flows.png')}" alt="eBPF Flow Filtering DNS flows"> |
| 260 | +<p style="text-align: center">Figure 5: eBPF Flow Filtering DNS flows</p> |
| 261 | + |
| 262 | +## Conclusion |
| 263 | + |
| 264 | +By filtering flows at the kernel level with eBPF, we maximize efficiency, |
| 265 | +ensuring only the most relevant data is processed and stored. |
| 266 | +This approach is critical for scalability, cost reduction, and real-time network insights. |
| 267 | + |
| 268 | +## Feedback |
| 269 | + |
| 270 | +We hope you liked this article! |
| 271 | +Netobserv is an open source project [available on github](https://github.com/netobserv). |
| 272 | +Feel free to share your [ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a). |
0 commit comments