#!/usr/bin/perl # p0fq-ppc.pl - sample p0f query interface # ------------------------------------ # # Just to show how things should be done, and perhaps to provide # a truly ineffective way of querying p0f from shell scripts and # such. # # If you want to query p0f from a production application, just # implement the same functionality in your code. It's perhaps 10 # lines. # # Copyright (C) 2007 by Vincent Li use strict; use warnings; use Convert::Binary::C qw( ); use IO::Socket; use Net::IP qw( ); use Data::Hexdumper; use Data::Dumper; use constant QUERY_MAGIC => 0x0defaced; use constant QTYPE_FINGERPRINT => 1; $Data::Dumper::Indent = 0; die "usage: p0fq.pl p0f_socket src_ip src_port dst_ip dst_port" unless @ARGV == 5; my $c = eval { Convert::Binary::C->new( Alignment => 4, Include => [ '/etc/mail/spamassassin' ], )->parse_file("p0f-query.h"); }; print Dumper( [$c->dependencies] ); if ($@) { die "Parse error: $@"; } # Convert the IPs and pack the request message my $src = Net::IP->new( $ARGV[1] ) or die( Net::IP::Error() ); my $dst = Net::IP->new( $ARGV[3] ) or die( Net::IP::Error() ); print "src ip:", ( $src->hexip() ), "\n", "dst ip:", ( $dst->hexip() ), "\n"; my $query = $c->pack( 'p0f_query', { magic => QUERY_MAGIC, type => QTYPE_FINGERPRINT, id => 0x12345678, src_ad => $src->hexip(), dst_ad => $dst->hexip(), src_port => $ARGV[2], dst_port => $ARGV[4], } ); #uncomment two lines below if running on linux x86 #$c->tag('p0f_query.src_ad', ByteOrder => 'BigEndian'); #$c->tag('p0f_query.dst_ad', ByteOrder => 'BigEndian'); print "query:\n", hexdump( data => $query, ); # Open the connection to p0f my $sock = IO::Socket::UNIX->new( Peer => $ARGV[0], Type => SOCK_STREAM, ) or die "Could not create socket: $!\n"; # Ask p0f print $sock $query; my $response = <$sock>; # yuck! close $sock; print "response:\n", hexdump( data => $response, ); # Extract the response from p0f $c->tag('p0f_response.genre', Format => 'String'); $c->tag('p0f_response.detail', Format => 'String'); $c->tag('p0f_response.link', Format => 'String'); my $data = $c->unpack( 'p0f_response', $response ); #print Dumper($data); die "Bad response magic.\n" if $data->{magic} != QUERY_MAGIC; die "P0f did not honor our query.\n" if $data->{type} == 1; die "This connection is not (no longer?) in the cache.\n" if $data->{type} == 2; # Display result print "Genre : " . $data->{genre} . "\n"; print "Details : " . $data->{detail} . "\n"; print "Link : " . $data->{link}. "\n"; print "Uptime : " . $data->{uptime} . " hrs\n";