v2
This commit is contained in:
		
							
								
								
									
										203
									
								
								xtrd.pl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								xtrd.pl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,203 @@
 | 
			
		||||
#!/usr/bin/perl
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use Dancer2;
 | 
			
		||||
use Socket;
 | 
			
		||||
use DBI;
 | 
			
		||||
use File::Fetch;
 | 
			
		||||
use PerlIO::gzip;
 | 
			
		||||
use Data::Dumper;
 | 
			
		||||
 | 
			
		||||
### README
 | 
			
		||||
# to install needed modules on debian:
 | 
			
		||||
# * apt-get install libperlio-gzip-perl libdancer2-perl libdbi-perl libdbd-sqlite3-perl
 | 
			
		||||
 | 
			
		||||
### vars
 | 
			
		||||
my $dbfile         = "xtrd.db";
 | 
			
		||||
my $ip2asn_csv_url = 'http://iptoasn.com/data/ip2asn-v4-u32.tsv.gz';
 | 
			
		||||
set port           => 12110;
 | 
			
		||||
 | 
			
		||||
### connect to database
 | 
			
		||||
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","");
 | 
			
		||||
$dbh->do("PRAGMA cache_size = 800000");
 | 
			
		||||
 | 
			
		||||
### create ip2asn database & table if needed and fill with ip information
 | 
			
		||||
