Cover V07, I01
Article
Listing 1
Listing 2

jan98.tar


Listing 2: SOCKSLIB.PL

#
# define constants used in the package.  Note that
# the SOCKS_DIRECTS *must* be 4 byte IP subnets.  Zero's
# are "don't care" (ie, anything matches)
#
sub SOCKSinit
{
$SOCKS_GW = "socks.server.internal.com";
@SOCKS_DIRECTS = (   "15.0.0.0",
"163"
)
}
#
#
# The Rconnect subroutine will make a connection to the
# socks gateway (defined in $SOCKS_GW).  It is passed
# two parameters, the server to connect to and the port to talk to.
#
# we return with the constant SOCKS_SERVER setup as a stream already
# connected to the socks gateway, which is proxied to the final
# destination machine.
#
#

sub Rconnect
{

local($address,$port,@server,$socks_server,$d1,$d2,$proto,$socks,$error);
local($bytes1,$byte2,$bytes3,$buff,@gotback,@addr);

if (!defined($SOCKS_GW)) {
SOCKSinit();
}

$address = $_[0];
$port = $_[1];

if (CheckDirect($address) == 1)
{

@server = &getIPaddress("$SOCKS_GW");
$socks_server = pack("C4",@server);

($d1, $d2, $proto) = getprotobyname("tcp");

$socks = pack("Sna4x8",2,1080,$socks_server);
if (socket(SOCKS_SOCKET,2,1,$proto) == 0 ) {
$error = -1;
return($error);
}

if ( connect(SOCKS_SOCKET,$socks) == 0)
{
$error = -2;
return($error);
}

#
# Now we build the SOCKS protocol stream
#

$bytes1 = pack("C2",04,01);
if ($port > 255)  {
$bytes2 = pack("C2", int($port/256),
$port-int($port/256)*256);
##
# need to figure out how to split
# into two bytes
##
}
else {
$bytes2 = \
pack("C2",0,$port);
}
@addr = &getIPaddress("$address");
$address = pack("C4",@addr);

$bytes3 = pack("C5",80,101,114,108,00);
select (SOCKS_SOCKET);
$| = 1;
print SOCKS_SOCKET ($bytes1, $bytes2, $address, $bytes3);
read (SOCKS_SOCKET,$buff,8);
@gotback = unpack("C*",$buff);

select(stdout);

return(@gotback[1]);  # the second byte is the return code
# from the server
}

else {
@server = &getIPaddress("$address");
$socks_server = pack("C4",@server);

($d1, $d2, $proto) = getprotobyname("tcp");

$socks = pack("Sna4x8",2,$port,$socks_server);
if (socket(SOCKS_SOCKET,2,1,$proto) == 0 ) {
$error = -10;
return($error);
}

if ( connect(SOCKS_SOCKET,$socks) == 0)
{
$error = -20;
return($error);
}

select (SOCKS_SOCKET);
$| = 1;
select (stdout);
return(0);
}

}
sub getIPaddress
{

# this routine takes the variable $address and interrogates each element
# (ie, the things between the dots).  If any of them are non-numeric, we
# set the variable $hostname to 1 indicating that the variable $address is
# probably a hostname and not an address (ie, we need to do a
# gethostbyname() call to get the IP address.
#

local ($address,@elements,$hostname,$part,$d1,$d2,$d3,$d4,$hostaddress);

$address = $_[0];
@elements = split(/\./,$address);  # split the octets into an array

$hostname = 0;
foreach $part (@elements) {
if ($part =~ /\D+/) {  $hostname = 1;
#check for non-numeric

}
else {
if ($part > 255) {
$hostname = 1;
}
}

}

if ($hostname == 1) {
@elements = ();
# do a gethostbyname filling in elements

if (!(($d1, $d2, $d3, $d4, $hostaddress) =
gethostbyname("$address")))
{

@elements = (0,0,0,0);
}
else {
@elements = unpack("C4",$hostaddress);

}
}

return(@elements);

}

#
# this routine scans thru the array @SOCKS_DIRECTS to see if the address
# passed matches any of the patterns. Zeros in the SOCKS)_DIRECTS subnet
# indicate a "don't care" byte (ie, anything matches it).
#
# a return value of 1 means use the SOCKS gateway
# a return value of 0 indicates we should connect directly to the server.
#
sub CheckDirect
{
local($address,$subnet,$direct,@sub,@ip,$octet,$match_count);

$address = $_[0];

foreach $subnet (@SOCKS_DIRECTS)
{
$direct = 0;    # assume we use the gateway, zero
# means use it
$match_count = 0;
@sub = getIPaddress("$subnet");
@ip  = getIPaddress("$address");

foreach $octet (0..$#sub)  {
if (@sub[$octet]
== 0)
{
$match_count++;

next;
}
else {
if
(@sub[$octet] == @ip[$octet])
{

$match_count++;
}
}
}
if ($match_count == 4) { return(0); }
}
return(1);
}

1;

# End of File