原始套接字SYN与数据包套接字SYN

时间:2017-04-06 18:43:50

标签: c++ linux tcp

我做了一个触发我问题的示例:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <time.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>

#include <iostream>

enum {
    IP_ERR
};

int main(int argc, char **argv) {
        int fd;
        sockaddr_ll device;
        // tcp and ip syn data
        unsigned char ipTcp[] = {0x45, 0x00, 0x00, 0x28, 0x23, 0xc6, 0x00, 0x00, 0x40, 0x06, 0x59, 0x08, 0x7f, 0x00, 0x00, 0x01,
                        0x7f, 0x00, 0x00, 0x01, 0x0f, 0xa1, 0x0b, 0xb8, 0x6b, 0x8b, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00,
                        0x50, 0x02, 0xaa, 0xaa, 0x3a, 0xea, 0x00, 0x00};

    // if any argument, send syn frame using packet socket
    // otherwise, send using raw socket
        bool asPacket = argc > 1;

        if (asPacket) {
            // send as packet
            fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
            if (fd == -1) {
                throw IP_ERR;
            }

            memset(&device, 0, sizeof(device));
            if (!(device.sll_ifindex = if_nametoindex("lo"))) {
                throw IP_ERR;
            }
            device.sll_family = AF_PACKET;
            device.sll_protocol = htons(ETH_P_IP);

            std::cout << sendto(fd, ipTcp, 40, 0, (struct sockaddr *) &device, sizeof(device)) << std::endl;

        } else {

            // send as raw socket
            fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
            if (fd == -1) {
                throw IP_ERR;
            }

            sockaddr_in sin;
            memset(&sin, 0, sizeof(sin));
            sin.sin_family = AF_INET;
            sin.sin_port = htons(3000);
            sin.sin_addr.s_addr = htonl(0x7f000001);
            std::cout << sendto(fd, ipTcp, 40, 0, (struct sockaddr *) &sin, sizeof(sin)) << std::endl;

        }
}

如果你在Linux上编译它并使用sudo运行,它将从端口4001上的127.0.0.1发送一个SYN到127.0.0.1到端口3000.这可以工作并显示在Wireshark中,Linux内核将自动发送RST端口3000,因为我们没有服务器。

但是,如果您将参数传递给此程序,它将发送完全相同的SYN但使用数据包套接字而不是原始套接字,这也将显示在Wireshark中,具有相同的内容(TCP / IP)。问题是,内核没有用RST响应,我不能让这个SYN从服务器触发任何SYN-ACK。我发送的数据包套接字似乎没有正确到达目标,即使我使用的接口“lo”是我机器上的环回接口。

这是为什么?数据包套接字是否也应该触发相同的RST响应?我无法得到它(数据包套接字)来触发任何类型的反应,即使它在Wireshark中显示为相同。

0 个答案:

没有答案