Tăng tốc TURN với eBPF: Cách tiếp cận phi xâm phạm và hiệu suất cao
Bài viết giới thiệu dự án TURN-BPF, một giải pháp sử dụng eBPF để tăng tốc đáng kể hiệu suất của máy chủ TURN mà không cần chỉnh sửa mã nguồn ứng dụng. Bằng cách chuyển xử lý gói tin sang lớp kernel, công cụ này giúp giảm tải CPU và giảm độ trễ, đặc biệt hữu ích cho các hệ thống WebRTC quy mô lớn.

Trong bối cảnh phát triển nhanh chóng của công nghệ mạng, eBPF (Extended Berkeley Packet Filter) đã nổi lên như một công cụ mạnh mẽ để giải quyết các bài toán lọc gói tin và tối ưu hóa hiệu suất. Tuy nhiên, việc áp dụng eBPF để tăng tốc cho các máy chủ relay trạng thái (stateful relay server) hoạt động ở không gian người dùng (userspace) luôn là một thách thức lớn.
Bài viết này sẽ khám phá cách tiếp cận mới mẻ để tăng tốc giao thức TURN (Traversal Using Relays around NAT - RFC 8656) sử dụng eBPF thông qua dự án mã nguồn mở TURN-BPF.
Thách thức về hiệu suất của TURN
Giao thức TURN đóng vai trò quan trọng trong WebRTC, giúp kết nối các đối tác ngang hàng (peer) khi tường lửa hoặc NAT chặn đường truyền trực tiếp. Tuy nhiên, đây là một giao thức "ngốn" nhiều tài nguyên CPU do phải thực hiện số lượng lớn chuyển đổi ngữ cảnh giữa chế độ kernel và người dùng (kernel-to-user mode switches).
Mặc dù đã có các đề xuất và giải pháp trước đây nhằm giảm tải xử lý TURN bằng eBPF/XDP, nhưng hầu hết chúng đều yêu cầu sửa đổi sâu rộng mã nguồn của máy chủ TURN. Điều này tạo ra rào cản lớn trong việc triển khai thực tế.
TURN-BPF: Cách tiếp cận "Nghe lén" (Snooping)
Dự án TURN-BPF giới thiệu một phương pháp phi xâm phạm (non-invasive). Thay vì thay đổi logic của máy chủ TURN (ví dụ: coturn), TURN-BPF hoạt động như một thành phần eBPF độc lập, "quan sát" và học hỏi các kết nối channel mới thông qua cơ chế "snooping" (nghe lén) các gói tin điều khiển.
Điều này có nghĩa là máy chủ TURN hoạt động bình thường mà không hề biết sự tồn tại của lớp tăng tốc bên dưới.
Kiến trúc tổng quan
Hệ thống bao gồm một tập hợp các chương trình eBPF được viết bằng ngôn ngữ C, chạy ở các hook XDP và TC (Traffic Control):
- XDP/TC Snoopers: Các chương trình này lắng nghe các gói tin bắt tay (handshake) để xác lập kênh relay.
- XDP Fast Path (cli2rem/rem2cli): Sau khi kênh được thiết lập, các gói tin dữ liệu sẽ được chuyển tiếp trực tiếp ở lớp kernel mà không cần đưa lên không gian người dùng.
Tại đây, các chương trình eBPF thực hiện các nhiệm vụ nặng nhọc:
- Thực hiện NAT (Network Address Translation) giữa client và peer.
- Thêm hoặc bóc tắt thẻ kênh TURN (channel tag).
- Cập nhật checksum và ghi lại địa chỉ MAC.
- Gửi gói tin ra ngoài dựa trên bảng định tuyến kernel (FIB).
Tại sao sử dụng TC Hook?
Bạn có thể thắc mắc tại sao tác giả sử dụng TC egress hook để "nghe lén" phản hồi của máy chủ thay vì xử lý mọi thứ trong XDP?
Lý do là: Trong khi XDP tối ưu cho tốc độ thô (raw speed) khi gói tin đi vào (ingress), thì hook TC ở hướng đi ra (egress) trên interface client cho phép quan sát gói tin sau khi chúng đã được xử lý bởi stack mạng của kernel và không gian người dùng. Đến lúc này, phản hồi thành công ChannelBind đã được hình thành đầy đủ. Bằng cách chặn tại điểm này, hệ thống đảm bảo rằng một kênh chỉ được chuyển sang đường dẫn nhanh (fast path) khi máy chủ đã chính thức chấp nhận cấp phát.
"Dưới nắp capo": Tra cứu FIB và Heartbeat
Tra cứu FIB
Việc biết địa chỉ IP nào ánh xạ tới địa chỉ MAC nào và quan trọng hơn là qua interface mạng nào, được thực hiện thông qua tra cứu FIB (Forwarding Information Base). Hàm bpf_fib_lookup của kernel được tận dụng để thực hiện việc này trong đường dẫn điều khiển (control path) khi channel binding được cam kết.
Cơ chế Heartbeat (Nhịp tim)
Để đảm bảo phiên làm việc không bị hết hạn (timeout) trong máy chủ TURN, TURN-BPF sử dụng cơ chế "heartbeat spill". Một phần nhỏ các gói tin dữ liệu vẫn được phép đi lên stack mạng để máy chủ TURN nhận thấy kênh vẫn đang hoạt động, trong khi phần lớn lưu lượng được xử lý với tốc độ cao bởi eBPF.
Lưu ý: Hiện tại dự án này vẫn ở khái niệm bằng chứng (proof-of-concept), chưa hỗ trợ các kênh được mã hóa (encrypted channels) và chỉ hoạt động với IPv4.
Cài đặt và Triển khai
Công cụ đi kèm với một chương trình loader được viết bằng Rust. Dưới đây là các bước cài đặt trên Debian 13 (kernel 6.12):
Trước tiên, cài đặt các thư viện cần thiết và biên dịch dự án:
sudo apt update
sudo apt install --yes cargo clang git libelf-dev pkg-config
git clone https://github.com/ivanmtech/turn-bpf
cd turn-bpf
cargo build
Chạy công cụ (trên terminal riêng biệt trước khi khởi động TURN):
sudo ./target/debug/turn-bpf <tên_interface_chính> [tên_các_interface_relay...]
Ví dụ kiểm tra
Trên một môi trường kiểm tra đơn giản với hai máy tính xách tay kết nối qua Ethernet USB 100Mbps:
Cấu hình Coturn (Server):
listening-port=3478
listening-ip=192.168.47.1
relay-ip=192.168.47.1
user=user:password
realm=turn.test
Chạy Coturn:
sudo turnserver -c ~/test.cfg
Chạy Client/Peer:
# Terminal 1 (Peer)
turnutils_peer -L 192.168.47.2
# Terminal 2 (Client)
turnutils_uclient -u user password \
-w p -e 192.168.47.2 -n 100000 -m 50 -g 192.168.47.1
Kết quả hiệu suất
Theo kết quả thử nghiệm, khi sử dụng pidstat để theo dõi tiến trình coturn:
- Tỉ lệ sử dụng CPU ở mức không đáng kể (gần 0%).
- Khi tắt TURN-BPF (nhấn Ctrl+C), mức sử dụng CPU của
coturnnhảy vọt lên khoảng 20%. - Mức sử dụng CPU toàn hệ thống chỉ ở mức 0-1% khi kích hoạt offload, so với 6-7% khi không có.
Mặc dù môi trường thử nghiệm còn đơn giản, nhưng kết quả ban đầu đã cho thấy tiềm năng lớn của eBPF trong việc tối ưu hóa hiệu suất mạng mà không cần can thiệp sâu vào cấu trúc ứng dụng hiện có.



