Hinweise
Transcription
Hinweise
IT-Sicherheit WS 07/08 Aufgabenblatt 10 1 TCP-Protokoll-Kapselung Beim Senden werden die Protokoll-Elemente eines Netz-Paketes auf unterschiedlichen System-Ebenen erstellt und gekapselt: Ethernet IP TCP Daten Betriebssystem / Netz-Adapter E T Netz-Adapter Betriebssystem, optional Anwendung (mit IP_HDRINCL) Anwendung Betriebssystem, optional Anwendung (mit SOCK_RAW) 2 FIN-Paket erstellen Analog zu Kapitel 7.5.1, Beispiel hier speziell für Linux: #define _BSD_SOURCE #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #define #define #define #define DEST_HOST DEST_PORT SOURCE_HOST SOURCE_PORT BSD-Version der Protokoll-Datentypen verwenden IP-Header-Definition und TCP-Header-Definition "192.168.0.2" 513 "192.168.0.1" 23300 3 Puffer / Zieladresse vorbereiten char buffer[4096]; struct ip *ihd = (struct ip *) buffer; struct tcphdr *thd = (struct tcphdr *) (buffer+sizeof(struct ip)); Schablone int buflen = sizeof(struct ip) + über den Puffer legen sizeof(struct tcphdr); memset(buffer,0,4096); // clear buffer Namensstruct sockaddr_in server; Auflösung server.sin_family = PF_INET; server.sin_addr.s_addr = inet_addr(DEST_HOST); server.sin_port = htons(DEST_PORT); 4 IP-Header füllen 0 vom System ausgefüllt in 32-Bit-Worten 8 4 Version IHL IPVERSION 5 16 19 24 Type Of Service Packet Length IPTOS_LOWDELAY Flags Packet Identifier Fragment Offset IP_DF Time To Live Protocol IPDEFTTL IPPROTO_TCP 31 Header Checksum Source Address SOURCE_HOST Destination Address DEST_HOST Achtung: Alle Werte in network byte order (Big-Endian) ! Zuweisung immer mit htons(short) bzw. htonl(long) 5 TCP-Header füllen 0 3 8 10 Source Port 16 SOURCE_PORT 24 Destination Port 31 DEST_PORT Sequence Number Acknowledgement Number Offset 5 0 U A P R S F R C S S Y I G K H T N N TCP Checksum Window Size Urgent Pointer Achtung: TCP-Prüfsumme muss manuell berechnet werden ! TCP-Paket wird sonst vor der Auswertung verworfen. 6 IP-Header füllen (Code) ihd->ip_v = IPVERSION; ihd->ip_id = htons(random()); ihd->ip_src.s_addr = inet_addr(SOURCE_HOST); ihd->ip_dst.s_addr = server.sin_addr.s_addr; ihd-> ... thd->th_sport thd->th_dport thd->th_flags thd->th_sum = thd-> ... = htons(SOURCE_PORT); = htons(DEST_PORT); = TH_FIN; ... 7 TCP/IP-Prüfsummen RFC 793: "The checksum field is the 16 bit one's complement of the one's complement sum of all 16-bit words in the header and text." Zur Erinnerung: ● Bei der Einerkomplement-Darstellung wird eine negative Zahl durch die bitweise Invertierung der positiven Zahl dargestellt ● Es gibt damit zwei Nullen: +0=00000000 und -0=11111111 ● Berechnung in C mit Operator ~ Einerkomplement-Addition auf Zweierkomplement-Maschine: Addiere Zahlen regulär, dann addiere Übertrag zum Ergebnis 1110 (-1 ) + 0011 ( 3 ) = 1 0001 ( 1!) + 0001 (carry) = 0010 ( 2 ) Übrigens: byteorder dabei unerheblich, da zyklische Operation! 8 Einerkomplement-Addition (Code) // add b to accumulator a void ocadd(u_short *a, u_short b) { u_int val = *a + b; // expand to int val += val >> 16; // add carry *a = (u_short)val; // reduce back to short } // add nelm elements of elm list to accumulator void ocsum(u_short *sum, u_short *elm, int nelm) { // count down elements, advance list pointer while (--nelm >= 0) ocadd(sum, *(elm++)); } // tcpsum = ~ ocsum( headerdata ) 9 TCP-Prüfsumme berechnen 0 3 8 10 inklusive PseudoHeader 0 3 16 Source Address SOURCE_HOST Destination Address DEST_HOST 8 IPPROTO_TCP 10 Source Port 31 TCP Length (Header+Data) Protocol 0 24 16 sizeof(struct 24 tcphdr) SOURCE_PORT Destination Port 31 DEST_PORT Sequence Number Acknowledgement Number Offset 5 U A P R S F R C S S Y I G K H T N N 0 0 Window Size Urgent Pointer 10 Paket abschicken (endlich!) // create raw IP socket int sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); // indicate that IP header is included in buffer int one = 1; // enable option setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)); und dann wiederholt: // ...construct TCP/IP message... // send message sendto(sockfd, buffer, buflen, 0, (struct sockaddr *)&server, sizeof(server)); 11 Pakete abhören mit libpcap ● Prozedur für packet sniffing aufwendig und plattform-spezifisch ● libpcap bietet plattformunabhängige Alternative ● inzwischen von fast allen Sniffern verwendet (tcpdump, ethereal, ...) ● Dokumentation: man 3 pcap ● Tutorial: http://www.tcpdump.org/pcap.htm char* dev; char errbuf[PCAP_ERRBUF_SIZE]; pcap_t* descr; bpf_u_int32 maskp; bpf_u_int32 netp; struct bpf_program fp; // // // // // // name of network device buffer for error messages packet capture handle subnet mask of device ip address of device compiled filter program 12 PCAP-Initialisierung // find the first suitable capture device dev = pcap_lookupdev(errbuf); if(dev==NULL) { printf("%s\n",errbuf); exit(1); } // determine network address and mask pcap_lookupnet(dev,&netp,&maskp,errbuf); // open device for reading descr = pcap_open_live(dev,CAPSIZE,1,-1,errbuf); gespeicherter Inhalt in Bytes, pro Paket abhören im promiscuous mode Pufferungs-Optimierung (nicht Lese-Timeout!) 13 Filter-Programme ● ● ● ● Filter-Programme ermöglichen effiziente Vorauswahl Komplexe Boolsche Kombinationen von Filtern möglich Nur übereinstimmende Pakete erreichen Anwendungs-Code Details der Filtersprache: man 1 tcpdump // define some filter program char* filter = "src host 192.168.0.1"; // compile the filter program, non-optimized pcap_compile(descr, &fp, filter, 0, netp); // set the compiled program as the filter pcap_setfilter(descr, &fp); 14 Paket-Behandlung Paket-Annahme einzeln: struct pcap_pkthdr header; const u_char* packet = pcap_next(descr, &header); ... oder kontinuierlich: alternativ: Behandle genau n Pakete pcap_loop(descr, -1, callback, NULL); optionales Argument void callback(u_char *args, const struct pcap_pkthdr* header, const u_char* packet) { // handle captured packet if (...) { pcap_close(descr); exit(0) } } 15 Timeouts Achtung, kontinuierliche Paket-Behandlung erlaubt keinen Timeout! Stattdessen z.B. Signal-Unterbrechung einstellen: signal(SIGALRM, timeout); alarm(5); // time in seconds pcap_loop(....); mit Behandlungs-Routine: void timeout(int sig) { // handle timeout signal(SIGALRM, timeout); timeout(5); // restart timer } 16 Ethernet-Header Empfangene Pakete enthalten komplette Protokoll-Elemente inklusive Ethernet-Header ! Definition: struct ether_header in <net/ethernet.h> 0 (Offset in Bytes) 6 Source MAC Address 12 Destination MAC Address 13 EtherType 00:11:22:33:44:55 aa:bb:cc:dd:ee:ff ETHERTYPE_IP(0x0800) 17