Listing 1 portknocking client
use strict;
use Math::VecStat qw(sum);
use Crypt::CBC;
use IO::Socket::INET;
use Getopt::Long;
use vars qw($opt_client $opt_remote $opt_port $opt_time);
GetOptions("client=s","remote=s","port=i","time=i");
$opt_client || die "specify IP address (-client) for which the port will be opened.";
$opt_remote || die "specify IP address (-remote) of server listening to knocks";
$opt_port || die "specify remote port (-port)";
$opt_time = (defined $opt_time)?$opt_time:5;
use constant PORTMIN => 745;
use constant KEY => "knock"; # keyphrase for the encryption
use constant CIPHER => "Blowfish"; # encryption algorithm
my $cipher = Crypt::CBC->new({key => KEY,
iv => "01234567",
prepend_iv => 0,
cipher => CIPHER});
# data to encrypt will be our IP address + port + time + checksum
my @data = (split(/\./,$opt_client),$opt_port,$opt_time);
# compute crc and push it onto the data array
push(@data,sum(@data) % 255);
print "encrypting data ",join(" ",@data),"\n";
# encrypt the packed data
my $ciphertext = $cipher->encrypt(pack("C*",@data));
# unpack the ciphered data into unsigned char values 0-255
my @cipherpack = unpack("C*",$ciphertext);
# create the knock sequence by mapping to ports PORTMIN-PORTMIN+255
print "ciphered data ",join(" ",@cipherpack),"\n";
my @knocks = map {PORTMIN+$_} @cipherpack;
print "knock sequence [",int(@cipherpack)," knocks]: ",join(" ",@knocks),"\n";
# create TCP connection to the remote host to each of the ports in the knock sequence
for my $port (@knocks) {
my $sock = IO::Socket::INET->new(PeerAddr => $opt_remote,
PeerPort => $port,
Timeout => 0.5,
Proto => 'tcp');
print " knocked on $opt_remote:$port\n";
}
exit 0;
|