Introduction to rawsockets Mathias Habltzel 29 May 2013 Mathias - - PowerPoint PPT Presentation

introduction to rawsockets
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 1

Introduction to rawsockets

Mathias Hablützel 29 May 2013

Mathias Hablützel Rawsockets 29 May 2013 1 / 34

slide-2
SLIDE 2

What is rawsocket

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

slide-3
SLIDE 3

Not covering other operating systems or even POSIX/BSD/whatever

Linux only! >2.6.*

Disclaimer

Not all base covered! Much is left out!

Mathias Hablützel Rawsockets 29 May 2013 3 / 34

slide-4
SLIDE 4

When to use rawsockets

◮ IP datagrams unknown to the kernel ◮ icmpv4/6, igmpv4 ◮ full controll from layer 2 upward

Mathias Hablützel Rawsockets 29 May 2013 4 / 34

slide-5
SLIDE 5

Let’s get started

  • 1. create socket
  • 2. set socket options (if needed)
  • 3. bind name to socket, gives source "IP"

basically wireing the socket to the interface

  • 4. connect to remote IP; though rarely used but allows to use

write/send instead of sendto

Mathias Hablützel Rawsockets 29 May 2013 6 / 34

slide-6
SLIDE 6

Let’s get started

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

slide-7
SLIDE 7

Let’s get started — Explained

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

slide-8
SLIDE 8

Let’s get started — Explained (AF_INET)

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

slide-9
SLIDE 9

Let’s get started — Explained (AF_INET)

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

  • utbound

connect(2) inbound bind(2), listen(2) and finally accept(2)

Mathias Hablützel Rawsockets 29 May 2013 12 / 34

slide-10
SLIDE 10

Let’s get started — Explained (AF_PACKET)

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

slide-11
SLIDE 11

Let’s get started — Explained (AF_PACKET)

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

slide-12
SLIDE 12

Socket options

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

slide-13
SLIDE 13

Socket options — IP_HDRINCL

◮ 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

slide-14
SLIDE 14

Binding the socket

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

slide-15
SLIDE 15

Connect the socket

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

slide-16
SLIDE 16

Sending

/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

slide-17
SLIDE 17

Receiving

◮ 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

slide-18
SLIDE 18

Receiving

Datagram gets passed to each socket as a copy, if all following conditions are true:

  • 1. non-zero protocol specified: socket(..., ..., proto);

and

  • 2. matching protocol ID
  • 3. locally bound IP address to raw socket must match the received datagrams

address

  • 4. if remote address was specified by connect(2) then the sender address

must match in the datagram

Mathias Hablützel Rawsockets 29 May 2013 25 / 34

slide-19
SLIDE 19

Receiving

◮ If a socket is created with a protocol := 0 and no bind(2)/connect(2)

  • ccurred, this socket will receive a copy of every datagram the kernel passes
  • n.

◮ 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

slide-20
SLIDE 20

Example: icmp_server.c

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

slide-21
SLIDE 21

Example: icmp_server.c

/∗

  • ur

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

slide-22
SLIDE 22

Example: icmp_server.c

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

slide-23
SLIDE 23

Example: icmp_server.c

/∗ 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

slide-24
SLIDE 24

Example: icmp_server.c

/∗ Prepare

  • u t g o i n g

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

slide-25
SLIDE 25

Example: icmp_server.c

/∗ Prepare

  • u t g o i n g

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

slide-26
SLIDE 26

Example: icmp_server.c

/∗ send i t

  • n

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

slide-27
SLIDE 27

Read on . . .

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