Listing 1
use strict;
use Math::VecStat qw(sum);
use Crypt::CBC;
use IO::Socket::INET;
use Getopt::Std;
use vars qw($opt_i $opt_r $opt_p $opt_t);
getopts("i:r:p:t:");
use constant PORTMIN => 745;
use constant KEY => "knock"; # keyphrase for the encryption
use constant CIPHER => "Blowfish"; # encryption algorithm
$opt_i || die "specify local IP";
$opt_r || die "specify remote IP";
$opt_p || die "specify remote port";
defined $opt_t || die "specify time flag";
my $cipher = Crypt::CBC->new({key=>KEY,cipher=>CIPHER,
iv=>"01234567",prepend_iv => 0});
# data to encrypt will be our IP address + port + time + checksum
my @data = (split(/\./,$opt_i),$opt_p,$opt_t);
# compute checksum 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
my @knocks = map {PORTMIN+$_} @cipherpack;
print "knock sequence ",int(@cipherpack)," knocks ",join("
",@knocks),"\n";
# create TCP connections for each port in the sequence
for my $port (@knocks) {
my $sock = IO::Socket::INET->new(PeerAddr => $opt_r,
PeerPort => $port,
Timeout => 0.5,
Proto => 'tcp');
print " knocked on $opt_r:$port\n";
}
exit 0;
### end of Listing 1