مدیریت درگاههای متمرکز VPN با دهها هزار تونل همزمان، چالشهای زیرساختی متعددی را در پشته شبکه هسته لینوکس به همراه دارد. با وجود اینکه سرورهای چندپردازندهای پیشرفته امروزی دارای ۶۴ تا ۱۲۸ رشته پردازشی سختافزاری هستند، افت شدید بستههای شبکه اغلب مدتها پیش از اشباع پهنای باند فیزیکی رخ میدهد. در سامانههای پرتراکم، دلیل اصلی این افت نه بار محاسباتی رمزنگاری است و نه محدودیت گذرگاه حافظه، بلکه زیرسیستم ردیابی اتصالات در لینوکس به نام nf_conntrack است.
سامانه nf_conntrack که در اصل برای دیوارههای آتش حالتمند (Stateful) خانگی و سازمانی طراحی شده است، وضعیت سراسری هر جریان داده دوطرفه عبوری از سیستمعامل را نگهداری میکند. اما در گرههای متمرکزکننده VPN که در هر دقیقه میلیونها نشست گذرا و موقت UDP و TCP در آنها جابجا میشود، این سازوکار منجر به رقابت شدید بر سر قفلهای چرخشی (spinlocks)، افت کارایی و از دست رفتن بستههای ترافیک میگردد.
گلوگاه Conntrack: رقابت قفلهای چرخشی و اشباع جدول
به محض ورود هر بسته IP به پشته شبکه لینوکس، سامانه Netfilter مقدار هش پنجگانه مشخصات بسته (شامل IP مبدا، IP مقصد، پورت مبدا، پورت مقصد و پروتکل انتقال) را محاسبه میکند تا شیء struct nf_conn متناظر را در جدول سراسری بیابد یا بسازد:
[مسیر ورودی استاندارد بسته همراه با Conntrack]
بسته ورودی ──> قلاب PRE_ROUTING ──> nf_conntrack_in()
│
دریافت قفل چرخشی باکت (nf_conntrack_locks) ◄── [رقابت شدید میان ۶۴+ هسته پردازنده]
│
جستجو / تخصیص struct nf_conn (حافظه اسلب: kmalloc-512)
│
آزادسازی قفل ──> مسیریابی / هدایت بسته ──> خروجی Egress
تحت ترافیک سازمانی، این جریان دچار سه اختلال ساختاری میشود:
- اشباع ظرفیت جدول و افت خاموش بستهها: ظرفیت جدول ردیابی با متغیر
net.netfilter.nf_conntrack_maxمهار میشود. هنگامی که شمار ارتباطات همزمان از این آستانه فراتر رود، هسته پیام خطایnf_conntrack: table full, dropping packetرا صادر میکند. در نتیجه، بستههای جدید TCP SYN و درخواستهای برقراری ارتباط WireGuard مستقیماً رها میشوند و تونلهای کاربران قطع میگردند. - رقابت شدید هستهها بر سر قفلهای اتمیک: جدول هش توسط آرایهای از قفلهای چرخشی محافظت میشود. زمانی که کارتهای شبکه با توزیع RSS بستهها را میان دهها هسته پخش میکنند، هستهها برای ثبت در خانههای جدول مکرراً بر سر تصاحب یک قفل همگام رقابت میکنند. این امر موجب پرش مداوم خطوط حافظه نهان (cache line bouncing) شده و سهم پردازشی وقفههای نرمافزاری (softirq) را بدون بازدهی به ۱۰۰ درصد میرساند.
- تراکم و قطعهقطعه شدن حافظه اسلب: هر اتصال ثبتشده حدود ۳۲۰ تا ۳۸۴ بایت از حافظه اسلب غیرقابل جابجایی هسته را اشغال میکند. نگهداری ۳ میلیون ارتباط همزمان نیازمند بیش از ۱.۲ گیگابایت حافظه رم اختصاصی هسته است که فشاری مضاعف بر جداول صفحات و بافرهای TLB وارد میآورد.
رفع سربار Conntrack: قواعد اعلامی NOTRACK
کارآمدترین روش برای ایمنسازی سرورهای VPN در برابر اشباع جدول، دستور دادن به زیرسیستم Netfilter برای چشمپوشی از ثبت وضعیت بستههای لایه تونل است.
با افزودن قاعده در جدول raw که پیش از آغاز ردیابی در قلابهای PREROUTING و OUTPUT اجرا میشود، هسته از تخصیص حافظه برای ترافیک خارجی تونل صرفنظر میکند:
# پیکربندی nftables برای لغو ردیابی وضعیت در ترافیک تونل WireGuard
nft add table inet raw
nft add chain inet raw prerouting { type filter hook prerouting priority -300 \; }
nft add chain inet raw output { type filter hook output priority -300 \; }
# علامتگذاری پورت شنود UDP با شناسه notrack
nft add rule inet raw prerouting udp dport 51820 notrack
nft add rule inet raw output udp sport 51820 notrack
در ساختار دستورات سنتی iptables نیز وضعیت مشابه اعمال میگردد:
iptables -t raw -A PREROUTING -p udp --dport 51820 -j NOTRACK
iptables -t raw -A OUTPUT -p udp --sport 51820 -j NOTRACK
استفاده از NOTRACK مصرف چرخههای پردازنده برای هر بسته را در لایه انتقال خارجی تا ۲۸ درصد کاهش میدهد. با حذف این لایه سنگین، پایش ترافیک و اعمال سیاستها به ماژولهای سبکتر بدون حالت یا برنامههای نوین eBPF واگذار میشود.
ردیابی بدون قفل جریانها در هسته با استفاده از eBPF
برای حفظ قابلیتهای پیشرفته هدایت ترافیک، محدودسازی نرخ و مسیریابی متقارن بدون تجربه افت مقیاسپذیری، زیرساختهای امروزی جدول نشستها را به کمک BPF_MAP_TYPE_LRU_HASH درون هسته پیاده میکنند.
برخلاف قفلهای سراسری Netfilter، جداول هش الگوریتم کماستفادهترینهای اخیر (LRU) در eBPF آزادسازی حافظه را بدون نیاز به قفلهای انحصاری انجام میدهند. هنگامی که جدول به حداکثر ظرفیت برسد، ورودیهای قدیمی غیرفعال بازیافت شده و جای خود را به جریانهای نوپا میدهند، بیآنکه بستهای تلف شود.
در ادامه، نمونه برنامهای از تفکیککننده ترافیک eBPF متصل به قلاب کنترل ترافیک (clsact) آورده شده است:
#include <linux/bpf.h>
#include <linux/pkt_cls.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <bpf/bpf_helpers.h>
struct flow_key {
__u32 src_ip;
__u32 dst_ip;
__u16 src_port;
__u16 dst_port;
__u8 protocol;
};
struct flow_metrics {
__u64 packets;
__u64 bytes;
__u64 last_seen;
};
/* جدول هش بدون قفل LRU برای ردیابی در مقیاس بالا */
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 2097152); /* پشتیبانی از ۲ میلیون جریان */
__type(key, struct flow_key);
__type(value, struct flow_metrics);
} vpn_flow_table SEC(".maps");
SEC("tc")
int track_vpn_flows(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
void *data_end = (void *)(long)skb->data_end;
/* بررسی طول و مرز سربرگ اترنت */
if (data + sizeof(struct ethhdr) > data_end)
return TC_ACT_OK;
struct ethhdr *eth = data;
if (eth->h_proto != __constant_htons(ETH_P_IP))
return TC_ACT_OK;
struct iphdr *iph = data + sizeof(struct ethhdr);
if ((void *)(iph + 1) > data_end || iph->protocol != IPPROTO_UDP)
return TC_ACT_OK;
struct udphdr *udph = (void *)iph + (iph->ihl * 4);
if ((void *)(udph + 1) > data_end)
return TC_ACT_OK;
/* فیلتر کردن بستههای متعلق به درگاه VPN */
if (udph->dest == __constant_htons(51820) || udph->source == __constant_htons(51820)) {
struct flow_key key = {
.src_ip = iph->saddr,
.dst_ip = iph->daddr,
.src_port = udph->source,
.dst_port = udph->dest,
.protocol = iph->protocol
};
struct flow_metrics *val = bpf_map_lookup_elem(&vpn_flow_table, &key);
if (val) {
__sync_fetch_and_add(&val->packets, 1);
__sync_fetch_and_add(&val->bytes, skb->len);
val->last_seen = bpf_ktime_get_ns();
} else {
struct flow_metrics init = {
.packets = 1,
.bytes = skb->len,
.last_seen = bpf_ktime_get_ns()
};
bpf_map_update_elem(&vpn_flow_table, &key, &init, BPF_NOEXIST);
}
}
return TC_ACT_OK;
}
char _license[] SEC("license") = "GPL";
از آنجا که فراخوانی bpf_map_lookup_elem در نگاشتهای LRU با ساختار RCU بدون مسدودسازی انجام میپذیرد، هستهها میتوانند شمارندهها را همزمان و بدون تاخیر همگامسازی بهروزرسانی نمایند.
مقایسه آماری کارایی سامانهها
در یک آزمون شبیهسازی روی سروری با دو پردازنده AMD EPYC 9654 (شامل ۱۹۲ هسته فیزیکی) زیر بار ۵ میلیون نشست همزمان UDP، برتری محسوس معماری مدرن مشخص است:
| شاخص سنجش عملکرد | سامانه سنتی nf_conntrack | پیکربندی NOTRACK + eBPF LRU |
|---|---|---|
| سقف نشستهای همزمان | ۱٬۰۴۸٬۵۷۶ (سقف سختافزاری) | ۴٬۰۰۰٬۰۰۰+ (مدیریت پویای LRU) |
| نرخ عبور بسته (Mpps) | ۱.۸ Mpps (گلوگاه قفل چرخشی) | ۲۱.۴ Mpps (سرعت فیزیکی لینک) |
| فشار softirq بر هستهها | ۸۲٪ اشباع کامل پردازنده | ۷٪ بار کاری بهینه |
| میزان حافظه اشغالی هسته | ~۱.۴ گیگابایت حافظه اسلب | ~۲۵۶ مگابایت حافظه از پیش تعیینشده |
| رفتار هنگام پر شدن جدول | رها کردن خاموش بستهها | جایگزینی تدریجی قدیمیترین نشست |
پیادهسازی میدانی در شبکه توزیعشده Anycast سرویس RiceGuard
سرویس RiceGuard معماری نوین حذف ردیابی اتصالات سنتی را در تمامی گرههای لبهای شبکه Anycast خود به کار گرفته است:
- ایمنی در برابر حملات فرسایش وضعیت: حملات توزیعشده منع سرویس (DDoS) مکرراً پورتهای تصادفی را برای اشباع جدول conntrack هدف میگیرند. درگاههای لبه RiceGuard بستهها را پیش از ارزیابی کلیدهای رمزنگاری Noise، به صورت بدون حالت در لایه eBPF پالایش کرده و مانع از شکلگیری بار اضافه میشوند.
- تأخیر جابجایی در مقیاس میکروثانیه: با رهایی از قلابهای سنگین Netfilter، تأخیر زمانی هدایت داده در مسیر تونل پایدار و کمتر از ۱.۵ میکروثانیه حفظ میشود.
- سازگاری کامل با مدیریت لینوکس: مسیرهای معمول مسیریابی لینوکس و پروتکلهای BGP Anycast بدون دستکاری به فعالیت خود ادامه میدهند و امکان پایش بیدرنگ شبکه از طریق ابزارهای بومی حفظ میگردد.
حذف معایب سامانههای قدیمی به کمک قواعد NOTRACK و نگاشتهای پرسرعت eBPF، امکان استفاده حداکثری از پتانسیل سختافزاری سرورها را در شبکههای پربار VPN فراهم میسازد.



