반응형
XDP를 활용하여 패킷을 수집한 후, 세션을 추적(Session Tracking)하는 방법입니다.
🔍 1. XDP에서 세션(Session)이란?
✅ 세션(Session)이란?
- 클라이언트(Client)와 서버(Server) 간의 연결을 유지하면서 상태를 추적하는 것
- TCP/UDP 패킷에서 5-Tuple (출발지 IP, 목적지 IP, 출발지 포트, 목적지 포트, 프로토콜)을 기반으로 식별 가능
✅ XDP에서 세션 관리가 어려운 이유?
- XDP는 무상태(Stateless) 방식으로 동작하며, 상태를 유지하는 기능이 없음
- 패킷을 처리하고 바로 드롭(XDP_DROP)하거나 전달(XDP_PASS)하기 때문에, 이전 패킷 정보를 기억할 수 없음
- 세션을 추적하려면 커널 내부에서 패킷 데이터를 저장하는 방식이 필요
✅ 해결 방법: eBPF 맵을 활용하여 세션 상태 유지
- eBPF Hash Map을 사용하여 세션 정보를 저장
- XDP가 패킷을 받을 때, 기존 세션이 존재하는지 확인하고 새로운 세션이면 추가
- 일정 시간이 지나면 유휴 세션(Idle Session)을 삭제
🔎 2. XDP 세션 관리 아키텍처
┌──────────────────────────────────┐
│ 🌍 네트워크 패킷 흐름 │
├──────────────────────────────────┤
│ 1️⃣ XDP에서 패킷 수집 (Zero-Copy) │
│ 2️⃣ eBPF Hash Map을 사용해 세션 저장 │
│ 3️⃣ 기존 세션 여부 확인 및 업데이트 │
│ 4️⃣ 일정 시간 후 만료된 세션 삭제 │
│ 5️⃣ 세션 유지된 패킷만 XDP_PASS │
└──────────────────────────────────┘
🔥 성능 최적화
- eBPF Hash Map을 사용하여 세션을 추적 (O(1) 조회 속도)
- 만료된 세션을 제거하여 메모리 절약
- Zero-Copy 방식으로 커널 네트워크 스택을 거치지 않음
🔎 3. XDP 기반 세션 관리 코드
✅ (1) eBPF XDP 코드: TCP/UDP 세션 저장 및 관리
📌 xdp_session.c (XDP + eBPF 기반 세션 관리 코드)
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
// 🔥 eBPF Hash Map을 사용하여 세션 관리
struct bpf_map_def SEC("maps") session_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u64), // 5-Tuple 해시 키 (IP + 포트 + 프로토콜)
.value_size = sizeof(__u64), // 타임스탬프 (세션 만료 추적)
.max_entries = 10240, // 최대 10,240개의 세션 저장 가능
};
// 🔥 5-Tuple 세션 키 생성 함수
static __u64 create_session_key(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, __u8 proto) {
return ((__u64)saddr << 32) | ((__u64)daddr << 16) | ((__u64)sport << 8) | ((__u64)dport) | ((__u64)proto);
}
// 🔥 XDP 프로그램 (TCP/UDP 패킷 필터링 및 세션 추적)
SEC("xdp")
int xdp_session_tracking(struct __sk_buff *skb) {
struct ethhdr *eth = bpf_hdr_pointer(skb, 0, sizeof(*eth));
if (!eth) return XDP_PASS;
struct iphdr *ip = bpf_hdr_pointer(skb, sizeof(*eth), sizeof(*ip));
if (!ip) return XDP_PASS;
if (ip->protocol != IPPROTO_TCP && ip->protocol != IPPROTO_UDP) {
return XDP_PASS; // TCP/UDP가 아니면 패킷을 커널로 전달
}
__u16 sport = 0, dport = 0;
if (ip->protocol == IPPROTO_TCP) {
struct tcphdr *tcp = bpf_hdr_pointer(skb, sizeof(*eth) + sizeof(*ip), sizeof(*tcp));
if (!tcp) return XDP_PASS;
sport = bpf_ntohs(tcp->source);
dport = bpf_ntohs(tcp->dest);
} else if (ip->protocol == IPPROTO_UDP) {
struct udphdr *udp = bpf_hdr_pointer(skb, sizeof(*eth) + sizeof(*ip), sizeof(*udp));
if (!udp) return XDP_PASS;
sport = bpf_ntohs(udp->source);
dport = bpf_ntohs(udp->dest);
}
// 5-Tuple을 사용하여 세션 키 생성
__u64 session_key = create_session_key(ip->saddr, ip->daddr, sport, dport, ip->protocol);
__u64 ts = bpf_ktime_get_ns(); // 현재 타임스탬프 (나노초)
// 🔥 세션이 존재하는지 확인
__u64 *session_ts = bpf_map_lookup_elem(&session_map, &session_key);
if (session_ts) {
// 세션이 이미 존재하는 경우 → 타임스탬프 업데이트
*session_ts = ts;
} else {
// 새로운 세션 등록
bpf_map_update_elem(&session_map, &session_key, &ts, BPF_ANY);
}
return XDP_PASS; // 세션이 존재하는 패킷만 허용
}
char LICENSE[] SEC("license") = "GPL";
✅ 설명
- session_map: eBPF Hash Map을 사용하여 세션 정보를 저장
- create_session_key(): 5-Tuple (출발지 IP, 목적지 IP, 출발지 포트, 목적지 포트, 프로토콜) 기반 해시 생성
- bpf_map_lookup_elem(): 기존 세션이 있는지 확인
- bpf_map_update_elem(): 새로운 세션을 추가하거나 기존 세션 업데이트
- XDP_PASS: 세션이 유지된 패킷만 허용
✅ (2) eBPF XDP 프로그램 실행 (Python)
📌 load_xdp.py (XDP 프로그램 실행)
from bcc import BPF
bpf_code = """
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
SEC("xdp")
int xdp_filter(struct __sk_buff *skb) {
struct ethhdr *eth = bpf_hdr_pointer(skb, 0, sizeof(*eth));
if (!eth) return XDP_PASS;
struct iphdr *ip = bpf_hdr_pointer(skb, sizeof(*eth), sizeof(*ip));
if (!ip) return XDP_PASS;
__u32 client_ip = bpf_htonl(0xC0A80101);
__u32 server_ip = bpf_htonl(0xC0A80102);
if (ip->saddr == client_ip || ip->daddr == server_ip) {
return XDP_PASS;
}
return XDP_DROP;
}
"""
bpf = BPF(text=bpf_code)
fn = bpf.load_func("xdp_filter", BPF.XDP)
bpf.attach_xdp("eth0", fn, 0)
print("XDP 세션 관리 프로그램 로드 완료.")
try:
bpf.trace_print()
except KeyboardInterrupt:
pass
bpf.remove_xdp("eth0", 0)
✅ 설명
- eBPF XDP 프로그램을 eth0 인터페이스에 적용
- 세션 정보가 존재하면 패킷을 허용(XDP_PASS)
- 세션이 존재하지 않으면 차단 가능
🚀 결론: XDP 기반 세션 관리
기능 | 역할 | 효과 |
eBPF Hash Map | 세션 정보 저장 | 초고속 O(1) 조회 |
5-Tuple 해시 | 세션 추적 | 네트워크 연결 유지 |
XDP_PASS | 기존 세션 유지 | 합법적인 트래픽 처리 |
🚀 결론:
XDP 기반 eBPF Hash Map을 활용하면 초고속 세션 관리를 구현 가능!
➡ 네트워크 환경(AWS, GCP, Kubernetes 등)을 알려주시면 추가 최적화 가능! 🚀
반응형
'장인으로의 여정 > 유용한 TIP' 카테고리의 다른 글
🚀 XDP와 eBPF의 관계 (0) | 2025.02.23 |
---|---|
🚀 XDP (eXpress Data Path) 완벽 가이드 (1) | 2025.02.23 |
🚀 eBPF (Extended Berkeley Packet Filter) 완벽 가이드 (0) | 2025.02.23 |
댓글