[FIN, ACK] Verbindung schließen

2fast4you87

Erfahrenes Mitglied
Hallo Leute,

habe mich mal wieder ein wenig mit Raw Sockets auseinander gesetzt und bin auf folgendes Problem gestoßen.

Aber zuerst :
- Programmiere mit Linux 10.0 (gcc) C

Wenn eine TCP / IP verbindung geschloßen werden soll, schickt der client ein FIN, ACK Paket an den Server, der Server nimmt das auf und schickt auch ein FIN, ACK Paket woer die ack + 1 setzt und die seq an den Client schickt. Der Client bestätigt das mit der ack + 1. Die Verbindung ist geschlossen.

Also könnte man doch an einen Server ein ACK;FIN paket schicken mit daddr,saddr,dport,sport , und den Server so auffordern die Verbindung zu schließen, nur dies bekomme ich leider nicht hin. hier mal mein Ansatz:

Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

int main(int argc, char *argv[])
{
	int 			s, bytes, on = 1;
	char 			buffer[1024];
	struct iphdr 		*ip;
	struct tcphdr		*tcp;
	struct sockaddr_in	to;
	struct in_addr		addr;
	
	if (argc != 4)
	{
		fprintf(stderr, "%s <dest-addr> <port> <wait>\n", argv[0]);
		return 1;
	}
	
	s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
	if (s == -1)
	{
		perror("socket() failed");
		return 1;
	}
	
	if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1)
	{
		perror("setsockopt() failed");
		return 2;
	}
	
	ip = (struct iphdr*) buffer;
	tcp = (struct tcphdr*) (buffer + sizeof(struct iphdr));
	
	memset(ip, 0, sizeof(struct iphdr));
	ip->version = 4;
	ip->ihl = 5;
	ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
	ip->id = random();
	ip->ttl = 255;
	ip->protocol = IPPROTO_TCP;
	ip->saddr = inet_addr("192.168.60.5");
	ip->daddr = inet_addr(argv[1]);
	
	memset(tcp, 0, sizeof(struct tcphdr));
	tcp->source = htons(1910);
	tcp->dest = htons(atol(argv[2]));
	tcp->seq = random();
	tcp->doff = 5;
	tcp->ack = 1;
	tcp->fin = 1;
	tcp->window = htons(65535);

        to.sin_addr.s_addr = ip->daddr;
        to.sin_family = AF_INET;
        to.sin_port = tcp->dest;

        printf("Ziel: %s:%i\n", inet_ntoa(to.sin_addr), ntohs(tcp->dest));
        addr.s_addr = ip->saddr;
        printf("Quelle: %s:%i\n", inet_ntoa(addr), ntohs(tcp->source));

	        bytes = sendto(s, buffer, ntohs(ip->tot_len), 0, &to, sizeof(to));
        	if (bytes == -1)
	{
        		perror("sendto() failed");
        		return 1;
        	}
        	putchar('.');
        	fflush(stdout);
        	
			
	return 0;
}
code abgeändert von http://www.zotteljedi.de

Er verschickt ACK, FIN Pakete, aber diese Pakete führen nicht zur beendigung der Verbindung! Habe genau den sport angeguckt mit netstat.

Könnt Ihr mir weiterhelfen ?


Gruß 2fast....
 
Ok, habe ein bisschen weiter geforscht,
Ich muss die TCP Checksum bilden, den algorythmus dazu habe ich aber ich brauch einen Pseudo Header für TCP, den ich mit den Daten von IP und TCP Len füllen muss.
Csum fkt :
Code:
unsigned short csum(unsigned short *addr, int len)
{
	int nleft = len;
	int sum = 0;
	unsigned short *w = addr;
	unsigned short answer = 0;

	while(nleft >1)
	{
		sum += *w++;
		nleft -=2;
	}

	if(nleft == 1)
	{
		*(unsigned char*) (&answer) = *(unsigned char *)w;
		sum += answer;
	}

	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);
	answer = ~sum;

	return answer;
}

Der Pseudo Header von TCP braucht :
Source IP Address
IP-Adresse des Absenders.
Destination IP Address
IP-Adresse des Empfängers.
00000000
Füllbits.
Protocol
Hat immer den Wert Sechs für das TCP-Protokoll (siehe auch IP-Header).
TCP Length
Länge des TCP-Segments in Bytes.


Mein Problem ist jetzt wenn ich den Pseudo Header in ein struct setze und ihn mit den Daten fülle, verschickt der nur noch ein IP Protocol ohne TCP.

Habt ihr ne Ahnung ?
 
Zurück