Gathering data via Divert Sockets
Matthew Goward
mgoward at mail.msen.com
Fri Feb 27 08:39:14 PST 2004
I am currently playing with a toy app using divert and ipfw
on 5.2.1. One of the bits of info I am trying to get ahold of
is the rule number in ipfw that sent the diverted packet over to
me. The DIVERT(4) man page states:
Diverted packets may be read unaltered via read(2), recv(2),
or recvfrom(2). In the latter case, the address returned
will have its port set to some tag supplied by the packet
diverter, (usually the ipfw rule number)
But I cant seem to get it to do so, nor am i really sure I want
it to do so. I still need the source and dest ip and ports,
along with the IPFW rule number. Here is a bit of what I have
(all the error checking and setup stuff pulled out for brievity)
get a socket
fd=socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT))
bind to it:
bindPort.sin_family=AF_INET;
bindPort.sin_port=htons(atol(port));
bindPort.sin_addr.s_addr=0;
if ((ret=bind(fd,(struct sockaddr *) &bindPort,
sizeof(struct sockaddr_in))) != 0) {
blah blah error checking}
stolen from the divert socket mini faq to try and use the data
start grabbing data:
sinlen=sizeof(struct sockaddr_in);
while(1) {
n=recvfrom(fd, packet, BUFSIZE, 0, (struct sockaddr *) &sin, &sinlen);
iphdr=(struct ip*)packet;
if (iphdr->ip_p == IPPROTO_TCP) {
tcphdr = (struct tcphdr *) (packet + sizeof(struct ip));
}
else if (iphdr->ip_p == IPPROTO_UDP) {
udphdr = (struct udphdr *) (packet + sizeof(struct ip));
}
printf("\n");
printf("%s: Source address: %s\n",progname, inet_ntoa(iphdr->ip_src));
if (iphdr->ip_p == IPPROTO_TCP)
printf("%s: Source port: %d\n",progname, ntohs(tcphdr->th_sport));
printf("%s: Destination address: %s\n", progname,
inet_ntoa(iphdr->ip_dst));
if (iphdr->ip_p == IPPROTO_TCP)
printf("%s: Destination port: %d\n\n",progname,
ntohs(tcphdr->th_dport));
printf("%s: Receiving IF address: %s\n", progname,
inet_ntoa(sin.sin_addr));
printf("%s: Protocol number: %i\n", progname, iphdr->ip_p);
printf("%s: Header length: %i\n", progname, iphdr->ip_hl);
printf("%s: Header ttl: %i\n", progname, iphdr->ip_ttl);
printf("%s: Header sum: %i\n\n", progname, iphdr->ip_sum);
if (iphdr->ip_p == IPPROTO_TCP) {
printf("%s: Sequence Number %d\n",progname, ntohs(tcphdr->th_seq));
printf("%s: Acknowledgement Number %d\n\n",progname,
ntohs(tcphdr->th_ack));
}
}
And it all works as you would expect. This really was from source port 1360
and to port 25.
The packet in hex:
69 16 00 52 247 230 64 00 64 06 61 91 192 168 66 11
192 168 66 22 05 80 00 25 49 238 186 32 30 184 225 162
128 16 226 64 195 168 00 00 01 01 08 10 27 81 180 235
00 38 09 44
Source address: 192.168.66.11
Source port: 1360
Destination address: 192.168.66.22
Destination port: 25
Receiving IF address: 192.168.66.22
Protocol number: 6
Header length: 5
Header ttl: 64
Header sum: 23357
Sequence Number 12782
Acknowledgement Number 7864
DIVERT 52 bytes
52 bytes reinjected.
Now, I need the data this way as i am also stuffing it off to a file in pcap
format. But from reading the divert man page I would expect to see the rule
number somewhere.
Sorry to have rambled on so much. I just want to know how I can continue to
get all the data I have now, but also find out what rule number ipfw is hitting
on before diverting to me.
Thank you so much for you help,
Matthew Goward
m g o w a r d @ e v i l o v e r l o r d . o r g
mgoward at IneedAname 906> uname -a
FreeBSD IneedAname 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #2: Thu Feb 26 12:57:33 GMT 2004
+root at IneedAname:/usr/obj/usr/src/sys/MATT i38
mgoward at IneedAname 909> diff MATT GENERIC
49c49
< options SCSI_DELAY=2000 #Delay (in ms) before probing SCSI
---
> options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI
60,69d59
< options IPFIREWALL #firewall
< options IPFIREWALL_VERBOSE #enable logging to syslogd(8)
< options IPDIVERT #divert sockets
< options IPFIREWALL_VERBOSE_LIMIT=100
< #options IPFIREWALL_DEFAULT_TO_ACCEPT
< options RANDOM_IP_ID
< options DUMMYNET
< options TCP_DROP_SYNFIN
< options IPSTEALTH
< #options "ICMP_BANDLIM"
00001 48 2549 divert 5555 tcp from 192.168.66.11 to 192.168.66.22 dst-port 25
00001 0 0 divert 5555 udp from 192.168.55.22 to 192.168.66.22 dst-port 25
00002 0 0 divert 5555 tcp from 192.168.66.22 25 to 192.168.55.22
00002 0 0 divert 5555 udp from 192.168.66.22 25 to 192.168.55.22
00100 54 2914 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
65000 34423 9607284 allow ip from any to any
65535 0 0 deny ip from any to any
ipfw2 initialized, divert enabled, rule-based forwarding enabled, default to deny, logging limited to 100 packets/entry by
+default
if anything else would be helpfull let me know.
More information about the freebsd-ipfw
mailing list