170 likes | 383 Views
Raw Socket e LIBPCAP. “vanilla” socket. int socket(int domain, int type, int protocol) domain PF_INET type SOCK_STREAM TCP SOCK_DGRAM UDP protocol 0 getprotobyname() /etc/protocols TCP (6) – UDP (17). raw socket. int socket(int domain, int type, int protocol) domain
E N D
“vanilla” socket int socket(int domain, int type, int protocol) • domain • PF_INET • type • SOCK_STREAM TCP • SOCK_DGRAM UDP • protocol • 0 • getprotobyname() /etc/protocols TCP (6) – UDP (17)
raw socket int socket(int domain, int type, int protocol) • domain • PF_INET • type • SOCK_RAW • protocol • IPPROTO_TCP / IPPROTO_UDP / IPPROTO_ICMP / IPPROTO_RAW (send only – implica IP_HDRINCL) [/usr/include/netinet/in.h] • TCP (0,6) / UDP (17) / ICMP (1)
Strutture /usr/include/netinet/ip.h struct ipheader { uchar ip_hl:4; // ip_hl: # of 32bit words (4bytes) uchar ip_v:4; uchar ip_tos; ushort ip_len; ushort ip_id; ushort ip_off; uchar ip_ttl; uchar ip_p; ushort ip_sum; uint ip_src; uint ip_dst; }; // total iphdr len 20 bytes
Strutture /usr/include/netinet/ip_icmp.h struct icmpheader { uchar icmp_type; uchar icmp_code; ushort icmp_cksum; ushort icmp_id; ushort icmp_seq; }; // icmp hdr len 8 bytes
Strutture /usr/include/netinet/udp.h struct udpheader { ushort uh_sport; ushort uh_dport; ushort uh_len; ushort uh_check; }; // udp hdr len 8 bytes
Strutture /usr/include/netinet/tcp.h struct tcpheader { ushort th_sport; ushort th_dport; uint th_seq; uint th_ack; // prev seq num ACK’d uchar th_x2:4, th_off:4; // x2 unused (zeroes) uchar th_flags; // URG | ACK | PSH | RST | … uint th_win; ushort th_sum; // on pseudohdr+tcphdr+payload ushort th_urp; }; // tcp hdr len 20 bytes
Lettura pacchetti • sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP) • read(sd, buffer, 8192) • ip = (struct iphdr *) buffer lettura campi ip (ipip_v / ipip_ttl / …) • tcp = (struct tcphdr *) (buffer+ipip_hl*4) lettura campi tcp (tcphdrth_flags / …) • data = buffer+(ipip_hl*4)+(tcpth_doff*4)
Scrittura pacchetti • sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP) • riempimento struct ipheader (NO checksum!!) • riempimento struct tcpheader (checksum = 0 – ci pensa il SO) • ORA devo calcolare ip checksum • int uno = 1; const int *val = &uno setsockopt (sd, IPPROTO_IP, IP_HDRINCL, val, sizeof (uno)
Riferimenti per raw socket • MAN Pages [http://www.die.net/doc/linux/man/] • ip(7) • raw(7) • setsockopt(2) • (socket(7)) • Includes in /usr/include/netinet • in.h / ip.h / tcp.h / udp.h / ip_icmp.h • http://unsecure.altervista.org/rawsocket/rawsocket.htm
Inizializzare una sessione (1) • Scelta dell’interfaccia dev = pcap_lookupdev(errbuf) • Ottenimento configurazione di rete result = pcap_lookupnet(dev, &net, &mask, errbuf) • Apertura della sessione handle = pcap_open_live(dev, snaplen, promisc, timeout, errbuf)
Inizializzare una sessione (2) • Compilazione del filtro… result = pcap_compile(handle, &filter, filter_exp, optimize, net) • …e applicazione del filtro stesso result = pcap_setfilter(handle, &filter) • Predisposizione del file di cattura dumper = pcap_dump_open(handle, filename)
Cattura • result = pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) result -2: Interrotto da pcap_breakloop() -1: Errore! 0: Interrotto perché “sniffati” cnt pacchetti • In alternativa: pcap_next(): “sniffa” un solo pacchetto pcap_dispatch(): “sniffa” un solo ‘burst’ di pacchetti
pcap_handler Callback • void packet_handler( u_char *user, const struct pcap_pkthdr *header, const u_char *packet ) Scrittura pacchetto: void pcap_dump(u_char *user, struct pcap_pkthdr *header, u_char *packet) Interruzione del loop di cattura: void pcap_breakloop(pcap_t *)
Chiusura sessione • Ottenimento statistiche sulla sessione pcap_stats(handle, *stats) • Chiusura della sessione di cattura pcap_close(handle) • Flushing dei dati e chiusura del file di dump pcap_dump_flush(dumper) pcap_dump_close(dumper)
Riferimenti per LIBPCAP • MAN Pages • pcap(3) • http://www.tcpdump.org/pcap.htm