Introduction to rawsockets
Mathias Hablützel 29 May 2013
Mathias Hablützel Rawsockets 29 May 2013 1 / 34
Introduction to rawsockets Mathias Habltzel 29 May 2013 Mathias - - PowerPoint PPT Presentation
Introduction to rawsockets Mathias Habltzel 29 May 2013 Mathias Habltzel Rawsockets 29 May 2013 1 / 34 What is rawsocket Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw
Mathias Hablützel 29 May 2013
Mathias Hablützel Rawsockets 29 May 2013 1 / 34
Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers.
— raw(7)
If we want something other than UDP/TCP, like ICMPv4/6 or IGMPv4. Packet sockets are used to receive or send raw packets at the device driver (OSI Layer 2) level. They allow the user to implement protocol modules in user space on top of the physical layer.
— packet(7)
If we want full controll about everything higher than the phy-layer.
Mathias Hablützel Rawsockets 29 May 2013 2 / 34
Not covering other operating systems or even POSIX/BSD/whatever
Disclaimer
Mathias Hablützel Rawsockets 29 May 2013 3 / 34
◮ IP datagrams unknown to the kernel ◮ icmpv4/6, igmpv4 ◮ full controll from layer 2 upward
Mathias Hablützel Rawsockets 29 May 2013 4 / 34
basically wireing the socket to the interface
write/send instead of sendto
Mathias Hablützel Rawsockets 29 May 2013 6 / 34
rawsocket on layer 2
i n t sock_eth = 0 ; sock_eth = s o c k e t (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL ) ) ;
rawsocket for IPv4 protocols
i n t sock_ip = 0 ; sock_ip = s o c k e t (AF_INET , SOCK_RAW, <p r o t o c o l −id >);
<protocol-id> as defined in RFC 1700 under ’PROTOCOL NUMBERS’
Mathias Hablützel Rawsockets 29 May 2013 8 / 34
socket(2)
#include <sys/socket.h> sockfd = socket(int socket_family, int socket_type, int protocol); As defined in <sys/sockets.h>: Name Purpose Man page AF_UNIX, AF_LOCAL Local communication unix(7) AF_INET IPv4 & Internet protocols ip(7) AF_INET6 IPv6 Internet protocols ipv6(7) AF_IPX IPX - Novell protocols AF_NETLINK Kernel user interface device netlink(7) AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7) AF_AX25 Amateur radio AX.25 protocol AF_ATMPVC Access to raw ATM PVCs AF_APPLETALK Appletalk ddp(7) AF_PACKET Low level packet interface packet(7)
Mathias Hablützel Rawsockets 29 May 2013 9 / 34
ip(7)
#include <sys/socket.h> sockfd = socket(AF_INET, int socket_type, int protocol); As defined in <bits/sockets.h >: Name Protocol Purpose SOCK_STREAM TCP Sequenced, reliable, connection-based SOCK_DGRAM UDP Connectionless, unreliable datagrams SOCK_RAW Raw Raw protocol interface
Mathias Hablützel Rawsockets 29 May 2013 11 / 34
tcp(7) resp. udp(7)
#include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> /* only for SOCK_STREAM */ sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd = socket(AF_INET, SOCK_DGRAM, 0 A few notes (won’t cover this in detail): Direction Required calls
connect(2) inbound bind(2), listen(2) and finally accept(2)
Mathias Hablützel Rawsockets 29 May 2013 12 / 34
packet(7)
#include <sys/socket.h> #include <netpacket/packet.h> #include <net/ethernet.h> /* for L2 */ sockfd = socket(AF_PACKET, int socket_type, int protocol); As defined in <bits/sockets.h >: Name Purpose SOCK_DGRAM cooked packets with the link level header removed SOCK_RAW raw packets including the link level header
Mathias Hablützel Rawsockets 29 May 2013 14 / 34
packet(7)
#include <sys/socket.h> #include <netpacket/packet.h> #include <net/ethernet.h> /* for L2 */ sockfd = socket(AF_PACKET, SOCK_RAW, int protocol); As defined in <linux/if_ether.h > (excerpt): Name Purpose ETH_P_IP Internet Protocol packet ETH_P_8021Q 802.1Q VLAN Extended Header ETH_P_FCOE Fibre Channel over Ethernet ETH_P_802_3 Dummy type for 802.3 frames ETH_P_ALL Every packet (be careful!!!)
Pitfall!
Always bear in mind that network-byte-order and host-byte-order may not necessarily be the same. Use htons(3) for this purpose:
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); Mathias Hablützel Rawsockets 29 May 2013 15 / 34
The only interesting option to set: rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); int one = 1; setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one));
Pitfall!
IP_HDRINCL only exists with AF_INET!
Mathias Hablützel Rawsockets 29 May 2013 17 / 34
◮ not set: kernel will build the IP header and prepend it ◮ set: the packet must contain the IP header
◮ IPPROTO_RAW implies enabled IP_HDRINCL! ◮ IP Identification == 0 → kernel sets this ◮ IP options may or may not be included ◮ IP checksum (RFC 1701) always calculate by kernel
But YOU are responsible for checksums in higher layers!
AF_PACKET requires you to calculate every checksum.
Mathias Hablützel Rawsockets 29 May 2013 18 / 34
Basically wiring the socket to an interface:
get interface index
c h a r ∗ i f a c e = " eth0 " ; s t r u c t i f r e q ∗ i f i n f o = m a l l o c ( s i z e o f ( s t r u c t i f r e q ) ) ; memset ( i f i n f o , 0 , s i z e o f ( s t r u c t i f r e q ) ) ; s t r n c p y ( i f i n f o − >ifr_name , i f a c e , IFNAMSIZ ) ; i o c t l ( sock_eth , SIOCGIFINDEX , i f i n f o ) ; /∗ < − − − − ∗/
bind socket to specific interface
s t r u c t s o c k a d d r _ l l s i n f o ; memset(& s i n f o , 0 , s i z e o f ( s i n f o ) ) ; s i n f o . s l l _ f a m i l y = PF_PACKET; s i n f o . s l l _ p r o t o c o l = htons (ETH_P_ALL) ; s i n f o . s l l _ i f i n d e x = i f i n f o − >i f r _ i f i n d e x ; bind ( sock , ( s t r u c t sockaddr ∗) &s i n f o , s i z e o f ( s t r u c t s o c k a d d r _ l l ) ) ; /∗ < − − ∗/ Mathias Hablützel Rawsockets 29 May 2013 20 / 34
Connect the socket to remote end (only with AF_INET → SOCK_STREAM,SOCK_DGRAM)
connect(2)
#include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Mathias Hablützel Rawsockets 29 May 2013 22 / 34
/wo connect /w connect send(2 sendto(2) sendto(2) sendmsg(2) sendmsg(2) write(2) writev(2)
Mathias Hablützel Rawsockets 29 May 2013 23 / 34
◮ TCP/UDP packets are never passed to a raw socket
Process must listen to data link layer to list to TCP/UDP
◮ most icmp messages and all igmp messages are passed to the raw socket ◮ all IP datagrams unknown to the kernel are passed to the raw socket, only
verification of IP version, IP header checksum, header length and destination address occurs
◮ fragments are first reassembled and then passed on to the raw socket
Mathias Hablützel Rawsockets 29 May 2013 24 / 34
Datagram gets passed to each socket as a copy, if all following conditions are true:
and
address
must match in the datagram
Mathias Hablützel Rawsockets 29 May 2013 25 / 34
◮ If a socket is created with a protocol := 0 and no bind(2)/connect(2)
◮ Every datagram passed to a raw socket will contain the entire datagram +
the IPv4 header.
◮ For IPv6 only the payload will be passed on.
Mathias Hablützel Rawsockets 29 May 2013 26 / 34
sock_eth = s o c k e t (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL ) ) ; /∗ get i n t e r f a c e i n d e x ∗/ i f i n f o = m a l l o c ( s i z e o f ( s t r u c t i f r e q ) ) ; memset ( i f i n f o , 0 , s i z e o f ( s t r u c t i f r e q ) ) ; s t r n c p y ( i f i n f o − >ifr_name , i f a c e , IFNAMSIZ ) ; i o c t l ( sock_eth , SIOCGIFINDEX , i f i n f o ) ; /∗ bind s o c k e t to s p e c i f i c i n t e r f a c e ∗/ memset(& s o c k i n f o , 0 , s i z e o f ( s o c k i n f o ) ) ; s o c k i n f o . s l l _ f a m i l y = PF_PACKET; s o c k i n f o . s l l _ p r o t o c o l = htons (ETH_P_ALL) ; s o c k i n f o . s l l _ i f i n d e x = i f i n f o − >i f r _ i f i n d e x ; bind ( sock_eth , ( s t r u c t sockaddr ∗) &s o c k i n f o , s i z e o f ( s t r u c t s o c k a d d r _ l l ) ) ; Mathias Hablützel Rawsockets 29 May 2013 27 / 34
/∗
i n p u t i s a raw e t h e r n e t frame ∗/ eth_hdr_in = ( s t r u c t ether_header ∗) buf_in ; eth_hdr_out = ( s t r u c t ether_header ∗) buf_out ; /∗ a f t e r the e t h e r n e t header comes the i p v 4 header ∗/ ip_hdr_in = ( s t r u c t i p ∗)( buf_in + s i z e o f ( s t r u c t ether_header ) ) ; ip_hdr_out = ( s t r u c t i p ∗)( buf_out + s i z e o f ( s t r u c t ether_header ) ) ; /∗ and f i n a l l y a f t e r the i p v 4 header comes the icmp packet ∗/ icmp_hdr_in = ( s t r u c t icmp ∗ ) ( ( u n s i g n e d c h a r ∗) ip_hdr_in + s i z e o f ( s t r u c t i p ) ) ; icmp_hdr_out = ( s t r u c t icmp ∗ ) ( ( u n s i g n e d c h a r ∗) ip_hdr_out + s i z e o f ( s t r u c t i p ) ) ; Mathias Hablützel Rawsockets 29 May 2013 28 / 34
w h i l e ( 1 ) { /∗ ICMP p r o c e s s i n g l o o p ∗/ /∗ r e a d i n g from the raw s o c k e t i n t o buf_in ∗/ r e c v f r o m ( sock_eth , buf_in , s i z e o f ( buf_in ) , 0 , NULL , NULL) ) /∗ i f we r e c e i v e d an ICMP and ICMP−Echo packet we c o n t i n u e ∗/ i f ( ip_hdr_in− >ip_p == IPPROTO_ICMP) { i f ( icmp_hdr_in− >icmp_type == ICMP_ECHO) { Mathias Hablützel Rawsockets 29 May 2013 29 / 34
/∗ we s w i t c h the MAC f i e l d s f o r s e n d i n g i t back ∗/ memcpy( eth_hdr_out− >ether_shost , eth_hdr_in− >ether_dhost , 6 ) ; memcpy( eth_hdr_out− >ether_dhost , eth_hdr_in− >ether_shost , 6 ) ; /∗ i t i s an i p v 4 packet we want to send back ∗/ eth_hdr_out− >ether_type = htons (ETH_P_IP ) ; Mathias Hablützel Rawsockets 29 May 2013 30 / 34
/∗ Prepare
IP header . ∗/ ip_hdr_out− >ip_v = ip_hdr_in− >ip_v ; ip_hdr_out− >ip_hl = ip_hdr_in− >ip_hl ; ip_hdr_out− >ip_tos = 0 ; ip_hdr_out− >ip_len = ip_hdr_in− >ip_len ; ip_hdr_out− >ip_id = ip_hdr_in− >ip_id ; /∗ we s e t the IP Don ’ t Fragment mask ∗/ ip_hdr_out− >i p _ o f f = htons (IP_DF ) ; ip_hdr_out− >i p _ t t l = 6 4 ; ip_hdr_out− >ip_p = IPPROTO_ICMP ; ip_hdr_out− >ip_sum = 0 ; /∗ we s w i t c h the d s t and s r c i p v 4 ∗/ ip_hdr_out− >i p _ s r c . s_addr = ip_hdr_in− >ip_dst . s_addr ; ip_hdr_out− >ip_dst . s_addr = ip_hdr_in− >i p _ s r c . s_addr ; /∗ c a l c u l a t e the i p header checksum ∗ bear i n mind t h a t ip_hl i s a double−word and the parameter ∗ wants a byte number (8 b i t s ) ∗/ ip_hdr_out− >ip_sum = rfc1701_cksum ( ( u n s i g n e d s h o r t ∗) ip_hdr_out , ip_hdr_out− >ip_hl ∗ 4 ) ; Mathias Hablützel Rawsockets 29 May 2013 31 / 34
/∗ Prepare
ICMP header . ∗/ icmp_hdr_out− >icmp_type = 0 ; icmp_hdr_out− >icmp_code = 0 ; icmp_hdr_out− >icmp_cksum = 0 ; icmp_hdr_out− >icmp_id = icmp_hdr_in− >icmp_id ; icmp_hdr_out− >icmp_seq = icmp_hdr_in− >icmp_seq ; ip_len = ntohs ( ip_hdr_out− >ip_len ) ; icmp_len = ip_len − s i z e o f ( s t r u c t i p ) ; icmp_data_len = icmp_len − s i z e o f ( s t r u c t icmphdr ) ; /∗ we j u s t need to echo the incoming data ∗/ memcpy( icmp_hdr_out− >icmp_data , icmp_hdr_in− >icmp_data , icmp_data_len ) ; /∗ f i n a l l y a l i t t l e checksum ∗/ icmp_hdr_out− >icmp_cksum = rfc1701_cksum ( ( u n s i g n e d s h o r t ∗) icmp_hdr_out , icmp_len ) ; Mathias Hablützel Rawsockets 29 May 2013 32 / 34
/∗ send i t
the w i r e ∗/ sendto ( sock_eth , buf_out , r e t , 0 , ( s t r u c t sockaddr ∗)& s o c k i n f o , s i z e o f ( s o c k i n f o ) ) ; } /∗ c l o s e i f ICMP_ECHO ∗/ } /∗ c l o s e i f IPPROTO_ICMP ∗/ } /∗ c l o s e while −l o o p ∗/
https://github.com/0x6d686b/rawsockets/ - Full source code available
Mathias Hablützel Rawsockets 29 May 2013 33 / 34
◮
linux man pages
◮
UNIX Network Programming, Volume 1 — W. Richard Stevens (ISBN: 978-0131411555)
◮
http://sock-raw.org/papers/sock_raw - In depth analysis on how the kernel handles the incoming packets Mathias Hablützel Rawsockets 29 May 2013 34 / 34