1000_T3_송인주_Kubernetes 클러스터에서의 고성능&고가용성 NAT Networking 시스템.pdf

가상화된 머신 내부의 리눅스 방화벽을 위한 eBPFXDP 패킷 필터링 성능 비교.pdf

Fast Packet Processing with eBPF and XDP - Concepts, Code, Challenges, and Applications (ACM).pdf

https://dev.to/kbknapp/enter-rust-1bgj

https://wariua.github.io/facility/extended-bpf.html

#![no_std]
#![no_main]
use redbpf_macros::{map, program, xdp};
use redbpf_probes::xdp::{prelude::*, PerfMap};
use redbpf_probes::net::Transport;
use cty::*;

program!(0xFFFFFFFE, "GPL");
#[derive(Default)]
struct PerformanceInfo {
        src: u32
}
#[map]
static mut map: PerfMap<PerformanceInfo> = PerfMap::<PerformanceInfo>::with_max_entries(4096);

#[xdp]
pub fn xdp_firewall(ctx: XdpContext) -> XdpResult {
        if let Ok(proto) = ctx.transport() {
                match proto {
                        Transport::TCP(tcp) => { return filter_tcp(&ctx, &proto, tcp); }
                        _ => ()
                };
        }

        return Ok(XdpAction::Pass);
}

fn filter_tcp(ctx: &XdpContext, proto: &Transport, tcp: *const tcphdr) -> XdpResult {
        if proto.dest() == 80 {
                unsafe { map.insert(ctx, &MapData::new(PerformanceInfo::default())); }
                return Ok(XdpAction::Drop);
        }

        Ok(XdpAction::Pass)
}

bpf 프로그램은 크게 2가지로 나뉘어진다. 메인 eBPF과 로더. map(PrefMap 포함)이 포함 안되어 있으면 아래와 같이 실행하면 되는데,

ip link set dev vethcaf7146 xdp obj dropper.o sec .text
ip link set ens3 xdp object ebpf-test.elf

map이나 PrefMap처럼 user-land와 교신해야 할 일이 있으면 로더로 불러줘야함. (ip로 즉시 로딩하면 아래와 같은 오류 발생)

root@vultr:/home/target/bpf/programs/ebpf-test$ ip link set ens3 xdp object ebpf-test.elf
libbpf: prog 'outer_xdp_firewall': bad map relo against 'map' in section 'maps/map'
ERROR: opening BPF object file failed

큰 구조는 다음과 같음

  1. 로더 실행
  2. 로더가 eBPF를 지정한 장치에 attach함
    1. 이때 드라이버가 지원하면 드라이버단에 붙어서 작동함. (ip link set INTERFACE xdp)
    2. 드라이버가 지원안하면 커널 모드로 돎. (ip link set INTERFACE xdpgeneric)
    3. NIC가 지원하면 아예 NIC 내부에서 (IOP 측에서) 전부 처리할 수도 있음 (단, VPS류는 사실상 불가능할 것으로 보임)
  3. 정상적으로 붙으면 로더에서 map을 열 수 있음.
  4. 이제 서로 교신하면서(?) 동적으로 필터링 할 수 있음.

일단 붙으면 아래와 같이 ip link show 로 확인가능

2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 56:00:03:5e:3c:5c brd ff:ff:ff:ff:ff:ff
    prog/xdp id 16 tag 39e0867e0a9f4e81 jited
    altname enp0s3