Linux C Программа не будет отправлять пакеты через сетевое пространство имен с использованием сокетов AF_PACKET - PullRequest
0 голосов
/ 28 марта 2020

Я сделал программу пересылки, которая пересылает пакеты через IPIP. Как сервер пересылки, так и сервер назначения являются Linux виртуальными машинами под управлением Ubuntu 18.04 (управление виртуальными машинами осуществляется на хосте Proxmox). На машине, на которой пакеты пересылаются (10.50.0.4), IPIP-туннель конечной точки (10.2.0.5) и приложение находятся вместе в сетевом пространстве имен. Приложение привязывается к IP-адресу туннеля IPIP, а шлюзом по умолчанию является туннель IPIP. То, что я пытаюсь сделать sh, - приложение отправляет пакеты напрямую обратно клиентам, а IP-адрес источника подделывается как IP-адрес сервера пересылки, а не пакеты, возвращающиеся через туннель IPIP. Я хочу сделать это, чтобы на сервере пересылки было меньше нагрузки, а время ожидания в целом меньше (например, пакетам из приложения не нужно будет go возвращаться через сервер пересылки).

Сначала я попытался создание пары veth и размещение однорангового узла в пространстве имен сети. Затем я создал мост в пространстве имен по умолчанию и назначил ему IP (10.2.0.1/16). С этого момента я подключил veth к пространству имен по умолчанию и создал правило SNAT в цепочке POSTROUTING IPTable под таблицей NAT для 10.2.0.0/16, источником которого является IP-адрес сервера пересылки (10.50.0.3). Я установил маршрут к пространству имен для ветерана и следующий переход (IP-адрес моста, 10.2.0.1). В то время как приложение могло отправлять исходящие пакеты через пару veth, которая была получена в качестве IP-адреса сервера пересылки, приложение все еще не работало должным образом. Я думаю, это потому, что приложение не поддерживает привязку к нескольким интерфейсам (туннель IPIP для получения и интерфейс маршрута по умолчанию, ветерар для отправки). К сожалению, это приложение с закрытым исходным кодом.

С учетом вышесказанного я решил попробовать создать программу C с использованием сокетов AF_PACKET. Маршрут по умолчанию в пространстве имен установлен для туннеля IPIP. Однако у меня все еще есть пара веток, связанная с пространством имен. Принимающий сокет захватывает все пакеты в туннеле IPIP (включая исходящие пакеты), а отправляющий сокет связывается с ветеринарным узлом в пространстве имен. Когда принимающий сокет перехватывает пакет, он проверяет исходный IP-адрес, и если это IP-адрес туннеля IPIP, это означает, что туннель IPIP отправляет этот пакет обратно. Поэтому я изменяю исходный IP-адрес на сервер пересылки и пытаюсь отправить его ветерану. Я также блокирую исходные пакеты, возвращающиеся на сервер пересылки через IPTables (iptables -A OUTPUT -d <forwarding server IP> -j DROP). Вот код программы:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/ethernet.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include <inttypes.h>
#include <pthread.h>
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <ctype.h>

#define REDIRECT_HEADER

#include "csum.h"

#define MAX_PCKT_LENGTH 65535

#define PACKET_MASK_ANY 0xffffffff

#define PACKET_OUTGOING 4

#define PACKET_RECV_TYPE 18

static int cont = 1;
static unsigned char sMAC[ETH_ALEN];
static unsigned char dMAC[ETH_ALEN];

void signHdl(int tmp)
{
    cont = 0;
}

void GetGatewayMAC()
{
    char cmd[] = "ip neigh | grep \"$(ip -4 route list 0/0 | cut -d' ' -f3) \" | cut -d' ' -f5 | tr '[a-f]' '[A-F]'";

    FILE *fp =  popen(cmd, "r");

    if (fp != NULL)
    {
        char line[18];

        if (fgets(line, sizeof(line), fp) != NULL)
        {
            sscanf(line, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &dMAC[0], &dMAC[1], &dMAC[2], &dMAC[3], &dMAC[4], &dMAC[5]);
        }

        pclose(fp);
    }
}

void shiftChar(char *arr, int size, int dataLen)
{
    for (int16_t i = (dataLen - 1); i >= 0; i--)
    {
        memmove(arr + i + size, arr + i, 1);
    }

    for (int16_t i = 0; i < size; i++)
    {
        memcpy(arr + i, "0", 1);
    }
}

void removeChar(char *arr, int size, int dataLen)
{
    for (int16_t i = 0; i < dataLen; i++)
    {
        memmove(arr + i, arr + size + i, 1);
    }

    for (int16_t i = 0; i < size; i++)
    {
        memcpy(arr + size + dataLen - i, "0", 1);
    }
}

