Initial passive DNS server commit at CanSecWest

This commit is contained in:
Alexandre Dulaunoy 2012-03-08 23:25:21 +01:00
parent 52da990aad
commit 9be511dc94
15 changed files with 26273 additions and 0 deletions

View file

@ -0,0 +1,6 @@
#!/bin/sh
#
# A simple feeder using dnscap input
#
./dnscap -T -s r -ieth1 -g 2>&1 >/dev/null | perl pdns-feeder.pl

View file

@ -0,0 +1,147 @@
#
# Minimal and Scalable Passive DNS - Redis feeder
#
# Read dnscap output to feed a Redis database
#
#
# Copyright (C) 2010-2012 Alexandre Dulaunoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use strict;
use warnings;
use Date::Manip;
use Redis;
use Scalar::Util;
use IO::Handle;
$| = 1;
my $block = 0;
my $date;
my %counter = (
"processed" => 0,
"redisrst" => 0
);
my @RRType = ( "A", "AAAA", "CNAME", "NS" );
my %RRTypevalue = (
"A" => 1,
"AAAA" => 28,
"CNAME" => 5,
"NS" => 2,
"MX" => 15,
"SRV" => 33
);
my $parsedate = new Date::Manip::Date;
my $r = Redis->new( server => '127.0.0.1:6379', encoding => undef );
my $stdin = new IO::Handle;
$stdin->fdopen( fileno(STDIN), "r" );
while ( defined( $_ = $stdin->getline ) ) {
if ( $counter{'redisrst'} == 1 ) {
$r->quit;
undef($r);
print "Reset\n";
$r = Redis->new( server => '127.0.0.1:6379', encoding => undef );
$counter{'redisrst'} = 0;
}
if (m/^\[/) {
$block = 1;
{
my @s = split;
$date = $s[1];
}
}
if ( !(m/^\[/) ) {
$_ =~ s/\cI//;
# discarding - [1.2.3.4].53 [149.13.33.69].5234
if (m/^\[/) { next; }
# split - 21 ns10.ovh.net,IN,AAAA,172800,2001:41d0:1:1981::1 \
if (m/^\d* /) {
$_ =~ s/^\d* //;
}
# discarding - dns QUERY,NOERROR,26278,qr|rd|ra \
if (m/^dns /) { next; }
# decode line
ProcessRequest( $date, $_ );
$counter{'processed'}++;
}
if ( ( $counter{'processed'} % 1000 ) == 0 ) {
$counter{'redisrst'} = 1;
print "Processed:"
. $counter{'processed'}
. " Redist RST:"
. $counter{'redisrst'} . "\n";
}
}
sub ProcessRequest {
my $epoch = shift;
my $line = shift;
chomp($line);
#my $err = $parsedate->parse($date);
#my $epoch = $parsedate->printf('%s');
my @l = split( /,/, $line );
if ( $l[2] ~~ @RRType ) {
my @rdatas = split( / /, $l[4] );
#$l[4] =~ s/\s\\.*$//g;
#$l[4] =~ s/(.*)\s/$1/g;
print $l[0] . " " . $l[2] . " " . "$rdatas[0]\n";
my @rdatap = split( / /, $l[4] );
RedisUpdate( $l[0], $l[2], $rdatap[0], $epoch );
undef(@rdatap);
}
}
sub RedisUpdate {
my $name = lc(shift);
my $recordtype = shift;
my $rdata = lc(shift);
my $timestamp = shift;
my $recordtypevalue = $RRTypevalue{$recordtype};
my $pdns_r = "r:" . $name . ":" . $recordtypevalue;
my $pdns_v = "v:" . $rdata;
my $pdns_s = "s:" . $name . ":" . $rdata;
my $pdns_l = "l:" . $name . ":" . $rdata;
my $pdns_o = "o:" . $name . ":" . $rdata;
my $ret = $r->sadd( $pdns_r, $rdata );
$ret = $r->sadd( $pdns_v, $name );
# set first seen value
if ( !( $r->exists($pdns_s) ) ) {
$ret = $r->set( $pdns_s, $timestamp );
}
# set last seen value
$ret = $r->set( $pdns_l, $timestamp );
# increment the occurence value
$ret = $r->incr($pdns_o);
}

View file

@ -0,0 +1,85 @@
#
# Minimal and Scalable Passive DNS - ranking records
#
# Copyright (C) 2012 Alexandre Dulaunoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Sample input (pdns-ranking.py) read line with the Passive DNS format:
# s:truecsi.org:ns3.afraid.org. = 1327737190
#
# and output the following:
# truecsi.org
# [(1.0003765060241001, 'truecsi.org')]
# truecsi.org,1.00037650602
#
# and update the DB 6 database
# redis> select 6
# OK
# redis> KEYS "*"
# 1) "truecsi.org"
# redis> GET "truecsi.org"
# "1.00037650602"
# redis>
import sys
import re
import redis
path = "../lib/DomainClassifier/DomainClassifier/"
sys.path.append(path)
import domainclassifier
def domexist(ldomain = None):
print ldomain
r = redis.StrictRedis(host='localhost', port=6379, db=6)
if ldomain is not None:
if r.exists(ldomain):
return True
else:
return False
else:
return False
def domstore(ldomain = None, rank = 1.0):
r = redis.StrictRedis(host='localhost', port=6379, db=6)
return r.set(ldomain,rank)
for line in sys.stdin:
domain = line.split(':')[1].lower()
if not (re.search("(spamhaus.org|arpa)$", domain)):
if not domexist(ldomain=domain):
c = domainclassifier.Extract(domain)
c.domain()
c.validdomain()
r = c.rankdomain()
if r:
r.sort(reverse=True)
ranking = r[0][0]
print r
if ranking is not None:
print domain+","+str(ranking)
domstore(ldomain=domain, rank=ranking)
else:
print domain+","+str(1)
domstore(ldomain=domain)
else:
print domain+","+str(1)
domstore(ldomain=domain)
else:
print domain+" already cached"

114
pdns-server/bin/query.pl Normal file
View file

@ -0,0 +1,114 @@
#
# Minimal and Scalable Passive DNS - Query tool
#
# Copyright (C) 2010-2012 Alexandre Dulaunoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use POSIX qw(strftime);
use Redis;
use Date::Manip;
# will lookup the following RR types
my %RRTypevalue = (
"A" => 1,
"AAAA" => 28,
"CNAME" => 5,
"NS" => 2
);
my $r = Redis->new( server => '127.0.0.1:6379', encoding => undef );
#sample feeder input
#1298823157.764221 "SET" "l:www.l.google.com:72.14.204.103" "1298819557"
#1298823157.764353 "INCR" "o:www.l.google.com:72.14.204.103"
#1298823157.765310 "SADD" "r:www.l.google.com:1" "72.14.204.104"
#1298823157.765439 "SADD" "v:72.14.204.104" "www.l.google.com"
#1298823157.765567 "EXISTS" "s:www.l.google.com:72.14.204.104"
#1298823157.765696 "SET" "l:www.l.google.com:72.14.204.104" "1298819557"
#1298823157.765823 "INCR" "o:www.l.google.com:72.14.204.104"
#1298823157.766776 "SADD" "r:www.l.google.com:1" "72.14.204.147"
#1298823157.766901 "SADD" "v:72.14.204.147" "www.l.google.com"
#1298823157.767086 "EXISTS" "s:www.l.google.com:72.14.204.147"
#1298823157.767207 "SET" "l:www.l.google.com:72.14.204.147" "1298819557"
#1298823157.767333 "INCR" "o:www.l.google.com:72.14.204.147"
while ( my ( $typename, $typevalue ) = each(%RRTypevalue) ) {
my @x = Lookup( $ARGV[0], $typevalue );
if ( defined(@x) ) {
foreach $p (@x) {
print $p. "("
. $typename . ")"
. " first seen: "
. NiceDate( FirstSeen( $ARGV[0], $p ) )
. " last seen: "
. NiceDate( LastSeen( $ARGV[0], $p ) )
. " Hits: "
. OccTuple( $ARGV[0], $p ) . "\n";
print " behind: " . join( ",", LookupIP($p) ) . "\n";
}
}
}
sub NiceDate {
my $epochvalue = shift;
return strftime( "%Y%m%d-%H:%M:%S", localtime($epochvalue) );
}
sub Lookup {
my $name = shift;
my $type = shift;
# default A record
if ( !( defined($type) ) ) { $type = 1; }
my $key = "r:$name:$type";
return $r->smembers($key);
}
sub LookupIP {
my $name = shift;
my $key = "v:$name";
return $r->smembers($key);
}
sub FirstSeen {
my $name = shift;
my $rdata = shift;
my $key = "s:$name:$rdata";
return $r->get($key);
}
sub LastSeen {
my $name = shift;
my $rdata = shift;
my $key = "l:$name:$rdata";
return $r->get($key);
}
sub OccTuple {
my $name = shift;
my $rdata = shift;
my $key = "o:$name:$rdata";
return $r->get($key);
}

View file

@ -0,0 +1,79 @@
A 1 a host address [RFC1035]
NS 2 an authoritative name server [RFC1035]
MD 3 a mail destination (Obsolete - use MX) [RFC1035]
MF 4 a mail forwarder (Obsolete - use MX) [RFC1035]
CNAME 5 the canonical name for an alias [RFC1035]
SOA 6 marks the start of a zone of authority [RFC1035]
MB 7 a mailbox domain name (EXPERIMENTAL) [RFC1035]
MG 8 a mail group member (EXPERIMENTAL) [RFC1035]
MR 9 a mail rename domain name (EXPERIMENTAL) [RFC1035]
NULL 10 a null RR (EXPERIMENTAL) [RFC1035]
WKS 11 a well known service description [RFC1035]
PTR 12 a domain name pointer [RFC1035]
HINFO 13 host information [RFC1035]
MINFO 14 mailbox or mail list information [RFC1035]
MX 15 mail exchange [RFC1035]
TXT 16 text strings [RFC1035]
RP 17 for Responsible Person [RFC1183]
AFSDB 18 for AFS Data Base location [RFC1183][RFC5864]
X25 19 for X.25 PSDN address [RFC1183]
ISDN 20 for ISDN address [RFC1183]
RT 21 for Route Through [RFC1183]
NSAP 22 for NSAP address, NSAP style A record [RFC1706]
NSAP-PTR 23 for domain name pointer, NSAP style [RFC1348]
SIG 24 for security signature [RFC4034][RFC3755][RFC2535]
KEY 25 for security key [RFC4034][RFC3755][RFC2535]
PX 26 X.400 mail mapping information [RFC2163]
GPOS 27 Geographical Position [RFC1712]
AAAA 28 IP6 Address [RFC3596]
LOC 29 Location Information [RFC1876]
NXT 30 Next Domain - OBSOLETE [RFC3755][RFC2535]
EID 31 Endpoint Identifier [Patton]
NIMLOC 32 Nimrod Locator [Patton]
SRV 33 Server Selection [RFC2782]
ATMA 34 ATM Address [ATMDOC]
NAPTR 35 Naming Authority Pointer [RFC2915][RFC2168][RFC3403]
KX 36 Key Exchanger [RFC2230]
CERT 37 CERT [RFC4398]
A6 38 A6 (Experimental) [RFC3226][RFC2874]
DNAME 39 DNAME [RFC2672]
SINK 40 SINK [Eastlake]
OPT 41 OPT [RFC2671]
APL 42 APL [RFC3123]
DS 43 Delegation Signer [RFC4034][RFC3658]
SSHFP 44 SSH Key Fingerprint [RFC4255]
IPSECKEY 45 IPSECKEY [RFC4025]
RRSIG 46 RRSIG [RFC4034][RFC3755]
NSEC 47 NSEC [RFC4034][RFC3755]
DNSKEY 48 DNSKEY [RFC4034][RFC3755]
DHCID 49 DHCID [RFC4701]
NSEC3 50 NSEC3 [RFC5155]
NSEC3PARAM 51 NSEC3PARAM [RFC5155]
Unassigned 52-54
HIP 55 Host Identity Protocol [RFC5205]
NINFO 56 NINFO [Reid]
RKEY 57 RKEY [Reid]
TALINK 58 Trust Anchor LINK [Wijngaards]
Unassigned 59-98
SPF 99 [RFC4408]
UINFO 100 [IANA-Reserved]
UID 101 [IANA-Reserved]
GID 102 [IANA-Reserved]
UNSPEC 103 [IANA-Reserved]
Unassigned 104-248
TKEY 249 Transaction Key [RFC2930]
TSIG 250 Transaction Signature [RFC2845]
IXFR 251 incremental transfer [RFC1995]
AXFR 252 transfer of an entire zone [RFC1035][RFC5936]
MAILB 253 mailbox-related RRs (MB, MG or MR) [RFC1035]
MAILA 254 mail agent RRs (Obsolete - see MX) [RFC1035]
* 255 A request for all records [RFC1035]
URI 256 URI [Faltstrom]
Unassigned 257-32767
TA 32768 DNSSEC Trust Authorities [Weiler] 2005-12-13
DLV 32769 DNSSEC Lookaside Validation [RFC4431]
Unassigned 32770-65279
Private use 65280-65534
Reserved 65535

View file

@ -0,0 +1,97 @@
This is a description of the various data-structure used
in the Passive DNS toolkit.
= Redis Database number =
- (0) default passive dns
- (6) ranking of hostname
= format for redis db 0 =
KEY, VALUE
s:<tuple> <epoch timestamp>
l:<tuple> <epoch timestamp>
o:<tuple> <integer value>
KEY, {SET}
r:<record>:<rr-type-value> {<answer>}
v:<answer> {<record>}
# "SET" "l:www.l.google.com:72.14.204.103" "1298819557"
#1298823157.764353 "INCR" "o:www.l.google.com:72.14.204.103"
#1298823157.765310 "SADD" "r:www.l.google.com:1" "72.14.204.104"
#1298823157.765439 "SADD" "v:72.14.204.104" "www.l.google.com"
#1298823157.765567 "EXISTS" "s:www.l.google.com:72.14.204.104"
#1298823157.765696 "SET" "l:www.l.google.com:72.14.204.104" "1298819557"
#1298823157.765823 "INCR" "o:www.l.google.com:72.14.204.104"
#1298823157.766776 "SADD" "r:www.l.google.com:1" "72.14.204.147"
#1298823157.766901 "SADD" "v:72.14.204.147" "www.l.google.com"
#1298823157.767086 "EXISTS" "s:www.l.google.com:72.14.204.147"
#1298823157.767207 "SET" "l:www.l.google.com:72.14.204.147" "1298819557"
#1298823157.767333 "INCR" "o:www.l.google.com:72.14.204.147"
== sample db 0 ==
Here is the classical update process for a feeder:
Set or update the last-seen.
#1298823157.764221 "SET" "l:www.l.google.com:72.14.204.103" "1298819557"
Update the occurence of the answer seen.
#1298823157.764353 "INCR" "o:www.l.google.com:72.14.204.103"
Add to a set "record:rr-type" the seen answer.
#1298823157.765310 "SADD" "r:www.l.google.com:1" "72.14.204.104"
Add the reverse for fast lookup.
#1298823157.765439 "SADD" "v:72.14.204.104" "www.l.google.com"
If there is no existing first-seen for the tuple,
#1298823157.765567 "EXISTS" "s:www.l.google.com:72.14.204.104"
A first-seen is set:
#1298823157.765696 "SET" "l:www.l.google.com:72.14.204.104" "1298819557"
and so on...
#1298823157.765823 "INCR" "o:www.l.google.com:72.14.204.104"
#1298823157.766776 "SADD" "r:www.l.google.com:1" "72.14.204.147"
#1298823157.766901 "SADD" "v:72.14.204.147" "www.l.google.com"
#1298823157.767086 "EXISTS" "s:www.l.google.com:72.14.204.147"
#1298823157.767207 "SET" "l:www.l.google.com:72.14.204.147" "1298819557"
#1298823157.767333 "INCR" "o:www.l.google.com:72.14.204.147"
= format for redis db 6 =
This db index hold a ranking value per hostname.
KEY, VALUE
hostname, float double precision
This can be seen as a cache when an expiration can be set
by key to limit the lifetime of a ranking. You can create
a persistent ranking for setting up some "golden" domains.
== sample db 6 ==
1) "truecsi.org"
redis> GET "truecsi.org"
"1.00037650602"
redis>
= contact =
Update, extension, or new data-structure more than welcome.
https://www.github.com/adulau/

View file

@ -0,0 +1,3 @@
#!/bin/sh
git clone git://github.com/adulau/DomainClassifier.git

171
pdns-server/web/PDNSq.pm Normal file
View file

@ -0,0 +1,171 @@
#
# Minimal and Scalable Passive DNS - Query tool
#
# Copyright (C) 2010-2012 Alexandre Dulaunoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
package PDNS::Query;
use base 'Exporter';
use POSIX qw(strftime);
use Redis;
use Date::Manip;
use Time::Format;
my %RRTypevalue = (
"A" => 1,
"NS" => 2,
"AAAA" => 28,
"CNAME" => 5
);
my $r = Redis->new( server => '127.0.0.1:6379', encoding => undef );
my $burl = "/l/";
sub Query {
my $query = shift;
my $ret = "";
$ret .= "<a id=\"v_toggle\" href=\"\#\">[+-]</a>";
$ret .= "<div id=\"vertical_slide\">";
while ( my ( $typename, $typevalue ) = each(%RRTypevalue) ) {
my @x = Lookup( $query, $typevalue );
if ( defined(@x) ) {
foreach $p (@x) {
if ( $typename =~ m/CNAME/ ) {
$ret .= MakeLink($p) . "(" . $typename . ")";
}
else {
$ret .= $p . "(" . $typename . ")";
}
$ret .=
" first seen: "
. NiceDate( FirstSeen( $query, $p ) )
. " last seen: "
. NiceDate( LastSeen( $query, $p ) )
. " Hits: "
. OccTuple( $query, $p ) . "\n";
#$ret .= " behind: " . join( "" , LookupIP($p) ) . "\n";
$ret .= "<br />";
foreach $n ( LookupIP($p) ) {
$ret .= MakeLink($n);
}
$ret .= "<br /> <br />";
}
}
}
$ret .= "</div>";
return $ret;
}
sub QueryJSON {
my $query = shift;
my $ret = <<JSHEAD;
var event_data =
{
"dateTimeFormat": "iso8601",
"events":[
JSHEAD
while ( my ( $typename, $typevalue ) = each(%RRTypevalue) ) {
my @x = Lookup( $query, $typevalue );
if ( defined(@x) ) {
foreach $p (@x) {
$ret .= "\{\"start\": \""
. NiceDateISO( FirstSeen( $query, $p ) ) . "\",\n";
$ret .= "\"end\": \""
. NiceDateISO( LastSeen( $query, $p ) ) . "\",\n";
chomp($p);
$ret .= "\"title\": \"" . $p . "(" . $typename . ")\",\n";
$ret .= "\"description\": \"" . $p . "(" . $typename . ")\",\n";
$ret .= "\"instant\": \"false\",\n";
$ret .= "\},\n";
}
}
}
chop($ret);
chop($ret);
return $ret . "] };\n";
}
sub MakeLink {
my $value = shift;
my $ret = "<a href=\"" . $burl . "" . $value . "\">$value</a> ";
return $ret;
}
sub NiceDate {
my $epochvalue = shift;
return strftime( "%Y%m%d-%H:%M:%S", localtime($epochvalue) );
}
sub NiceDateISO {
my $epochvalue = shift;
my $format = "yyyy-mm{on}-ddThh:mm:ss+00:00";
return time_format( $format, $epochvalue );
}
sub Lookup {
my $name = shift;
my $type = shift;
# default A record
if ( !( defined($type) ) ) { $type = 1; }
my $key = "r:$name:$type";
return $r->smembers($key);
}
sub LookupIP {
my $name = shift;
my $key = "v:$name";
return $r->smembers($key);
}
sub FirstSeen {
my $name = shift;
my $rdata = shift;
my $key = "s:$name:$rdata";
return $r->get($key);
}
sub LastSeen {
my $name = shift;
my $rdata = shift;
my $key = "l:$name:$rdata";
return $r->get($key);
}
sub OccTuple {
my $name = shift;
my $rdata = shift;
my $key = "o:$name:$rdata";
return -1;
#return $r->get($key);
}
1;

214
pdns-server/web/pdns-web.pl Executable file
View file

@ -0,0 +1,214 @@
#!/bin/env perl
#
# Minimal and Scalable Passive DNS - Web interface
#
# Copyright (C) 2010-2012 Alexandre Dulaunoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
use Mojolicious::Lite;
use Mojolicious::Static;
use PDNSq;
# Documentation browser under "/perldoc" (this plugin requires Perl 5.10)
plugin 'pod_renderer';
get '/l/(.query)' => sub {
my $self = shift;
my $q = $self->param('query');
my $ret = PDNS::Query::Query($q);
my $json = PDNS::Query::QueryJSON($q);
$self->render(template => 'index', q => $ret, query => $q, jq => $json);
};
post '/l' => sub {
my $self = shift;
my $q = $self->param('q');
my $ret = PDNS::Query::Query($q);
my $json = PDNS::Query::QueryJSON($q);
$self->render(template => 'index', q => $ret, query => $q, jq => $json);
};
get '/js/(.query)' => sub {
my $self = shift;
my $q = $self->param('query');
$self->render_static('static/'.$q);
};
get '/__history__.html' => sub {
my $self = shift;
$self->render_static('static/__history__.html');
};
get '/' => sub {
my $self = shift;
$self->render(template => 'main');
};
app->secret('You have to change it');
app->start;
__DATA__
@@ main.html.ep
% layout 'default';
% title 'Passive DNS';
<h1>Passive DNS interface</h1>
<form name="lookup" action="/l/"i method=POST>
<input type="text" name="q" />
<input type="submit" value="lookup"/>
</form>
@@ index.html.ep
% layout 'default';
% title 'PDNS Lookup';
<h1>Passive DNS lookup result for <a href="/l/<%= $query %>"><%= $query %></a></h1>
<a href="#visual">(go to visual timeline)</a><br /><br />
<%== $q %>
<a name="visual">Visual timeline</a>
<div id="tl" class="timeline-default" style="height: 400px; border: 1px solid #aaa;"></div>
<noscript>
This page uses Javascript to show you a Timeline. Please enable Javascript in your browser to see the full page. Thank you.
</noscript>
<script>
var tl;
//in php you can get this 1so8601 date using date("c",$you_date_variable);
var startProj = SimileAjax.DateTime.parseIso8601DateTime("2011-03-01T00:00:00");
var endProj = SimileAjax.DateTime.parseIso8601DateTime("2011-12-30T00:00:00");
<%== $jq %>
function onLoad() {
var tl_el = document.getElementById("tl");
var eventSource = new Timeline.DefaultEventSource();
var theme = Timeline.ClassicTheme.create();
theme.autoWidth = true; // Set the Timeline's "width" automatically.
theme.autoWidthMargin=10;
theme.event.bubble.width = 220;
theme.event.bubble.height = 120;
theme.ether.backgroundColors = ["#E6E6E6","#F7F7F7"];
theme.timeline_start = startProj;
theme.timeline_stop = endProj;
theme.event.track.height = "20";
theme.event.tape.height = 10; // px
theme.event.track.height = theme.event.tape.height + 6;
var d = SimileAjax.DateTime.parseIso8601DateTime("2011-03-01T00:00:00");
var bandInfos = [
Timeline.createBandInfo({
layout: 'original',// original, overview, detailed
eventSource: eventSource,
date: d,
width: 350,
intervalUnit: Timeline.DateTime.DAY,
intervalPixels: 100,
//trackHeight: 10,
theme :theme
}),
Timeline.createBandInfo({
layout: 'overview',
date: d,
trackHeight: 0.5,
trackGap: 0.2,
eventSource: eventSource,
width: 50,
intervalUnit: Timeline.DateTime.MONTH,
// showEventText: false,
intervalPixels: 200,
theme :theme
})
];
bandInfos[1].highlight = true;
bandInfos[1].syncWith = 0;
bandInfos[1].decorators = [
new Timeline.SpanHighlightDecorator({
// startDate: startProj,
// endDate: endProj,
inFront: false,
color: "#FFC080",
opacity: 30,
startLabel: "Begin",
endLabel: "End",
theme: theme
})
];
tl = Timeline.create(tl_el, bandInfos, Timeline.HORIZONTAL);
// show loading message
tl.showLoadingMessage();
eventSource.loadJSON(event_data, document.location.href);
// dismiss loading message
tl.hideLoadingMessage();
// setup highlight filters
//setupFilterHighlightControls(document.getElementById("controls"), tl, [0,1], theme);
}
//function centerProjStart() {
// tl.getBand(1).setCenterVisibleDate(startProj);
//}
//function centerProjEnd() {
// tl.getBand(1).setCenterVisibleDate(endProj);
// }
var resizeTimerID = null;
function onResize() {
if(resizeTimerID == null) {
resizeTimerID = window.setTimeout(function() {
resizeTimerID = null;
tl.layout();
}, 500);
}
}
</script>
@@ layouts/default.html.ep
<!doctype html><html>
<head><title><%= title %></title>
<link rel="stylesheet" type="text/css" href="http://www.circl.lu/css/styles.css">
<link rel="stylesheet" type="text/css" href="/js/pdns.css">
<link rel="shortcut icon" href="/favicon.ico" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<script src="http://static.simile.mit.edu/timeline/api-2.3.0/timeline-api.js?bundle=true" type="text/javascript"></script>
<script src="/js/mootools-core-1.3.1.js" type="text/javascript"></script>
<script src="/js/mootools-more-1.3.1.1.js" type="text/javascript"></script>
<script src="/js/moo-pdns.js" type="text/javascript"></script>
</head>
<body onload="onLoad();" onresize="onResize();">
<div class="header" id="header">Passive DNS toolkit
</div>
<div class="body" id="body">
<%= content =%></body>
</div>
</html>

View file

@ -0,0 +1,5 @@
#!/bin/sh
#
# Will listen on port 3000
perl pdns-web.pl daemon --reload

View file

@ -0,0 +1,17 @@
window.addEvent('domready', function() {
var status = {
'true': 'open',
'false': 'close'
};
// -- vertical
var myVerticalSlide = new Fx.Slide('vertical_slide');
document.id('v_toggle').addEvent('click', function(event){
event.stop();
myVerticalSlide.toggle();
});
});

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
h3.section {
margin-top: 1em;
}
#vertical_slide, #horizontal_slide {
background: #D0C8C8;
color: #8A7575;
padding: 10px;
border: 5px solid #F3F1F1;
font-weight: bold;
}
div.marginbottom {
/* Since the Fx.Slide element resets margins, we set a margin on the above element */
margin-bottom: 10px;
}