Blog

Get the latest cybersecurity news

블로그 메인페이지로 돌아가기

 XDP를 활용한 네트워크 패킷 처리

 

eBPF/XDP

 모니터랩 연구소 클라우드팀 권세민 팀장

 

IT 분야에서 네트워크는 대부분의 기술 및 서비스에 필수 요소이다. 이제 일상생활에서도 네트워크가 없는 삶은 생각하기 어렵다. IT 네트워크 분야 기업들은 네트워크 품질 및 속도 개선에 그 역량을 집중하고 있고 네트워크 처리 성능이 그 기업의 경쟁력을 나타내는 지표로 여겨지고 있다. 모니터랩은 가상화 환경의 네트워크 성능 향상을 위해 DPDK 및 XDP를 적용하고 있다. 이번 기고에서는 XDP에 대해 간략하게 알아보도록 한다.

 

 XDP를 활용한 네트워크 패킷 처리

XDP는 eBPF Hook의 한 종류로 네트워크 드라이버 내에서 동작하는 명령어 집합입니다. 쉽게 이야기하자면 iptables의 패킷 처리 기능을 네트워크 드라이버 단에서 사용할 수 있도록 커널에서 제공하는 명령어 들이죠. 이러한 XDP 기능을 지원하기 위해 네트워크 장치 드라이버 내에는 XDP 관련 코드가 구현이 되어있습니다.

이러한 불편함을 감수하면서 얻고자 하는 부분은 명확합니다. 바로 성능이죠. Cloudflare의 블로그의 글을 보면 단일 cpu 기준 초당 천만 개의 패킷을 버릴 수 있다고 합니다.
(https://blog.cloudflare.com/ko/how-to-drop-10-million-packets-ko-kr/)

XDP를 사용하기 위해서는 Linux 4.8 이상의 커널을 사용해야 합니다. 만약, 네트워크 드라이버가 XDP를 지원하지 않는다면 Generic 모드를 사용하여 구현이 가능합니다. Generic 모드는 Driver에서 SKB 할당 이후 처리되기 때문에 당연히 성능적인 손실이 있습니다.

XDP 프로그램은 xdp_md 구조체를 인자로 받습니다. xdp_md 구조체에는 패킷의 시작(data)과 끝(data_end)에 해당되는 주소가 담겨 있습니다. 이 값을 이용하여 패킷을 분석하고 변경할 수 있습니다.

아래는 간단한 XDP 프로그램입니다.

SEC를 통해 프로그램의 섹션을 분리할 수 있습니다. 이렇게 정의된 섹션은 libbpf를 사용하여 프로그램을 로드할 때 사용됩니다(물론, C-Function Name을 통해 호출하는 방법도 있습니다). license는 GPL로 명시하지 않을 경우 헬퍼 함수 사용에 제약이 있습니다. bpf_printk는 trace debug 출력을 위한 헬퍼 함수로 간단한 로그를 출력하기에 적합합니다. 단, 속도가 매우 느리기 때문에 사용 시 제약이 심합니다. 위의 XDP 프로그램은 패킷이 유입될 때 receive packet 메시지를 출력하고 리턴 타입인 XDP_PASS에 의해 커널 network stack으로 패킷을 보내게 됩니다. 컴파일 후 생성되는 ELF 파일을 ip 명령어를 통해 인터페이스에 연결할 수 있습니다.

trace debug를 확인하기 위해 trace_pipe를 cat 명령어로 출력하여 “receive packet” 문장이 출력되는지 확인하겠습니다. 트래픽 수신을 확인해야 하니 해당 인터페이스를 소유한 컨테이너 내부에서 ping 명령어를 사용하여 트래픽을 발생시키자 trace debug가 출력되는 것을 확인할 수 있습니다.

XDP 프로그램에 drop 섹션을 추가하고 모든 패킷을 차단하는 프로그램을 만들어 보겠습니다.

동일하게 ip 명령어를 사용하여 프로그램을 인터페이스에 연결합니다. 섹션 이름은 동일할 수 있으나 C-Function 달라야 합니다(컴파일 오류 발생).

기존 XDP 프로그램을 분리하고 새로 만든 프로그램을 로드합니다.

 

다시 컨테이너 내부에서 ping을 통해 트래픽 발생 후 trace debug를 확인하겠습니다.

 

XDP_DROP으로 인해 모든 ping이 차단되는 것을 확인할 수 있습니다. 이번에는 특정 IP에 대해서만 차단을 수행하고 나머지는 커널로 보내는 프로그램을 만들어 보겠습니다.

위 프로그램은 목적지 IP가 8.8.8.8인 경우에 차단하고 나머지는 허용하는 간단한 FW 프로그램입니다. 기능이 잘 동작하는지 테스트를 위해 컨테이너 내부에서 ping 테스트를 해보겠습니다.

 

위 그림의 결과와 같이 차단 IP로 지정한 8.8.8.8로의 연결이 차단되는 것을 확인할 수 있습니다. 코드에서 리턴 타입으로 XDP_PASS, XDP_DROP과 같이 약속된 타입을 리턴하는 것을 볼 수 있습니다. XDP 프로그램의 리턴 타입에는 5가지 종류가 있습니다.

  • XDP_ABORTED: 패킷을 버리고 xdp_exception을 발생시킴
  • XDP_DROP: 패킷을 버림
  • XDP_PASS: 패킷을 커널로 보냄
  • XDP_TX: 패킷을 수신된 인터페이스로 재전송
  • XDP_REDIRECT: 패킷을 다른 인터페이스로 전달

위에 명시한 타입들을 사용하여 다양한 기능을 수행하는 네트워크 장치를 만들 수 있습니다.

이번에는 ping을 전송했을 때 수신 인터페이스에서 ping 응답을 반환하는 프로그램을 만들어 보겠습니다.

해당 프로그램을 인터페이스에 로드 후 컨테이너 내부에서 ping 테스를 진행하면 정상적으로 응답이 오는 것을 확인할 수 있습니다.

이때, 컨테이너 외부에서 패킷 dump를 확인해보면 해당 패킷이 보이지 않는 것을 알 수 있습니다.

이런 현상이 발생하는 이유는 XDP 프로그램이 Driver 내에서 실행되기 때문에 패킷이 커널까지 전달되지 않기 때문입니다. tcpdump는 BPF 필터를 사용하기 때문에 커널 network stack 이후에 확인이 가능하죠. 이러한 내용은 netfilte-packet-flow 그림에서 확인할 수 있습니다.

그림을 보면 XDP eBPF가 allock_skb 이전에 동작하는 부분을 확인할 수 있습니다. 이렇듯 Driver 다음에 바로 XPD가 실행되기 매우 빠른 패킷 처리 능력을 보여줍니다.

XDP_REDIRECT, AF_XDP 등 좀 더 다양하고 실용적인 기능은 다음 포스팅 시간에 추가적으로 살펴보도록 하겠습니다.

 

Scroll Up