NAME

Net::Divert - Divert socket module

SYNOPSIS

use Net::Divert;

DESCRIPTION

The Net::Divert module facilitates the use of divert sockets for packet alteration on FreeBSD and MacOSX.

Divert sockets can be bound to a certain port. This port will then receive all packets you divert to it with the help of a divert filter rule. On FreeBSD and MacOSX ipfw allows you to add such a rule. Please refer to the divert and ipfw manpages for more information.

This module allows you to create a divert socket and then just supply a function that will deal with the incoming packets.

new(host,port) will create a new divert object. It will also create a divert socket bound to the specified port at the given host/ip.

getPackets(func) will create a loop getting all incoming packets and pass them onto the specified function you created. This function will be called with two arguments: packet and fwtag. Fwtag contains the rule number where the packet is reinserted. Refer to divert(4) for more information.

putPacket(packet,fwtag) reinsert a packet at the specified fw rule (normally you don't want to alter fwtag, as it is easy to create infinite loops this way)

FRAMEWORK EXAMPLE

First of all, you need a ipfw divert rule, for example: ipfw add divert 9999 all from any to www.somesite.com 80

Basic framework:

use Net::Divert;

$divobj = Net::Divert->new('yourhostname',9999);

$divobj->getPackets(\&alterPacket);

sub alterPacket { my($packet,$fwtag) = @_;

# here you can do things to the packet

# write it back out
$divobj->putPacket($packet,$fwtag);
}

EXAMPLES

You can modify the header of the packet as well as its payload. Say you wanted to turn on the tcp ece and cwr flags in all tcp packets:

use Net::Divert; use NetPacket::IP; use NetPacket::TCP;

$divobj = Net::Divert->new('yourhostname',9999);

$divobj->getPackets(\&alterPacket);

sub alterPacket { my($packet,$fwtag) = @_;

# decode the IP header
$ip_obj = NetPacket::IP->decode($packet);

# check if this is a TCP packet
if($ip_obj->{proto} == IP_PROTO_TCP) {

    # decode the TCP header
    $tcp_obj = NetPacket::TCP->decode($ip_obj->{data});

    # set the ece and cwr flags
    $tcp_obj->{flags} |= ECE | CWR;

    # construct the new ip packet
    $ip_obj->{data} = $tcp_obj->encode($ip_obj);
    $packet = $ip_obj->encode;

}

# write it back out
$divobj->putPacket($packet,$fwtag);
}

When you alter the payload of an IP packet, the total length in the IP header will be adjusted automatically when the packet is reencoded.

NOTES

Altering the payload in TCP packets does not work this easily. You can modify the payload in such a way that the length of the payload stays the same. If you just want to modify, say, an outgoing webrequest you can also make the payload smaller. The problem is inherent in the way TCP uses sequence numbers. Data flowing from one host to the other is a stream of data, spread out over multiple packets. The sequence number identifies the byte in this stream of data from the sender to the receiver that the first byte in this segment represents. If you change the size of a packet in between the state on both ends will be disynchronized. See TCP/IP Illustrated Vol. 1 for more information on TCP.

You need at least NetPacket 0.03 to do the modifications described above.

LIMITATIONS

Packet modifications are done on packet per packet basis. If you would want to make modifications spanning multiple packets, you would have to keep packets in a alterPacket yourself. Keep in mind though that because of retransmissions on the sending side, this might not be possible for too long.

AUTHOR

Stephanie Wehner, atrak@itsx.com

COPYRIGHT

Copyright (c) 2001 Stephanie Wehner. All rights reserved. This module is released under the BSD License. See the file LICENSE for details.

SEE ALSO

perl(1), divert(4), ipfw(8)