printf STDOUT "\t\tNetProx Port Redirector\n"; printf STDOUT "\t\t-----====[NP]====------\n\n\n"; printf STDOUT "\t\t--==[CODED BY:-ZeroKnock]==--\n"; printf STDOUT "\t\t-----====[PERL]====-----\n\n"; printf STDOUT "USAGE: NetProx [ --remote host ] [ --local interface ] [ --service service ]\n"; use strict; use Getopt::Long; use Net::hostent; use IO::Socket; use POSIX ":sys_wait_h"; my ( %Children, $REMOTE, $LOCAL, $SERVICE, $proxy_server, $ME, ); ($ME = $0) =~ s,.*/,,; check_args(); start_proxy(); service_clients(); die "NOT REACHED"; sub check_args { GetOptions( "remote=s" => \$REMOTE, "local=s" => \$LOCAL, "service=s" => \$SERVICE, ) or die < 'tcp', Reuse => 1, Listen => SOMAXCONN, ); push @proxy_server_config, LocalPort => $SERVICE if $SERVICE; push @proxy_server_config, LocalAddr => $LOCAL if $LOCAL; $proxy_server = IO::Socket::INET->new(@proxy_server_config) or die "Can't create proxy server: $@"; print "[Proxy server on ", ($LOCAL || $SERVICE), " initialized.]\n"; } sub service_clients { my ( $local_client, # someone internal wanting out $lc_info, # local client's name/port information $remote_server, # the socket for escaping out @rs_config, # temp array for remote socket options $rs_info, # remote server's name/port information $kidpid, # spawned child for each connection ); $SIG{CHLD} = \&REAPER; # harvest the moribund accepting(); while ($local_client = $proxy_server->accept()) { $lc_info = peerinfo($local_client); set_state("servicing local $lc_info"); printf "[Connect from $lc_info]\n"; @rs_config = ( Proto => 'tcp', PeerAddr => $REMOTE, ); push(@rs_config, PeerPort => $SERVICE) if $SERVICE; print "[Connecting to $REMOTE..."; set_state("connecting to $REMOTE"); # see below $remote_server = IO::Socket::INET->new(@rs_config) or die "remote server: $@"; print "done]\n"; $rs_info = peerinfo($remote_server); set_state("connected to $rs_info"); $kidpid = fork(); die "Cannot fork" unless defined $kidpid; if ($kidpid) { $Children{$kidpid} = time(); close $remote_server; close $local_client; next; } close $proxy_server; $kidpid = fork(); die "Cannot fork" unless defined $kidpid; if ($kidpid) { set_state("$rs_info --> $lc_info"); select($local_client); $| = 1; print while <$remote_server>; kill('TERM', $kidpid); # kill my twin cause we're done } # this is the fork's child, the master's grandchild else { set_state("$rs_info <-- $lc_info"); select($remote_server); $| = 1; print while <$local_client>; printf "\n"; # kill('TERM', getppid()); } exit; } continue { accepting(); } } sub peerinfo { my $sock = shift; my $hostinfo = gethostbyaddr($sock->peeraddr); return sprintf("%s:%s", $hostinfo->name || $sock->peerhost, $sock->peerport); } sub set_state { $0 = "$ME [@_]" } sub accepting { set_state("[*]Accepting Proxy For " . ($REMOTE || $SERVICE)); } sub REAPER { my $child; my $start; while (($child = waitpid(-1,WNOHANG)) > 0) { if ($start = $Children{$child}) { my $runtime = time() - $start; printf "Child $child ran %dm%ss\n", $runtime / 60, $runtime % 60; delete $Children{$child}; } else { print "Bizarre kid $child exited $?\n"; } } $SIG{CHLD} = \&REAPER; };