त्वरित शुरुआत करना 超XDP परिचय भाग 3 (ICMP ईको उत्तर खंड 1)

पिछले लेख में, हमने XDP के साथ eBPF मैप का उपयोग करके उपयोगकर्ता भूमि के साथ डेटा का आदान-प्रदान किया।

पिछले लेख में, हमने XDP कार्यक्रम का उपयोग करके सभी पैकेटों को ड्राप करने वाला कार्यक्रम लिखा।

इस बार, हम ICMP ईको अनुरोध के जवाब में ICMP ईको उत्तर देने वाला कार्यक्रम लिखेंगे।

ICMP ईको उत्तर देने के लिए

ICMP ईको अनुरोध के जवाब में ICMP ईको उत्तर देने के लिए, निम्नलिखित चरणों की आवश्यकता है।

  1. ICMP ईको अनुरोध के पैकेट को प्राप्त करें
  2. ICMP ईको उत्तर में फ्लैग बदलें
  3. भेजने वाले और प्राप्तकर्ता के IP पते बदलें
  4. ईथरनेट हेडर के भेजने वाले और प्राप्तकर्ता के MAC पते बदलें
  5. पैकेट भेजें

केवल ICMP ईको अनुरोध को ड्रॉप करें

पहले, हम ICMP ईको अनुरोध को संसाधित करने के लिए, केवल ICMP ईको अनुरोध को ड्रॉप करने वाला कार्यक्रम लिखना चाहेंगे।

  • xdp_echo_request_drop.c
    #include <linux/bpf.h>
    #include <bpf/bpf_helpers.h>
    #include <linux/if_ether.h>
    #include <linux/ip.h>
    #include <linux/icmp.h>
    #include <arpa/inet.h>
    
    SEC("xdp")
    int xdp_drop_icmp(struct xdp_md *ctx) {
        void *data_end = (void *)(unsigned long)ctx->data_end;
        void *data = (void *)(unsigned long)ctx->data;
    
        // ईथरनेट हेडर के पॉइंटर को प्राप्त करें
        struct ethhdr *eth = data;
        if ((void *)eth + sizeof(*eth) > data_end)
            return XDP_PASS;
    
        // ईथरनेट फ्रेम में IP पैकेट है या नहीं यह चेक करें
        if (eth->h_proto != htons(ETH_P_IP))
            return XDP_PASS;
    
        // IP हेडर के पॉइंटर को प्राप्त करें
        struct iphdr *ip = data + sizeof(*eth);
        if ((void *)ip + sizeof(*ip) > data_end)
            return XDP_PASS;
    
        // प्रोटोकॉल ICMP है या नहीं चेक करें
        if (ip->protocol != IPPROTO_ICMP)
            return XDP_PASS;
    
        // ICMP हेडर के पॉइंटर को प्राप्त करें
        struct icmphdr *icmp = (void *)ip + sizeof(*ip);
        if ((void *)icmp + sizeof(*icmp) > data_end)
            return XDP_PASS;
    
        // ICMP ईको अनुरोध के अलावा पैकेट को पास करें
        if (icmp->type != ICMP_ECHO)
            return XDP_PASS;
    
        // ICMP ईको अनुरोध के पैकेट को ड्रॉप करें
        return XDP_DROP;
    }
    
    char _license[] SEC("license") = "MIT";
    

त्वरित शुरुआत करना 超XDP परिचय में बनाए गए कार्यक्रम के समान है।

  // ICMP ईको अनुरोध के अलावा पैकेट को पास करें
  if (icmp->type != ICMP_ECHO)
      return XDP_PASS;

इस भाग में, ICMP ईको अनुरोध के अलावा के पैकेट को पास किया जा रहा है।

ICMP ईको को उत्तर में बदलना

अब, ICMP ईको अनुरोध के जवाब में ICMP ईको उत्तर देने के लिए एक कार्यक्रम लिखते हैं।

  1. ICMP ईको उत्तर के लिए फ्लैग बदलें
// ICMP ईको उत्तर के लिए फ्लैग बदलें
icmp->type = ICMP_ECHOREPLY;

type को ICMP_ECHO (8) से ICMP_ECHOREPLY (0) में बदलें।

  1. भेजने वाले और प्राप्तकर्ता के IP पतों को बदलें
// भेजने वाले और प्राप्तकर्ता के IP पतों को बदलें
__u32 tmp = ip->saddr;
ip->saddr = ip->daddr;
ip->daddr = tmp;
  1. ईथरनेट हेडर के भेजने वाले और प्राप्तकर्ता के MAC पतों को बदलें
// ईथरनेट हेडर के भेजने वाले और प्राप्तकर्ता को बदलें
unsigned char tmp_mac[ETH_ALEN];
__builtin_memcpy(tmp_mac, eth->h_dest, ETH_ALEN);
__builtin_memcpy(eth->h_dest, eth->h_source, ETH_ALEN);
__builtin_memcpy(eth->h_source, tmp_mac, ETH_ALEN);
  1. XDP_TX का उपयोग करके पैकेट को भेजें
// पैकेट को भेजें
return XDP_TX;

इस प्रकार, ICMP ईको उत्तर देने वाला कार्यक्रम तैयार है।