int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        perror("main");

        exit(1);
    }

    int sockfd, sendsockfd;
    uint8_t type;   // 1 = normal interface (includes Ethernet headers). 2 = IPIP tunnel (doesn't include Ethernet headers).
    struct sockaddr_ll a, b, din;
    socklen_t dinLen = sizeof(din);

    if (argc > 3)
    {
        type = atoi(argv[3]);
    }

    a.sll_family = PF_PACKET;
    a.sll_ifindex = if_nametoindex(argv[1]);
    a.sll_protocol = htons(ETH_P_ALL);
    a.sll_halen = ETH_ALEN;

    b.sll_family = PF_PACKET;
    b.sll_ifindex = if_nametoindex("veth2");
    b.sll_protocol = htons(ETH_P_IP);
    b.sll_halen = ETH_ALEN;

    sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    sendsockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);

    if (sockfd < 0 || sendsockfd < 0)
    {
        perror("socket");

        exit(1);
    }

    int v=0;
    v = PACKET_MASK_ANY & ~(1<<PACKET_OUTGOING) & ~(1 << PACKET_LOOPBACK);
    setsockopt(sockfd, SOL_PACKET, PACKET_RECV_TYPE, &v, sizeof(v));

    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    strcpy(ifr.ifr_name, "veth2");

    if (ioctl(sendsockfd, SIOCGIFHWADDR, &ifr) != 0)
    {
        perror("ioctl");

        exit(1);
    }

    memcpy(a.sll_addr, ifr.ifr_addr.sa_data, ETH_ALEN);
    memcpy(sMAC, a.sll_addr, ETH_ALEN);
    GetGatewayMAC();

    if (bind(sockfd, (struct sockaddr *)&a, sizeof(a)) < 0)
    {
        perror("bind");

        exit(1);
    }

    if (bind(sendsockfd, (struct sockaddr *)&b, sizeof(b)) < 0)
    {
        perror("bind");

        exit(1);
    }

    signal(SIGINT, signHdl);

    printf("Source MAC => ");

    for(uint8_t i = 0; i < ETH_ALEN; i++)
    {
        printf("%02x", sMAC[i]);

        if (i != 5)
        {
            printf(":");
        }
    }

    printf("\n");

    printf("Destination MAC => ");

    for(uint8_t i = 0; i < ETH_ALEN; i++)
    {
        printf("%02x", dMAC[i]);

        if (i != 5)
        {
            printf(":");
        }
    }

    printf("\n\n");


    while (cont)
    {
        unsigned char buffer[MAX_PCKT_LENGTH];

        uint16_t recv;

        if ((recv = recvfrom(sockfd, &buffer, MAX_PCKT_LENGTH, 0, (struct sockaddr *)&din, &dinLen)) < 1)
        {
            perror("recvfrom");
            continue;
        }

        struct ethhdr *ethhdr;
        struct iphdr *iphdr;
        struct udphdr *udphdr;

        if (type == 1)
        {
            ethhdr = (struct ethhdr *) (buffer);
            iphdr = (struct iphdr *) (buffer + sizeof(struct ethhdr));
            udphdr = (struct udphdr *) (buffer + sizeof(struct ethhdr) + (iphdr->ihl * 4));
        }
        else
        {
            iphdr = (struct iphdr *) (buffer);
            udphdr = (struct udphdr *) (buffer + (iphdr->ihl * 4));      
        }

        if (type != 1)
        {
            shiftChar(buffer, sizeof(struct ethhdr), ntohs(iphdr->tot_len));

            ethhdr = (struct ethhdr *) (buffer);
            iphdr = (struct iphdr *) (buffer + sizeof(struct ethhdr));
            udphdr = (struct udphdr *) (buffer + sizeof(struct ethhdr) + (iphdr->ihl * 4));

            //memcpy(ethhdr->h_source, sMAC, ETH_ALEN);
            //memcpy(ethhdr->h_dest, dMAC, ETH_ALEN);

            ethhdr->h_source[0] = 0x82;
            ethhdr->h_source[1] = 0xB3;
            ethhdr->h_source[2] = 0x6F;
            ethhdr->h_source[3] = 0x24;
            ethhdr->h_source[4] = 0x0E;
            ethhdr->h_source[5] = 0x74;

            ethhdr->h_dest[0] = 0x96;
            ethhdr->h_dest[1] = 0xF0;
            ethhdr->h_dest[2] = 0xB6;
            ethhdr->h_dest[3] = 0xDC;
            ethhdr->h_dest[4] = 0xE5;
            ethhdr->h_dest[5] = 0x1A;
            ethhdr->h_proto = htons(ETH_P_IP);

            if (iphdr->saddr == inet_addr(argv[2]) && iphdr->protocol == IPPROTO_UDP)
            {
                printf("Sending out %d bytes from %s => %s. %d is version. %d is port. XDDD\n", recv, inIP, outIP, iphdr->version, ntohs(udphdr->dest));

                // Change source IP
                uint32_t oldAddr = iphdr->saddr;
                iphdr->saddr = inet_addr("10.50.0.3");

                struct in_addr in;
                in.s_addr = iphdr->saddr;
                char inIP[16];
                strcpy(inIP, inet_ntoa(in));
                struct in_addr out;
                out.s_addr = iphdr->daddr;
                char outIP[16];
                strcpy(outIP, inet_ntoa(out));

                // Recalculate checksumz.
                iphdr->check = csum_diff4(oldAddr, iphdr->saddr, iphdr->check);
                udphdr->check = 0;
                udphdr->check = csum_tcpudp_magic(iphdr->saddr, iphdr->daddr, ntohs(udphdr->len), IPPROTO_UDP, csum_partial(udphdr, ntohs(udphdr->len), 0));
                //udphdr->check = csum_diff4(oldAddr, iphdr->saddr, udphdr->check);

                uint16_t sent;

                if ((sent = write(sendsockfd, buffer, ntohs(iphdr->tot_len) + sizeof(struct ethhdr))) < 1)
                {
                    perror("write");
                    continue;
                }

                printf("Sent %d (%lu) back %s => %s.\n\n", sent, ntohs(iphdr->tot_len) + sizeof(struct ethhdr), inIP, outIP);
            }
        }
    }
    close(sockfd);

    exit(0);
}

