4
votes

I use raw socket to send TCP packets from Computer B to Computer A.

First, I create a socket

int s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);

and tell the kernel don't fill ip header for me because my data includes both ip header and tcp header

int optval = 1;
setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval));

and set the destination address

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(33333);
addr.sin_addr.s_addr = inet_addr("192.168.200.135");

and send the data

sendto(s, data, len, 0, (struct sockaddr*)&addr, sizeof(addr));

My network environment is as the figure below network environment

In Case A, two computers are connected by a switch. While in Case B, Computer B connects to a router, and the router connects to the switch.

My program works fine in Case A. I can use a raw socket to recieve the packet on Computer A, and can use wireshark to capture that packet.

In Case B, I can ping from Computer B to Computer A, and ssh from B to A. And I can use both raw socket and wireshark on Computer A to capture some TCP packet sent between B and A. However, the packets sent by my raw socket on Computer B can't be captured on A. It seems that the router doesn't forward my packet. Is there anything wrong with my packet?

My send program with packet data is as follows:

//data to send
char data[48] =
{
    //iphdr:
    0x45, 0x00, 0x00, 0x30, //version:4 header_length:5 TOS:0 length:0x30
    0x00, 0x01, 0x00, 0x00, //identification:1 flags:0 fragment_offset:0
    0x40, 0x06, 0x2f, 0x47, //TTL:0x40 protocol:6(TCP) header_checksum:0x2f47
    0xc0, 0xa8, 0x01, 0xa8, //source_IP:192.168.1.168
    0xc0, 0xa8, 0xc8, 0x87, //destination_IP:192.168.200.135
    //tcphdr:
    0x56, 0xce, 0x82, 0x35, //source_port:22222 destination_port:33333
    0x00, 0x00, 0x00, 0x00, //sequence_number:0
    0x00, 0x00, 0x00, 0x00, //ack_number:0
    0x50, 0x00, 0xaa, 0xaa, //header_length:5 window_size:0xaaaa
    0xeb, 0xbd, 0x00, 0x00, //checksum:0xebbd urgent_pointer:0
    //tcp content:
    0x7a, 0x68, 0x73, 0x00,
    0x39, 0x30, 0xce, 0x56, 
};
int len = 48;
//open the socket
int s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
//don't fill header
int optval = 1;
setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval));
//destination addr
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.200.135");
//send
sendto(s, data, len, 0, (struct sockaddr*)&addr, sizeof(addr));
2
Did you make sure that (i) you enabled IP forwarding at the router, and (ii) your program runs with root privileges (which is required for raw sockets)?mavam
Can you add the wireshark output of that packet? The 50 that you describe as header length is the data offset. Check tools.ietf.org/html/rfc793 - Finally, TCP is connection oriented, don't you want to use UDP instead?ott--
@MatthiasVallentin (i) IP forwarding is enabled, otherwise I can't ssh and ping from B to A (my router is CISCO WRVS4400N). (ii) I run my program as root, otherwise the return value of socket() will be -1.Haoshu
@ott-- In Case A, the wireshark output is the same as what I send, including a Ethernet header. While in Case B, wireshark can't capture that package. That article says tha Data Offset is "The number of 32 bit words in the TCP Header", which are the same. And I just want to test some feature of TCP.Haoshu
Finally, use a different address family (AF_PACKET instead IPPROTO_TCP) on the socket-call. See linux.die.net/man/2/socket for valid values. Is wireshark running on the sending PC?ott--

2 Answers

0
votes
  1. Router 192.168.1.1 should be your default router. Check your configuration in Machine A.
0
votes

Your TCP header is wrong, since it misses flags. For your test, you should at least set the SYN flag. There may be other things not correct with the header.

So if the router is actually inspecting the TCP header, it probably discards your packet. Inspecting the TCP header happens if your router is actually not routing but uses NAT for packet forwarding, or if there's a firewall that checks for ports or connection states.