SEC("xdp")
int xdp_echo_reply(struct xdp_md *ctx)
{
    void *data_end = (void *)(unsigned long)ctx->data_end;
    void *data = (void *)(unsigned long)ctx->data;

    // ईथरनेट हेडर के पॉइंटर को प्राप्त करें
    struct ethhdr *eth = data;
    if ((void *)eth + sizeof(*eth) > data_end)
        return XDP_PASS;

    // ईथरनेट फ्रेम में IP पैकेट है या नहीं यह चेक करें
    if (eth->h_proto != htons(ETH_P_IP))
        return XDP_PASS;

    // IP हेडर के पॉइंटर को प्राप्त करें
    struct iphdr *ip = data + sizeof(*eth);
    if ((void *)ip + sizeof(*ip) > data_end)
        return XDP_PASS;

    // प्रोटोकॉल ICMP है या नहीं चेक करें
    if (ip->protocol != IPPROTO_ICMP)
        return XDP_PASS;

    // ICMP हेडर के पॉइंटर को प्राप्त करें
    struct icmphdr *icmp = (void *)ip + sizeof(*ip);
    if ((void *)icmp + sizeof(*icmp) > data_end)
        return XDP_PASS;

    // ICMP ईको अनुरोध के अलावा पैकेट को पास करें
    if (icmp->type != ICMP_ECHO)
        return XDP_PASS;

    // ICMP ईको उत्तर के लिए फ्लैग बदलें
    icmp->type = ICMP_ECHOREPLY;

    // IP हेडर के भेजने वाले और प्राप्तकर्ता को बदलें
    __u32 tmp = ip->saddr;
    ip->saddr = ip->daddr;
    ip->daddr = tmp;

    // ईथरनेट हेडर के भेजने वाले और प्राप्तकर्ता को बदलें
    unsigned char tmp_mac[ETH_ALEN];
    __builtin_memcpy(tmp_mac, eth->h_dest, ETH_ALEN);
    __builtin_memcpy(eth->h_dest, eth->h_source, ETH_ALEN);
    __builtin_memcpy(eth->h_source, tmp_mac, ETH_ALEN);

    // ICMP ईको अनुरोध के पैकेट को ड्रॉप करें
    // return XDP_DROP;
    return XDP_TX;
}

NIC पर कार्यक्रम को लोड करना

कार्यक्रम को संकलित करें और NIC पर लोड करें।

$ clang -O2 -target bpf -c xdp_echo_reply.c -o xdp_echo_reply.o
$ sudo ip link set dev eth0 xdp obj xdp_echo_reply.o

कार्यशीलता की पुष्टि करना

  • क्लाइंट से पिंग भेजें

    $ ping 192.168.XXX.XXX
    
  • सर्वर पर tcpdump चलाकर पुष्टि करें कि ICMP अनुरोध प्राप्त नहीं हो रहा है।
    XDP सीधे पैकेट को संसाधित कर रहा है, इसलिए tcpdump पर इसे नहीं देखा जा सकता है और यह पता चलता है कि Linux kernel ने ईको उत्तर नहीं दिया है।

    $ sudo tcpdump -i eth0 icmp
    
  • क्लाइंट से पिंग भेजने पर ICMP ईको उत्तर का लौटना सुनिश्चित करें।

    $ sudo tcpdump -i eth0 icmp -vvv
    XX:XX:XX.160507 IP (tos 0x0, ttl 64, id 53521, offset 0, flags [DF], proto ICMP (1), length 84)
        192.168.XXX.1 > 192.168.XXX.2: ICMP echo request, id 58371, seq 684, length 64
    XX:XX:XX.161394 IP (tos 0x0, ttl 64, id 53521, offset 0, flags [DF], proto ICMP (1), length 84)
        192.168.XXX.2 > 192.168.XXX.1: ICMP echo reply, id 58371, seq 684, length 64 (गलत icmp cksum 767b (->7e7b)!)
    

ICMP ईको उत्तर लौट आया है यह पुष्ट हुआ।
हालांकि, “गलत icmp cksum” प्रदर्शित हो रहा है, तो स्पष्ट है कि ICMP हेडर की चेकसम सही तरीके से गणना नहीं की गई है।

ICMP की चेकसम की गणना करना और सही तरीके से लौटाने के लिए क्या किया जाना चाहिए, इस पर एक और लेख लिखने का विचार है, जब लिखने की प्रेरणा मिलेगी।

सारांश

  • XDP का उपयोग करके ICMP ईको अनुरोध के जवाब में ICMP ईको उत्तर देने वाला XDP कार्यक्रम लागू किया है।
  • प्रक्रिया में, ICMP ईको अनुरोध का पता लगाने, उत्तर पैकेट को उत्पन्न करने एवं भेजने वाले और प्राप्तकर्ता के MAC पते और IP पते को बदलने तथा XDP_TX का उपयोग करके प्रत्यक्ष उत्तर देने का तरीका दिखाया गया है।
  • अंततः “गलत icmp cksum” नामक एक त्रुटि उत्पन्न हुई, जिससे पता चला कि ICMP चेकसम की पुनः गणना की आवश्यकता है।

अगले कदम (अपडेट: 06/03/2025)

त्वरित प्रारंभ गाइड: सुपर XDP परिचय भाग 3 (ICMP Echo Reply - भाग 2)