cilium / tetragon

eBPF-based Security Observability and Runtime Enforcement
https://tetragon.io
Apache License 2.0
3.63k stars 360 forks source link

Using rateLimit on tcp_connect calls doesn't have any effect #2486

Open vladimirkus opened 5 months ago

vladimirkus commented 5 months ago

What happened?

I'm trying to use rateLimit on tpc_connect calls, example:

spec:
  kprobes:
  - args:
    - index: 0
      maxData: false
      returnCopy: false
      type: sock
    call: tcp_connect
    return: false
    selectors:
    - matchActions:
      - action: Post
        rateLimit: 1m
        rateLimitScope: process
      matchArgs:
      - index: 0
        operator: NotDPort
        values:
        - "9910"
        - "9911"
    syscall: false

I wrote a small python program that opens and closes sockets:

import socket
import time

# Function to open and close a TCP socket in an infinite loop for a set duration
def open_and_close_socket(host, port, duration):
    start_time = time.time()
    while time.time() - start_time < duration:
        try:
            # Create a socket object
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                # Connect to the given host and port
                s.connect((host, port))
                print(f"Connected to {host}:{port}")

        except Exception as e:
            print(f"An error occurred: {e}")

        finally:
            # Close the socket
            s.close()
            print(f"Disconnected from {host}:{port}")

        # Short delay to prevent overwhelming the server or network
        time.sleep(0.1)

# Replace 'example.com' with the target host and '80' with the target port
host = '93.184.215.14'
port = 80
duration = 120  # Duration set for 2 minutes

open_and_close_socket(host, port, duration)

And when I run it, I observed that rateLimit didn't really drop events. I checked events' args:

process_kprobe: { 
     action: KPROBE_ACTION_POST
     args: [ 
       { 
         sock_arg: {
           cookie: 18446621494401152128
           daddr: 93.184.215.14
           dport: 80
           family: AF_INET
           protocol: IPPROTO_TCP
           saddr: ***
           sport: 36720
           state: TCP_SYN_SENT
           type: SOCK_STREAM
         }
       }
     ]

So, I noticed that source port sport is probably the thing here, as it's chosen randomly per each opened socket. Cookie also doesn't repeat.

Question: is there any way of using rateLimit on tcp_connect? Probably fieldFilter might help?

Tetragon Version

v1.1.0

Kernel Version

5.15.60

Kubernetes Version

v1.24.16

Bugtool

No response

Relevant log output

No response

Anything else?

No response

vladimirkus commented 5 months ago

update: I tried fieldFilter, but it doesn't work. Possibly because of args being an array, or I just use wrong syntax.

ajeet17181 commented 5 months ago

we have removed source port from the event and after that ratelimit is working as expected to remove source port just comment out following line from bpf/process/types/sock.h

proberead(&event->tuple.sport, sizeof(event->tuple.sport), (&common->skc_num));

however there should be a simple way to remove source port from the events (fieldFilters ?)