FreeBSD divert sockets


A divert socket is a socket that can be used to alter packets before being processed by the networking stack. When a packet is received by the network interface, it goes to the Kernel delivers it to the firewall which decides what to do with it. When using divert sockets, the firewall module can be configured to transfer the packet to a running process. The program listening on the divert socket can for example change the TCP source port before forwarding the packet to the networking stack.


Prerequisites


Kernel support for IP Divert sockets

The Kernel must support divert sockets. The Kernel support of divert sockets depends on operating systems. The configuration of divert sockets enabled Kernels is not the scope of this document (probably in a future update of the document).


IP firewall settings

The IP firewall on the host using divert sockets need to be configured to forward packets to the port where the divert socket is binded.

In case of FreeBSD, ipfw 'divert' rule can be used for this purpose.


Sample code

This code uses a divert socket to read TCP packets and display generic information in FreeBDS systems (This sample code works but may use some clean up)

#include "sysdep.h"
 
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_var.h>
#include <arpa/inet.h>
 
#ifdef IPSEC
#include <netinet6/ipsec.h>
#endif /*IPSEC*/
 
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <math.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
 
 
#define BUFSIZE 65535
 
 
int
main(int argc, char **argv)
{
        int             fd, rawfd, fdfw, ret, n;
        int             on = 1;
        struct sockaddr_in bindPort, sin;
        int             sinlen;
        int             port_nb;
        struct ip   *hdr;
        unsigned char   packet[BUFSIZE];
        struct in_addr  addr;
        int             i, direction;
        struct ip_mreq  mreq;
 
        if (argc != 2) {
                fprintf(stderr, "Usage: %s <port number>\n", argv[0]);
                exit(1);
        }
        bindPort.sin_family = AF_INET;
        bindPort.sin_port = htons(atol(argv[1]));
        bindPort.sin_addr.s_addr = 0;
 
 
        fprintf(stderr, "%s:Creating a socket\n", argv[0]);
        /* open a divert socket */
        fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT);
 
        if (fd == -1) {
                fprintf(stderr, "%s:We could not open a divert socket\n", argv[0]);
                exit(1);
        }
        bindPort.sin_family = AF_INET;
        bindPort.sin_port = htons(atol(argv[1]));
        bindPort.sin_addr.s_addr = 0;
 
        fprintf(stderr, "%s:Binding a socket\n", argv[0]);
        ret = bind(fd, (struct sockaddr*)&bindPort, sizeof(struct sockaddr_in));
 
        if (ret != 0) {
                close(fd);
                fprintf(stderr, "%s: Error bind(): %s", argv[0], strerror(ret));
                exit(2);
        }
        printf("%s: Waiting for data...\n", argv[0]);
        /* read data in */
 
        sinlen = sizeof(struct sockaddr_in);
        while (1) {
                n = recvfrom(fd, packet, BUFSIZE, 0, (struct sockaddr*)&sin, &sinlen);
                hdr = (struct ip *) packet;
 
                printf("%s: The packet looks like this:\n", argv[0]);
                for (i = 0; i < 40; i++) {
                        printf("%02x ", (int)*(packet + i));
                        if (!((i + 1) % 16))
                                printf("\n");
                };
                printf("\n");
 
                printf("%s: Source address: %s\n", argv[0], inet_ntoa(hdr->ip_src));
                printf("%s: Destination address: %s\n", argv[0], inet_ntoa(hdr->ip_dst));
                printf("%s: Receiving IF address: %s\n", argv[0], inet_ntoa(sin.sin_addr));
                printf("%s: Protocol number: %i\n", argv[0], hdr->ip_p);
 
        }
}


Labels: , Wireless Internet Security Coding Network Monitoring

Comment

Enter your comment (wiki syntax is allowed):
FEDMN

Wireless Internet Security Performance RADIUS server Wireless Internet Security Performance RADIUS server