Имейте в виду, что в вышеуказанной программе много бесполезного кода, так как я пытался протестировать несколько вещей. При этом при захвате пакетов в туннеле IPIP с использованием сокетов AF_PACKET он не включает заголовок Ethe rnet. Я полагаю, что это сделано специально, поскольку захват на любом другом интерфейсе системы включает заголовки Ethe rnet. Вот как я выполняю программу в пространстве имен:

root@test03:/home/roy# ip netns exec server01 ./af_packet_ipip ipip01 10.2.0.5 2

Вот информация об интерфейсе на хост-машине (пространство имен по умолчанию) вместе с пространством имен, внутри которого работает туннель IPIP и приложение:

root@test03:/home/roy# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether ae:21:14:4b:3a:6d brd ff:ff:ff:ff:ff:ff
    inet 10.50.0.4/24 brd 10.50.0.255 scope global dynamic ens18
       valid_lft 68316sec preferred_lft 68316sec
    inet6 fe80::ac21:14ff:fe4b:3a6d/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:49:df:c2:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
7: veth1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master idk state UP group default qlen 1000
    link/ether 96:f0:b6:dc:e5:1a brd ff:ff:ff:ff:ff:ff link-netnsid 0
11: idk: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 96:f0:b6:dc:e5:1a brd ff:ff:ff:ff:ff:ff
    inet 10.2.0.1/16 scope global idk
       valid_lft forever preferred_lft forever

root@test03:/home/roy# ip netns exec server01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
5: ipip01@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 peer 10.50.0.3 link-netnsid 0
    inet 10.2.0.5/16 scope global ipip01
       valid_lft forever preferred_lft forever
6: veth2@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 82:b3:6f:24:0e:74 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.2.0.4/16 scope global veth2
       valid_lft forever preferred_lft forever

root@test03:/home/roy# ip route
default via 10.50.0.1 dev ens18 proto dhcp src 10.50.0.4 metric 100
10.2.0.0/16 dev idk proto kernel scope link src 10.2.0.1
10.50.0.0/24 dev ens18 proto kernel scope link src 10.50.0.4
10.50.0.1 dev ens18 proto dhcp scope link src 10.50.0.4 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown

root@test03:/home/roy# ip netns exec server01 ip route
default dev ipip01 scope link
10.2.0.0/16 dev veth2 proto kernel scope link src 10.2.0.4
10.2.0.0/16 dev ipip01 proto kernel scope link src 10.2.0.5

Пакеты отправляются обратно на мост (idk), и вот TCPDump, показывающий это:

