$_ outputting extra bit of data - perl

The static $_ might needs to be flushed. It is tried to be done by $|=1;.
DESIRED OUTPUT:
CLIENT
Connected to the Server.
sent to server : SAS4
sent to server : 50
sent to server : SAS_ACTION LOGIN
sent to server : LOGIN bss
sent to server : PASSWORD cleint
sent to server : $END$
Message received from Server : SAS4
Message received from Server : 61
Message received from Server : SAS_ACTION LOGIN_ACK
Message received from Server : ACK_STATUS 0
Message received from Server : ACK_MESSAGE Logged In
Message received from Server : $END$
SERVER
Waiting for the Client.
Connected from : 127.0.0.1, Port : 1862
Message received from Client : SAS4
Message received from Client : 50
Message received from Client : SAS_ACTION LOGIN
Message received from Client : LOGIN bss
Message received from Client : PASSWORD cleint
Message received from Client : $END$
server to client : SAS4
server to client : 61
server to client : SAS_ACTION LOGIN_ACK
server to client : ACK_STATUS 0
server to client : ACK_MESSAGE Logged In
server to client : $END$
CODE :
CLIENT
use strict;
use warnings;
use IO::Socket::INET;
my $socket = new IO::Socket::INET (PeerHost => '127.0.0.1', PeerPort => '1055', Proto => 'tcp', Reuse => 1) or die "$!\n";
print "Connected to the Server.\n";
send_login();
$|=1;
receive_loginack();
$socket->close();
sub send_login
{
my $login_txt = "Login.txt";
open LOGIN, '<', $login_txt or die "Cannot open $login_txt $!\n";
my #login = <LOGIN>;
close LOGIN;
my $logfile = "logfile.txt";
open LOG, '>>', $logfile or die "Cannot open $logfile ($!)\n";
foreach my $login (#login)
{
print $socket $login;
print LOG "CLIENT : $login";
print "sent to server : $login";
#last if ($login eq "\$END\$\n");
}
close LOG;
}
sub receive_loginack
{
while (<$socket>)
{
print"Message received from Server : $_";
}
}
SERVER
use strict;
use warnings;
use IO::Socket::INET;
my $socket = new IO::Socket::INET (LocalHost => '127.0.0.1', LocalPort => '1055', Proto => 'tcp', Listen => 1, Reuse => 1) or die "Oops: $! \n";
print "Waiting for the Client.\n";
server_loop();
$socket->close();
sub server_loop
{
OUTER:
while (my $clientsocket = $socket->accept())
{
print "connected from : ", $clientsocket->peerhost();
print ", port : ", $clientsocket->peerport(), "\n";
INNER:
while (<$clientsocket>) #
{ #
print"Message received from Client : $_"; #
last INNER if ($_ eq "\$END\$\n"); # RECEIVING
#last OUTER if ($_ eq "\$QUIT\$\n"); #
print $clientsocket $_; #
} #
my $login_ack = "login_ack.txt";
open LOGINACK, '<', $login_ack or die "Cannot open login acknowledgment file $login_ack ($!)\n";
my #loginack = <LOGINACK>;
close LOGINACK;
my $logfile = "logfile.txt";
open LOG, ">>", $logfile or die "cannot open $logfile ($!)\n";
foreach my $loginack (#loginack)
{
$|=1;
print $clientsocket $loginack;
print LOG "SERVER : $loginack";
print "server to client : $loginack";
#last if ($loginack eq "\$END\$\n");
}
close LOG;
close $clientsocket;
}
}

The server's input loop contains:
print $clientsocket $_;
So everything the client sends to the server is being sent back to the client, before the login_ack.txt file. So the client prints it as a message received from the server.

Related

Net::OpenSSH how to make perl script not exit and move to next IP if authentication fails

I am a beginner to Perl. My objective is to run a loop on a list of router IPs and attempt to ssh login into them, execute some commands, and store the output.
Upon unsuccessful authentication of one router IP, the entire script stops, and it does not move to the next IP. I wish to store why authentication failed of the router IP in question, and then move onto the next IP to execute.
The error I get before the script exits is:
Unable to connect: unable to establish master SSH connection: bad
password or master process exited unexpectedly
#!/usr/bin/perl -s
use Net::OpenSSH;
my $password = "xxxxxxx";
my $s;
$filename1 = "ip_FINAL_sample";
open my $f1, '<', "$filename1.txt";
chomp(my #file1 = <$f1>);
close $f1;
for $loopvariable(#file1)
{
my #mikparameters = split /\|/, $loopvariable;
$mikip = $mikip . $mikparameters[0] . "\n";
}
my #routers = split "\n", $mikip;
my $cmd1 = 'system identity print';
my $cmd2 = 'system routerboard print';
foreach $s (#routers)
{
my $ssh = Net::OpenSSH->new("yyyyy+500w\#$s", password=>$password, timeout=>30);
$ssh->error and die "Unable to connect: " . $ssh->error;
print "connected to $s\n";
my $fh1 = $ssh->pipe_out($cmd1) or die "Unable to run command\n";
my $fh1_1 = $ssh->capture($cmd1) or die "Unable to run command\n";
my $fh2 = $ssh->pipe_out($cmd2) or die "Unable to run command\n";
my $fh2_2 = $ssh->capture($cmd2) or die "Unable to run command\n";
while (<$fh1>)
{
print "$_";
}
close $fh1;
print "\n";
open my $file1, '>>', "output.txt" or die "Can't open output.txt: $!\n";
print $file1 "$fh1_1";
close $file1;
while (<$fh2>)
{
print "$_";
}
close $fh2;
print "\n";
open my $file2, '>>', "output.txt" or die "Can't open output.txt: $!\n";
print $file2 "$fh2_2";
close $file2;
undef $ssh;
}

have the fakeidentd.pl script listen on both ipv4 and ipv6

I'm trying to update a perl script that acts as identd, to also listen on an ipv6 socket.
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket;
use IO::Socket::IP;
my($client,$socket);
if (!defined($ARGV[0])) { die "Please supply ident\n"; }
my $ident=$ARGV[0];
$socket = IO::Socket::IP->new(
"Domain" => "PF_INET6",
"Proto" => "tcp",
"LocalPort" => 113,
Reuse => 1,
"Listen" => 1) or die "Error: $!\n";
print "using ident: $ident\n";
while ($client=$socket->accept()) {
my $host=$client->peerhost();
print "connection: ", $host . "\n";
my $data = <$client>;
if ($data) {
print "$host recv: $data\n";
$data =~ s/^\s+//;
$data =~ s/\s+$//;
$ident =~ s/^\s+//;
$ident =~ s/\s+$//;
print $client "$data : USERID : UNIX : $ident\n";
close $client;
}
}
undef $client if $client;
results are not satisfying at all:
netstat -alpn | grep perl
tcp 0 0 0.0.0.0:113 0.0.0.0:* LISTEN
The following seems to work:
$socket = IO::Socket::IP->new(
Domain => PF_INET6,
LocalHost => "::1",
"Proto" => "tcp",
"LocalPort" => 113,
Reuse => 1,
"Listen" => 1) or die "Error: $!\n";
Result:
# netstat -alpn | grep perl
tcp 0 0 ::1:113 :::* LISTEN 1357/perl

Perlscript with only one instance running, the next call add to queue of the first

I trie to make a Perlscript where only one instance is running, and the next call of the script sends the payload to the queue of the first one. If the queue is done the script should terminate.
I tried this with sockets - they should be blocking... I use Win7
If I call this script with test1 and test2 in two different command windows booth tell me they open the port and the queue echo back but don't terminate.
use 5.14.2;
use strict;
use warnings;
#Filename: singleInstance.pl
use Socket;
use threads;
use Thread::Queue;
sub sendToPort($);
my $q = Thread::Queue->new(); # A new empty queue
# Worker thread
my $thr = threads->create(
sub {
# Thread will loop until no more work
while (defined(my $item = $q->dequeue())) {
say $item;
sleep 10;
}
die "all done";
}
);
my $string = shift;
my $proto = getprotobyname('tcp');
my $port = 7890;
my $server = "localhost";
socket(SOCKET, PF_INET, SOCK_STREAM, $proto)
or die "Can't open socket $!\n";
setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, 1)
or die "Can't set socket option to SO_REUSEADDR $!\n";
bind( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
or die sendToPort($string);
listen(SOCKET, 5) or die "listen: $!";
print "SERVER started on port $port\n";
$q->enqueue($string);
# accepting a connection
my $client_addr;
while ($client_addr = accept(NEW_SOCKET, SOCKET)) {
# send them a message, close connection
my $string = <NEW_SOCKET>;
$q->enqueue($string);
close NEW_SOCKET;
}
sub sendToPort($){
# create the socket, connect to the port
socket(SOCKET,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
or die "Can't create a socket $!\n";
connect( SOCKET, pack_sockaddr_in($port, inet_aton($server)))
or die "Can't connect to port $port! \n";
print SOCKET $string;
close SOCKET or die "close: $!";
die "send to open script";
}
It seams that with Windows Port blocking don't work and also flock on the script if the script should be used when locked. I used a lock on a file instead. If the queue is done it exit the script. It's not the best solution, but it works for me so I didn't researched it more.
use 5.14.2;
use strict;
use warnings;
use Socket;
use threads;
use Thread::Queue;
use File::Flock::Tiny;
sub sendToPort($);
my $string = shift;
my $proto = getprotobyname('tcp');
my $port = 7890;
my $server = "localhost";
my $pid = File::Flock::Tiny->write_pid('cl_sv.pid') or do
{
say "in lock. send to daemon: $string";
sendToPort($string);
exit(0);
};
my $q = Thread::Queue->new(); # A new empty queue
# Worker thread
my $thr = threads->create(
sub {
# Thread will loop until no more work
while (defined(my $item = $q->dequeue())) {
say $item;
sleep 5;
}
exit;
}
);
my $socket;
socket($socket, PF_INET, SOCK_STREAM, $proto)
or die "Can't open socket $!\n";
setsockopt($socket, SOL_SOCKET, SO_REUSEADDR, 1)
or die "Can't set socket option to SO_REUSEADDR $!\n";
bind( $socket, pack_sockaddr_in($port, inet_aton($server)))
or die;
listen($socket, 5) or die "listen: $!";
print "SERVER started on port $port\n";
$q->enqueue($string, undef);
# accepting a connection
my $client_addr;
my $new_socket;
while ( ($client_addr = accept($new_socket, $socket))) {
# send them a message, close connection
my $string = <$new_socket>;
my $remove_undef= $q->extract(-1);
$q->enqueue($string, undef);
close $new_socket;
}
sub sendToPort($){
# create the socket, connect to the port
print "sendToPort";
socket($socket,PF_INET,SOCK_STREAM,(getprotobyname('tcp'))[2])
or die "Can't create a socket $!\n";
connect( $socket, pack_sockaddr_in($port, inet_aton($server)))
or die "Can't connect to port $port! \n";
print $socket $string;
close $socket or die "close: $!";
#die "send to open script";
}

How to Secure a port opened in the host?

Our goal is to monitor the server up/down from a remote(central) server. For this we are opening a port in the target host using the below (Client_port.pl) script. On the server we have other script to monitor this port, to make sure the server is up and port is up. Both the server wouldn't be on same network, so we need to open the client port to the world. How would we secure the client port from security hole and other possible harmful issues?
Client_port.pl
use IO::Socket::INET;
$server = IO::Socket::INET->new(LocalPort => $server_port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 ) # or SOMAXCONN
or die "Couldn't be a tcp server on port $server_port: $!\n";
while ($client = $server->accept()) {
# $client is the new connection
}
close($server);
Server_port_listener.pl
use strict;
use Socket;
# set time until connection attempt times out
my $timeout = 3;
if ($#ARGV != 1) {
print "usage: is_tcp_port_listening hostname portnumber\n";
exit 2;
}
my $hostname = $ARGV[0];
my $portnumber = $ARGV[1];
my $host = shift || $hostname;
my $port = shift || $portnumber;
my $proto = getprotobyname('tcp');
my $iaddr = inet_aton($host);
my $paddr = sockaddr_in($port, $iaddr);
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
eval {
local $SIG{ALRM} = sub { die "timeout" };
alarm($timeout);
connect(SOCKET, $paddr) || error();
alarm(0);
};
if ($#) {
close SOCKET || die "close: $!";
print "$hostname is NOT listening on tcp port $portnumber.\n";
exit 1;
}
else {
close SOCKET || die "close: $!";
print "$hostname is listening on tcp port $portnumber.\n";
exit 0;
}

FTP application written in Perl doesn't connect

Why doesn't my program work? It refuses to connect to the host, I've tried two different servers and verified which port is used.
Note that I'm not very experienced when it comes to Perl.
use strict;
use Net::FTP;
use warnings;
my $num_args = $#ARGV+1;
my $filename;
my $port;
my $host;
my $ftp;
if($num_args < 2)
{
print "Usage: ftp.pl host [port] file\n";
exit();
}
elsif($num_args == 3)
{
$port = $ARGV[1];
$host = $ARGV[0];
$filename = $ARGV[2];
print "Connecting to $host on port $port.\n";
$ftp = Net::FTP->new($host, Port => $port, Timeout => 30, Debug => 1)
or die "Can't open $host on port $port.\n";
}
else
{
$host = $ARGV[0];
$filename = $ARGV[1];
print "Connecting to $host with the default port.\n";
$ftp = Net::FTP->new($host, Timeout => 30, Debug => 1)
or die "Can't open $host on port $port.\n";
}
print "Usename: ";
my $username = <>;
print "\nPassword: ";
my $password = <>;
$ftp->login($username, $password);
$ftp->put($filename) or die "Can't upload $filename.\n";
print "Done!\n";
$ftp->quit;
Thanks in advance.
Now that you already have your answer <> -> <STDIN>, I think I see the problem. When #ARGV contains anything, <> is the 'magic open'. Perl interprets the next item in #ARGV as a filename, opens it and reads it line by line. Therefore, I think you can probably do something like:
use strict;
use Net::FTP;
use warnings;
use Scalar::Util 'looks_like_number';
if(#ARGV < 2)
{
print "Usage: ftp.pl host [port] file [credentials file]\n";
exit();
}
my $host = shift; # or equiv shift #ARGV;
my $port = (looks_like_number $ARGV[0]) ? shift : 0;
my $filename = shift;
my #ftp_args = (
$host,
Timeout => 30,
Debug => 1
);
if ($port)
}
print "Connecting to $host on port $port.\n";
push #ftp_args, (Port => $port);
}
else
{
print "Connecting to $host with the default port.\n";
}
my $ftp = Net::FTP->new(#ftp_args)
or die "Can't open $host on port $port.\n";
#now if #ARGV is empty reads STDIN, if not opens file named in current $ARGV[0]
print "Usename: ";
chomp(my $username = <>); #reads line 1 of file
print "\nPassword: ";
chomp(my $password = <>); #reads line 2 of file
$ftp->login($username, $password);
$ftp->put($filename) or die "Can't upload $filename.\n";
print "Done!\n";
$ftp->quit;
Then if you had some connection creditials in a file (say named cred) like
myname
mypass
then
$ ftp.pl host 8020 file cred
would open host:8020 for file using credentials in cred.
I'm not sure you want to do that, its just that THAT is how <> works.