Отправить полный пакет Ethernet на конкретный IP с помощью C ++ - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь отправить полный пакет на определенный IP-адрес. Дело в том, что у меня уже есть полный двоичный пакет, и я не хочу, чтобы он был инкапсулирован в какие-либо дополнительные заголовки пакетов. Вот моя логика:

std::string destination_ip = "127.0.0.1";
uint16_t destination_port = 8080;
int socket_fd;

struct sockaddr_in socket_attrs;

if ((socket_fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
{
    printf("Socket creation error\n");
    return false;
}

memset(&socket_attrs, '0', sizeof(socket_attrs));

socket_attrs.sin_family = AF_INET;
socket_attrs.sin_port = htons(destination_port);

if(inet_pton(AF_INET, destination_ip.c_str(), &socket_attrs.sin_addr)<=0)
{
    printf("Invalid IP address/ IP address not supported\n");
    return false;
}

if (connect(socket_fd, (struct sockaddr *)&socket_attrs, sizeof(socket_attrs)) < 0)
{
    printf("Connection Failed\n");
    return false;
}

if((write(socket_fd , <PACKET_DATA> , <PACKET_SIZE>)) < 0){
    std::cout << "Error sending packets to the network" << std::endl;
    exit(1);
}

Выход:

Connection Failed

Может ли кто-нибудь помочь мне достичь моей цели?

1 Ответ

0 голосов
/ 09 января 2019

Используйте libpcap, pcap_inject () , в частности.

Вы не можете использовать socket(), также используя IPPROTO_RAW, потому что L2 (eth) и L3 (ip) также будут подделаны стеком IP ОС в этом случае.

Вам необходимо внедрить пакет прямо в сетевую карту. Если вы хотите, чтобы он был доставлен на IP-адрес, отличный от исходного, вам необходимо «отредактировать» содержимое пакета.

Пример вставлен отсюда: http://www.microhowto.info/howto/send_an_arbitrary_ethernet_frame_using_libpcap.html

char pcap_errbuf[PCAP_ERRBUF_SIZE];
pcap_errbuf[0]='\0';

pcap_t* pcap=pcap_open_live(if_name,65536,0,0,pcap_errbuf);
if (pcap_errbuf[0]!='\0') {
    fprintf(stderr,"%s",pcap_errbuf);
}

if (!pcap) {
    exit(1);
}

if (pcap_inject(pcap, <PACKET_DATA> , <PACKET_SIZE> )==-1) {
    pcap_perror(pcap,0);
    pcap_close(pcap);
    exit(1);
}

pcap_close(pcap)

Если вы не хотите редактировать IP-адрес, пакет сможет достичь другого конца провода, только если у вас нет коммутаторов / маршрутизаторов между двумя узлами.

В качестве альтернативы ОП предлагает использовать туннель. Это на самом деле работает (я проверял это с tcpreplay) - вы можете использовать туннель GRE, который на самом деле может также транспортировать Ethernet-трафик.

На двух узлах вы можете установить туннель gretap . Я использовал эти команды:

на хосте A (его IP-адрес 192.168.1.211):

ip link add gretap1 type gretap local 192.168.1.211 remote 192.168.1.64
ip link set gretap1 up

на хосте B (его IP-адрес 192.168.1.64):

ip link add gretap1 type gretap local 192.168.1.64 remote 192.168.1.211
ip link set gretap1 up

На этом этапе можно использовать туннель L2 GRE и позволить ему транспортировать ETH-трафик с использованием интерфейсов gretap1. На одном узле я ввел трафик в туннель с помощью команды:

tcpreplay -i gretap1 test.pcap

и другой узел подтвердил, что трафик был передан, перехватив его через интерфейс gretap1 с помощью wireshark или tcpdump.

К сожалению, есть проблема с этой настройкой: MTU туннеля меньше, чем MTU сети, поэтому не гарантируется, что вы можете воспроизвести все пакеты.

...