root@test03:/home/roy# tcpdump -i idk dst host 10.xxx.xxx.xxx -nne
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on idk, link-type EN10MB (Ethernet), capture size 262144 bytes
17:14:48.529043 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:50.224207 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:52.024256 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 147: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 105
17:14:52.234143 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:52.519119 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:54.529119 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:55.024089 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 147: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 105
17:14:55.234171 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:56.524109 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:14:57.229134 82:b3:6f:24:0e:74 > 96:f0:b6:dc:e5:1a, ethertype IPv4 (0x0800), length 51: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9

Эти пакеты отправляются обратно на мой компьютер (10.xxx.xxx.xxx). Однако мой компьютер не получает эти пакеты, и я не могу подключиться к приложению. Вот захват пакета с использованием значения интерфейса any:

root@test03:/home/roy# tcpdump -i any udp and src host 10.50.0.3 and dst host 10.xxx.xxx.xxx -nne
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
17:18:15.214170  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:15.214205  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:16.519127  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:16.519153  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:17.014107  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 149: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 105
17:18:17.014132  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 149: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 105
17:18:17.224127  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:17.224151  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:18.514150  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:18.514208  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:19.219091  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9
17:18:19.219115  In 82:b3:6f:24:0e:74 ethertype IPv4 (0x0800), length 53: 10.50.0.3.27015 > 10.xxx.xxx.xxx.7130: UDP, length 9

Я пытался использовать разные адреса MA C источника и назначения для заголовка Ethe rnet. В настоящее время адрес источника MA C устанавливается равным адресу MA C партнера ветхого обмена внутри пространства имен, а адрес назначения MA C устанавливается равным veth / bridge в пространстве имен по умолчанию. Когда я сделал захват пакета, когда маршрут по умолчанию в пространстве имен был установлен равным veth peer вместе со следующим переходом (IP-адрес моста), это были используемые адреса источника и назначения MA C. Я также попытался установить адреса источника и назначения MA C в 0, чтобы увидеть, если это что-то делает. С учетом вышесказанного я попытался установить адрес назначения MA C в адрес MA C основного шлюза. Однако ничего из этого не сработало.

Я также попытался установить правила POSTROUTING для маскировки и SNAT. Вот некоторые из них, которые я пробовал:

Chain POSTROUTING (policy ACCEPT 9 packets, 640 bytes)
 pkts bytes target     prot opt in     out     source               destination
   79  5056 SNAT       all  --  *      *       10.2.0.0/16          0.0.0.0/0            to:10.50.0.3
    0     0 SNAT       all  --  *      idk     0.0.0.0/0            0.0.0.0/0            to:10.50.0.3
    0     0 SNAT       all  --  *      veth1   0.0.0.0/0            0.0.0.0/0            to:10.50.0.3
    0     0 MASQUERADE  all  --  *      *       10.50.0.3            0.0.0.0/0

Ничего из этого не сработало. Я не уверен, что мне понадобится какое-то правило POSTROUTING, чтобы моя программа отправляла пакеты через пару / мост veth (но также подделывалась как IP-адрес сервера переадресации).

Я подтвердил контрольные суммы заголовков IP / UDP также правильны для этих пакетов.

Дополнительные примечания / вопросы:

  1. Как только я выясняю основную проблему, я не уверен, что Лучший способ получить правильные адреса источника и назначения MA C для заголовка Ethe rnet автоматически. По какой-то причине моя функция получить адрес источника MA C от однорангового узла не работает, и я привык задавать адрес назначения MA C для адреса шлюза MA C (который равен всем 0 внутри пространство имен сети). Любые предложения приветствуются!

  2. Вышеприведенная программа создается для целей тестирования, и я просто хочу посмотреть, сработает ли моя теория. Если я могу заставить это работать, я хочу найти более быстрое решение, чем сокеты AF_PACKET. Сокеты AF_PACKET получают копию пакета от ядра, насколько я понимаю. Следовательно, это приведет к увеличению нагрузки. Я хочу найти способ перехвата всех исходящих пакетов в туннеле IPIP и изменить сам исходный пакет перед отправкой его через ветеринарный узел в пространстве имен сети. Если у вас есть какие-либо предложения для этого, не стесняйтесь, дайте мне знать! Я хотел начать искать DPDK для этого, но я не думаю, что DPDK сможет подключаться к туннелю IPIP вместе с интерфейсом, к которому уже привязано приложение. Насколько я понимаю, это требует специального NI C.

Мне было интересно, если кто-нибудь знает, что я пропускаю или делаю здесь неправильно. Я бы предположил, что либо отсутствует правило IPTables, либо мои исходные / конечные адреса MA C неверны в отправляемом мной заголовке Ethe rnet.

Если вам нужна дополнительная информация, пожалуйста, дайте мне знать!

Любая помощь очень ценится и спасибо за ваше время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...