if(create_db_table($dbh,"ip2asn","ip2asn( ip_from INTEGER, ip_to INTEGER, ip_as INTEGER)","ip2asnIndex ON ip2asn(ip_from,ip_to);"))
 | 
			
		||||
{
 | 
			
		||||
	get_ipas_data($dbh,$ip2asn_csv_url);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
### create server database & table if needed
 | 
			
		||||
create_db_table($dbh,"server","server( server_ip TEXT, server_port INTEGER, server_as INTEGER, server_status INTEGER)","");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### hook for HTTP "security"
 | 
			
		||||
hook 'before' => sub {
 | 
			
		||||
    header 'Access-Control-Allow-Origin' => '*';
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
### main get route
 | 
			
		||||
get '/v2/server' => sub {
 | 
			
		||||
	my $server = get_server($dbh,"1");
 | 
			
		||||
	return encode_json $server;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
put '/v2/server/:ip/:port/:status' => sub {
 | 
			
		||||
	my $ip = route_parameters->get('ip');
 | 
			
		||||
	my $port = route_parameters->get('port');
 | 
			
		||||
	my $status = route_parameters->get('status');
 | 
			
		||||
	my $result = add_server($dbh,$ip,$port,$status);
 | 
			
		||||
	return encode_json $result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
### start the loop
 | 
			
		||||
start;
 | 
			
		||||
 | 
			
		||||
### if you reach this, you're done
 | 
			
		||||
exit;
 | 
			
		||||
 | 
			
		||||
sub add_server
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh,$ip,$port,$status) = @_;
 | 
			
		||||
	my $id = get_server_id($dbh,$ip,$port);
 | 
			
		||||
	if($id ne "0")
 | 
			
		||||
	{
 | 
			
		||||
		# update server status
 | 
			
		||||
		set_server_status($dbh,$id,$status);
 | 
			
		||||
		my $return_code = {"status" => "1"};
 | 
			
		||||
		return $return_code;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		# create
 | 
			
		||||
		my $resolve = gethostbyname($ip);
 | 
			
		||||
		my $a_record = inet_ntoa($resolve);
 | 
			
		||||
		my $as = find_as($dbh,$a_record);
 | 
			
		||||
		my $add_server_cmd = "INSERT INTO server VALUES ('".$ip."','".$port."','".$as."','".$status."');";
 | 
			
		||||
		my $add_server_sth = $dbh->prepare($add_server_cmd);
 | 
			
		||||
		$add_server_sth->execute();
 | 
			
		||||
		my $return_code = {"status" => "1"};
 | 
			
		||||
		return $return_code;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub set_server_status
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh,$id,$status) = @_;
 | 
			
		||||
	
 | 
			
		||||
	my $set_status_cmd = "UPDATE server set server_status = '".$status."' WHERE _rowid_ = '".$id."';";
 | 
			
		||||
	my $set_status_sth = $dbh->prepare($set_status_cmd);
 | 
			
		||||
	$set_status_sth->execute();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub get_server_id
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh,$ip,$port) = @_;
 | 
			
		||||
 | 
			
		||||
	my $get_id_cmd = "SELECT _rowid_ FROM server WHERE server_ip = '".$ip."' AND server_port = '".$port."';";
 | 
			
		||||
	my $get_id_sth = $dbh->prepare($get_id_cmd);
 | 
			
		||||
	$get_id_sth->execute();
 | 
			
		||||
	my $result = $get_id_sth->fetch;
 | 
			
		||||
	return $result->[0] || 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub get_server
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh,$status) = @_;
 | 
			
		||||
	if($status eq "") { $status = 1; }
 | 
			
		||||
	my $get_server_cmd = "SELECT * FROM server WHERE server_status = '".$status."';";
 | 
			
		||||
        my $get_server_sth = $dbh->prepare($get_server_cmd);
 | 
			
		||||
        $get_server_sth->execute();
 | 
			
		||||
        my $result = $get_server_sth->fetchall_arrayref;;
 | 
			
		||||
	return $result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub get_ipas_data
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh,$ip2asn_csv_url) = @_;
 | 
			
		||||
 | 
			
		||||
	my $ff = File::Fetch->new(uri => $ip2asn_csv_url);
 | 
			
		||||
	my $temp_file = $ff->fetch( to => '/tmp' );
 | 
			
		||||
 | 
			
		||||
	open(FILE,"<:gzip",$temp_file) or die "Can't open file: $!";
 | 
			
		||||
	my @data = <FILE>;
 | 
			
		||||
	close(FILE);
 | 
			
		||||
 | 
			
		||||
	$dbh->do('begin');
 | 
			
		||||
 | 
			
		||||
	my $max_commit  = 10000;
 | 
			
		||||
	my $inserted    = 0;
 | 
			
		||||
	my $array_size  = @data;
 | 
			
		||||
	my $last_p      = -1;
 | 
			
		||||
	print "loading data...\n";
 | 
			
		||||
	foreach my $line (@data)
 | 
			
		||||
	{
 | 
			
		||||
		chomp($line);
 | 
			
		||||
		if($line=~/^(\d+)\s+(\d+)\s+(\d+)/)
 | 
			
		||||
		{
 | 
			
		||||
			if($3 eq "0") { next; }
 | 
			
		||||
			#my %temp_hash = ('from' => $1, 'to' => $2, 'as' => $3);
 | 
			
		||||
			#push(@ipaslist,\%temp_hash);
 | 
			
		||||
			my $insert_cmd .= "INSERT INTO ip2asn VALUES ('".$1."','".$2."','".$3."');";
 | 
			
		||||
			my $insert_sth = $dbh->prepare($insert_cmd);
 | 
			
		||||
			$inserted += $insert_sth->execute();
 | 
			
		||||
			
 | 
			
		||||
			# print status for console users
 | 
			
		||||
			my $p = int($inserted * 100 / $array_size);
 | 
			
		||||
			if($p != $last_p) { print $p % 10 ? "" : "$p%\n"; }
 | 
			
		||||
			$last_p = $p;
 | 
			
		||||
 | 
			
		||||
			# only commit every $max_commit statements (it's faster)	
 | 
			
		||||
			unless ($inserted % $max_commit)
 | 
			
		||||
			{
 | 
			
		||||
				$dbh->do('commit');
 | 
			
		||||
				$dbh->do('begin');
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	$dbh->do('commit');
 | 
			
		||||
	unlink($temp_file);
 | 
			
		||||
	print "data prepared for searches!\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub find_as
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh, $ip) = @_;
 | 
			
		||||
	my $ip_id = unpack("N", inet_aton($ip));
 | 
			
		||||
 | 
			
		||||
	my $get_as_cmd = "SELECT ip_as FROM ip2asn WHERE ip_from < '".$ip_id."' AND ip_to > '".$ip_id."';";
 | 
			
		||||
	my $get_as_sth = $dbh->prepare($get_as_cmd);
 | 
			
		||||
	$get_as_sth->execute();
 | 
			
		||||
	my $result = $get_as_sth->fetch;
 | 
			
		||||
	return $result->[0] || 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub create_db_table
 | 
			
		||||
{
 | 
			
		||||
	my ($dbh,$table,$schema,$schema_index) = @_;
 | 
			
		||||
 | 
			
		||||
	my $check_table_cmd = "SELECT name FROM sqlite_master WHERE type='table' AND name='".$table."';";
 | 
			
		||||
	my $check_table_sth = $dbh->prepare($check_table_cmd);
 | 
			
		||||
	$check_table_sth->execute();
 | 
			
		||||
	if(!$check_table_sth->fetch)
 | 
			
		||||
	{
 | 
			
		||||
		print "creating table '".$table."'...\n";
 | 
			
		||||
		my $create_table_cmd = "CREATE TABLE ".$schema;
 | 
			
		||||
		my $create_table_sth = $dbh->prepare($create_table_cmd);
 | 
			
		||||
		$create_table_sth->execute();
 | 
			
		||||
		if($schema_index ne "")
 | 
			
		||||
		{
 | 
			
		||||
			my $create_index_cmd = "CREATE INDEX ".$schema_index;
 | 
			
		||||
			my $create_index_sth = $dbh->prepare($create_index_cmd);
 | 
			
		||||
			$create_index_sth->execute();
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user