Approximately year ago I wrote an article “Wiresharking TCP Split Handshake Attack“. Normally client/server application written on socket level does not permit to split handshaking. For example TCP client connect function initiates a connection on a socket and performs all 3 handshaking step. Handshaking process is hidden in Transport layer of ISO model. To manipulate with handshaking signals application must be able to send and receive raw packets and for this purpose raw socket is used.
There is opinion that raw socket is source of malicious software. Yes it is true, but it the same time raw socket opens opportunity to learn protocol internals, experimenting, test firewall and routers.
Here is c++ example of raw socket application (rawsock.cpp) which sends SYN signal to server and does not wait for ACK-SYN response, besides it specifies real source IP with loopback IP address – 127.0 0.1:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <netinet/in.h> #include <sys/socket.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <unistd.h> int main(int n, char ** s) { if(n<3) { printf("Arguments are required: destination ip and destination port, space separated, order is important\n"); return -1; } int destport = atoi(s[2]); printf("Destination end point: %s:%d\n", s[1], destport); int sckt; struct sockaddr_in saddr; struct send_tcp { struct iphdr ip; struct tcphdr tcp; } packtcp; packtcp.ip.version = 4; /* version of IP used */ packtcp.tcp.source = htons(2000); /* source port */ saddr.sin_family = AF_INET; sckt = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if(sendto(sckt, &packtcp, sizeof(packtcp), 0, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) close(sckt); |
Testing using tcpdump:
From one Linux box I ran 3 time rawsock application:
# ./rawsock 192.168.2.59 22 Destination end point: 192.168.2.59:22 # ./rawsock 192.168.2.59 22 Destination end point: 192.168.2.59:22 # ./rawsock 192.168.2.59 22 Destination end point: 192.168.2.59:22 |
Other Linux box tcpdump captured SYN signals:
# tcpdump -n src 127.0.0.1 && 'tcp[13] & 12!=0' && 'ip[8]==255' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on ens160, link-type EN10MB (Ethernet), capture size 262144 bytes 16:22:44.486301 IP 127.0.0.1.2000 > 192.168.2.59.22: Flags [S], seq 16777216, win 512, length 0 16:22:45.588872 IP 127.0.0.1.2000 > 192.168.2.59.22: Flags [S], seq 16777216, win 512, length 0 16:22:46.514978 IP 127.0.0.1.2000 > 192.168.2.59.22: Flags [S], seq 16777216, win 512, length 0 |
Explanation of tcpdump parameters:
Parameter | Line of c++ code | Comment |
---|---|---|
src 127.0.0.1 | inet_addr("127.0.0.1"); | |
tcp[13] & 12!=0 | packtcp.tcp.syn = 1; | rawsock sends SYN only, tcpdump checks SYN and ACK |
ip[8]==255 | packtcp.ip.ttl = 255; | tcpdump verifies also TTL |