Date: Sun, 17 Jun 2001 14:24:14 -0400 (EDT) From: Dru <genisis@istar.ca> To: Mike Meyer <mwm@mired.org> Cc: <questions@FreeBSD.ORG> Subject: Re: script not found in /usr/local/etc/rc.d Message-ID: <20010617141853.S48172-100000@x1-6-00-50-ba-de-36-33.kico1.on.home.com> In-Reply-To: <15148.61274.704322.668319@guru.mired.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi Mike,
Forgive the long post, as this time I'll include both scripts instead of
sending them as attachments. (feel free to snip the appropriate portions)
Thanks for the help guys :)
Dru
more /usr/local/etc/rc.d/mnwclient.sh
#!/bin/sh
#
# mnwclient This shell script takes care of starting and stopping
# myNetWatchman Agent for FreeBSD
#
# description: mnwclient
# untested needs default paths of /bin and /usr/bin
# Check that networking is up.
#[ ${NETWORKING} = "no" ] && exit 0
# check if the mnwclient.rc file is present
[ -f /etc/mnwclient.rc ] || exit 0
# check to see if mnwclient exists
[ -f /usr/sbin/mnwclient ] || exit 0
if [ $# -eq 0 -o x$1 = xstart ]; then
/usr/sbin/mnwclient -c /etc/mnwclient.rc &
fi
if [ x$1 = xstop ]; then
/bin/kill `ps | grep 'perl.*mnwclient' | cut -f 1 -d " "`
fi
*************************************************************************
more /usr/sbin/mnwclient
#!/usr/bin/perl -w
##
## mnwclient - a Perl client for myNetWatchman
## Copyright (C) 2001 Chad Wagner
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
## mnwclient -- a Perl client for myNetWatchman
## $Id: mnwclient,v 1.9 2001/05/01 03:46:12 wagnerch Exp $
use Getopt::Std;
use IO::Socket;
use POSIX;
## DEFAULTS ##
## configuration file, where configuration parameters are stored
$mnwclientrc = "/etc/mnwclient.rc";
## this is where Packet log kernel messages are logged, typically
## /var/log/messages, but may vary based on distribution.
$logfile = "/var/log/messages";
## user interface to upload packets for
$interface = "ppp0";
## default chain to inspect, typically 'input'
@chaintbl = ("input");
## location to write error messages, success, etc
$errorlog = "/var/log/mnwclient.log";
## gmt correction offset, in seconds.
$gmt = 0;
## default delay interval between rescanning log
$interval = 60;
## default dequeue interval in seconds.
$dqinterval = 1;
## default backoff factor
$backoff = 3;
## maximum backoff factor
$maxbackoff = 600;
## default debug level
$debug = 0;
## DO NOT MODIFY BELOW THIS LINE ##
## version number
$mnwvers = "1.9";
## this is the server and port
$server = "www.mynetwatchman.com";
$port = 80;
$script = "/insertwebreport.asp";
## unbuffer i/o
$| = 1;
## process switches and arguments
getopts("i:c:l:e:zh", \%args);
## set overrides
$mnwclientrc = $args{c} if defined $args{c}; ## override rc file
$errorlog = $args{e} if defined $args{e}; ## override errors log
## check for invalid conditions, or help request
if (defined $args{h}) {
printf "%s [-c resource_file] [-l kernel_log_file] [-e errors_log_file]\n\t[-i interface]\n\n",$0;
printf " -c resource_file data file that holds configuration parameters\n";
printf " -l kernel_log_file where the kernel logs dropped or filtered packets\n";
printf " -e errors_log_file where this client logs error messages\n";
printf " -i interface upload data for interface\n";
exit 1;
}
## open pointer resource file
if (open(FD,$mnwclientrc)) {
$braces=0;
@filtbl=();
while (<FD>) {
$_ =~ s/\n$//g;
$_ =~ s/^\s*//g;
$_ =~ s/\s*$//g;
if (m/^#/ || m/^$/) {
## comment
} elsif ((m/^interface\s+(.*)$/) && (!$braces)) {
## interface directive
$interface=$1;
} elsif ((m/^chain\s+(.*)$/) && (!$braces)) {
## chain directive
@chaintbl=split(/,/,$1);
} elsif ((m/^errors\s+(.*)$/) && (!$braces)) {
## errors log directive
$errorlog=$1;
} elsif ((m/^log\s+(.*)$/) && (!$braces)) {
## log directive
$logfile=$1;
} elsif ((m/^login\s+(.*)$/) && (!$braces)) {
## login directive
$agtname=$1;
} elsif ((m/^password\s+(.*)$/) && (!$braces)) {
## password directive
$agtpass=$1;
} elsif ((m/^server\s+(.*)$/) && (!$braces)) {
## server directive
$server=$1;
} elsif ((m/^port\s+(.*)$/) && (!$braces)) {
## port directive
$port=$1;
} elsif ((m/^proxy\s+(.*)$/) && (!$braces)) {
## proxy directive
($proxyserver,$proxyport) = split(/:/,$1,2);
} elsif ((m/^debug(?:\s+(.*))?$/) && (!$braces)) {
## debug directive
if ($1 ne "") {
$debug = $1;
} else {
$debug=1;
}
} elsif ((m/^quiet$/) && (!$braces)) {
## quiet directive
$quiet=1;
} elsif ((m/^test$/) && (!$braces)) {
## test directive
$test=1;
} elsif ((m/^gmt\s+(.*)$/) && (!$braces)) {
## gmt directive
$gmt=$1 * 3600;
} elsif ((m/^retry\s+(.*)$/) && (!$braces)) {
## retry directive, ignored
} elsif ((m/^interval\s+(.*)$/) && (!$braces)) {
## interval directive
$interval=$1;
} elsif ((m/^dqinterval\s+(.*)$/) && (!$braces)) {
## dqinterval directive
$dqinterval=$1;
} elsif ((m/^backoff\s+(.*)$/) && (!$braces)) {
## backoff directive
$backoff=$1;
} elsif ((m/^maxbackoff\s+(.*)$/) && (!$braces)) {
## maxbackoff directive
$maxbackoff=$1;
} elsif ((m/^filter\s+\{$/) && (!$braces)) {
## filter directive, open braces mode
$braces=1;
} elsif ((m/^\}$/) && ($braces)) {
## close braces mode
$braces=0;
} elsif ($braces) {
## braces mode
if (m/^source\s+([0-9,\.]+)\s+netmask\s+([0-9,\.]+)$/) {
## filter-source/netmask directive
push(@filtbl,[0,$1,$2]);
} elsif ((m/^port\s+(\d+)(?:\s+proto\s+(\w+))?$/) ||
(m/^target\s+port\s+(\d+)(?:\s+proto\s+(\w+))?$/)) {
## filter-target/port/proto directive
push(@filtbl,[1,$1,$2]);
} elsif (m/^proto\s+(\w+)$/) {
## filter-proto directive
push(@filtbl,[2,$1]);
} elsif (m/^target\s+([0-9,\.]+)\s+netmask\s+([0-9,\.]+)$/) {
## filter-target/netmask directive
push(@filtbl,[3,$1,$2]);
} elsif (m/^source\s+port\s+(\d+)(?:\s+proto\s+(\w+))?$/) {
## filter-source/port/proto directive
push(@filtbl,[4,$1,$2]);
} elsif (m/^target\s+([0-9,\.]+)\s+netmask\s+([0-9,\.]+)\s+xchg\s+([0-9,\.]+)$/) {
## filter-target/netmask/xchg directive
push(@filtbl,[5,$1,$2,$3]);
} else {
## unknown filter directive
printf STDERR "unknown filter directive encountered in configuration file, \"%s\"\n",$_;
}
} else {
## unknown directive
printf STDERR "unknown directive encountered in configuration file, \"%s\"\n",$_;
}
}
close(FD);
} else {
printf STDERR "failed to open \"%s\" for reading: %s\n",$mnwclientrc,$!;
exit 1;
}
## warn about resource file being world/group readable/writable
$mode = (stat($mnwclientrc))[2];
&warning("configuration file is set world/group readable/writeable.\n") if ($mode & 077);
## override logfile, if set on command line
$logfile = $args{l} if defined $args{l};
## override interface, if set on command line
$interface = $args{i} if defined $args{i};
## check for agent name and password
if (!defined $agtname || !defined $agtpass) {
&fatal("agent name or password must be defined.\n");
}
## check for valid proxy port, if defined
if (defined $proxyserver) {
if (!$proxyport) {
&fatal("proxy directive has invalid port, or undefined port.\n");
}
}
## stat log file and get current size
$size = (stat($logfile))[7];
$offset=$size;
$offset=0 if defined $args{z};
## initialize msgq list
@msgq=();
## report version, and state that we are running
&printk("mnwclient version %s, monitoring \"%s\" starting at offset %lu\n",$mnwvers,$logfile,$offset);
## initialize several scalars here
my($proto)=0;
my(%protonum) = ( ## protocol table
'TCP' => 6, ## tcp
'tcp' => 6, ## tcp
'UDP' => 17, ## udp
'udp' => 17, ## udp
'ICMP' => 1, ## icmp
'icmp' => 1 ## icmp
);
my($count); ## attack count
my($match); ## match regex, used for checking for 'repeated' msgs
my($success); ## match regex, used to submit report
## setup currdqinterval equal to dqinterval, and var for lastdq stamp
my($currdqinterval) = $dqinterval;
my($lastdq) = time;
while (1) {
## stat log file and get current size
$size = (stat($logfile))[7];
## if offset is larger then size then logfile has been reset
$offset=0 if ($offset > $size);
## read in log file, and store in data array
open(FD,$logfile) || &fatal("unable to open kernel log for reading \"%s\": %s\n",$logfile,$!);
seek(FD,$offset,SEEK_SET);
while (<FD>) {
## initialize scalars on each looping
$count = 1;
$success = 0;
## dump debug info
&printk("debug: logread [%s]\n",$_) if ($debug >= 9);
## this is our regexp that we are looking to extract meaningful data from
if (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+kernel:\s+Packet\s+log:\s+(\w+)\s+(REJECT|DENY)\s+(\w+)\s+PROTO=(\d+)\s+([0-9,\.]+):(\d+)\s+([0-9,\.]+):(\d+)/) {
## deal with ipchains log formatting
if (&ischain($2) && $4 eq $interface) {
@last = ($1,$5,$6,$7,$8,$9);
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/id=firewall/) {
## deal with sonicwall log formatting
my($fwtime,$fwc,$fwm,$fwsrcaddr,$fwsrcport,$fwdstaddr,$fwdstport);
if (m/time=\"(\d+-\d+-\d+\s+\d+:\d+:\d+(?:\s+UTC)?)\"/) {
$fwtime=$1;
}
if (m/c=(\d+)/) {
$fwc=$1;
}
if (m/m=(\d+)/) {
$fwm=$1;
}
if (m/src=([\w,\.]+)(?::(\d+))?:WAN/) {
$fwsrcaddr=$1;
$fwsrcport=$2;
}
if (m/dst=([\w,\.]+)(?::(\d+):\w+)?/) {
$fwdstaddr=$1;
$fwdstport=$2;
}
$proto = 0;
if ($fwc == 32) {
my(%protocvt) = ( ## port/proto -- attack
22 => 1, ## icmp -- ping of death
23 => 0, ## ip -- ip spoof (unsupported)
27 => 6, ## tcp -- land
67 => 0, ## ??? -- ipsec auth failed (unsupported)
70 => 0, ## ??? -- ipsec dropped (unsupported)
72 => 6, ## tcp -- netbus
73 => 6, ## 31337/tcp -- back orifice
74 => 6, ## 1024/tcp -- net spy
75 => 6, ## 27374/tcp -- subseven
76 => 6, ## 2023/tcp -- ripper
77 => 6, ## 2565/tcp -- striker
78 => 17, ## 13000/udp -- senna spy
79 => 6, ## 16969/tcp -- priority
80 => 6, ## 9989/tcp -- inikiller
81 => 1, ## icmp -- smurf
82 => 0, ## ??? -- probable port scan (unsupported)
83 => 0, ## ??? -- probable port scan (unsupported)
84 => 6, ## tcp -- syn port scan
173 => 6 ## tcp -- fin port scan
);
$proto = $protocvt{$fwm};
} else {
my(%protocvt) = ( ## packets dropped
64 => 6, ## tcp
128 => 17, ## udp
256 => 1 ## icmp
);
$proto = $protocvt{$fwc};
}
## check for fwdstport and icmp proto, if not defined assume it is
## type 0 icmp (echo-request)
$fwdstport=0 if ($proto == 1 && !defined $fwdstport);
## check for fwsrcport, if not defined then assign it as -1, which is
## 'not displayed'
$fwsrcport=-1 if (!defined $fwsrcport);
## must have all necessary fields, and protocol nonzero
if (defined $fwtime && defined $fwsrcaddr && defined $fwsrcport &&
defined $fwdstaddr && defined $fwdstport && $proto) {
@last = ($fwtime,$proto,$fwsrcaddr,$fwsrcport,$fwdstaddr,$fwdstport);
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+portsentry\[\d+\]:\s+attackalert:\s+(.+\s+scan|Packet|Connect)\s+from\s+host:\s+\S+\/([0-9,\.]+)\s+to\s+(\w+)\s+port:\s+(\d+)/) {
## deal with portsentry log formatting
$proto = $protonum{$4};
@last = ($1,$proto,$3,-1,-1,$5);
$match = 1;
$success = 1;
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\S+:\s+ipfw:\s+\d+\s+(REJECT|DENY)\s+(TCP|UDP)\s+([0-9,\.]+):(\d+)\s+([0-9,\.]+):(\d+)\s+(\w+)\s+via\s+(\w+)/i) {
## deal with ipfw log formatting udp/tcp (freebsd)
$proto = $protonum{$3};
if (&ischain($8) && $9 eq $interface) {
@last = ($1,$proto,$4,$5,$6,$7);
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\S+:\s+ipfw:\s+\d+\s+(REJECT|DENY)\s+(ICMP):(\d+)\.(\d+)\s+([0-9,\.]+)\s+([0-9,\.]+)\s+(\w+)\s+via\s+(\w+)/i) {
## deal with ipfw log formatting icmp (freebsd)
if (&ischain($8) && $9 eq $interface) {
@last = ($1,1,$6,$4,$7,$5);
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\d+:\s+([\*]*)(\w+\s+\d+\s+\d+:\d+:\d+)(?:\.\d+\s+\w+)?:\s+\S+:\s+list\s+(\d+)\s+denied\s+(tcp|udp)\s+([0-9,\.]+)\((\d+)\)\s+->\s+([0-9,\.]+)\((\d+)\),\s+(\d+)\s+packet/i) {
## deal with cisco format tcp/udp
if (&ischain($4)) {
$proto = $protonum{$5};
@last = ($1,$proto,$6,$7,$8,$9);
## use date from router if not marked invalid
@last = ($3,$proto,$6,$7,$8,$9) if ($2 eq "");
$count = $10;
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\d+:\s+([\*]*)(\w+\s+\d+\s+\d+:\d+:\d+)(?:\.\d+\s+\w+)?:\s+\S+:\s+list\s+(\d+)\s+denied\s+(icmp)\s+([0-9,\.]+)\s+->\s+([0-9,\.]+)\s+\((\d+)\/(\d+)\),\s+(\d+)\s+packet/i) {
## deal with cisco format icmp
if (&ischain($4)) {
@last = ($1,1,$6,$8,$7,$9);
## use date from router if not marked invalid
@last = ($3,1,$6,$8,$7,$9) if ($2 eq "");
$count = $10;
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+named\[\d+\]:\s+(denied|unapproved)\s+query\s+from\s+\[([0-9,\.]+)\]\.(\d+)\s+for\s+\"version\.bind/i) {
## deal with version.bind named requests
@last = ($1,6,$3,$4,-1,53);
$match = 1;
$success = 1;
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\S+\s+IP\[Src=([0-9,\.]+)\s+Dst=([0-9,\.]+)\s+(\w+)(?:\s+spo=(\d+)\s+dpo=(\d+))?\]\s*\}\s*S(\d+)>R(\d+)(m|n)D/) {
## (syslog format) zyxel prestige 314/netgear rt314 router
## only 'm'atched or 'n'ot matched 'D'rops
if (&ischain($7)) {
$proto = $protonum{$4};
if ($proto == 1) {
@last = ($1,$proto,$2,-1,$3,8);
} else {
@last = ($1,$proto,$2,$5,$3,$6);
}
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+kernel:\s+(.*):\s+IN=(\S*)\s+OUT=(\S*)\s+(?:MAC=[\d,a-f,:]+\s+)?SRC=([\d,\.]+)\s+DST=([\d,\.]+)\s+LEN=\d+\s+TOS=[\w,x]+\s+PREC=[\w,x]+\s+TTL=\d+\s+ID=\d+\s+(?:DF\s+)?PROTO=(\w+)(?:\s+TYPE=(\d+)\s+CODE=(\d+))?(?:\s+SPT=(\d+)\s+DPT=(\d+))?/) {
## iptables syslog format
if (&ischain($2) && $3 eq $interface) {
$proto = $protonum{$7};
if ($proto == 1) {
## icmp packet
@last = ($1,$proto,$5,-1,$6,$8);
} else {
## tcp/udp/? packet
@last = ($1,$proto,$5,$10,$6,$11);
}
$match = 1;
$success = 1;
} else {
$match = 0;
}
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+inbound\s+(UDP)\s+from\s+([\d,\.]+)\/(\d+)\s+to\s+([\d,\.]+)\/(\d+)/ ||
m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+inbound\s+(\w+)\s+src\s+\w+:\s*([\d,\.]+)\/(\d+)\s+dst\s+\w+:([\d,\.]+)\/(\d+)/ ||
m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Dst\s+IP\s+is\s+network\/broadcast\s+IP,\s+translation\s+creation\s+failed\s+for\s+(\w+)\s+src\s+\w+:\s*([\d,\.]+)\/(\d+)\s+dst\s+\w+:\s*([\d,\.]+)\/(\d+)/ ||
m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Inbound\s+(TCP)\s+connection\s+denied\s+from\s+([\d,\.]+)\/(\d+)\s+to\s+([\d,\.]+)\/(\d+)/) {
## PIX-2-106006, inbound UDP packet
## PIX-3-106010, inbound TCP/UDP packet, broadcast destination
## PIX-3-305006, inbound TCP/UDP packet, broadcast destination
## PIX-2-106001, inbound TCP packet
$proto = $protonum{$4};
@last = ($1,$proto,$5,$6,$7,$8);
$match = 1;
$success = 1;
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+inbound\s+(icmp)\s+src\s+\w+:\s*([\d,\.]+)\s+dst\s+\w+:\s*([\d,\.]+)\s+\(type\s+(\d+),\s+code\s+(\d+)\)/ ||
m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Dst\s+IP\s+is\s+network\/broadcast\s+IP,\s+translation\s+creation\s+failed\s+for\s+(icmp)\s+src\s+\w+:\s*([\d,\.]+)\s+dst\s+\w+:\s*([\d,\.]+)\s+\(type\s+(\d+),\s+code\s+(\d+)\)/) {
## PIX-3-106010, inbound ICMP packet, broadcast destination
## PIX-3-305006, inbound ICMP packet, broadcast destination
$proto = $protonum{$4};
@last = ($1,$proto,$5,-1,$6,$7);
$match = 1;
$success = 1;
} elsif (m/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\S+\s+\%PIX-(\d+)-(\d+):\s+Deny\s+(IP)\s+from\s+([\d,\.]+)\s+to\s+([\d,\.]+),\s+IP\s+options/) {
## PIX-2-106012, inbound IP packet
## currently we do nothing with this packet
} elsif (m/^\w+\s+\d+\s+\d+:\d+:\d+\s+\S+\s+\%PIX-(\d+)-(\d+):\s+.{0,1}last\s+message\s+repeated\s+(\d+)\s+time/ && $match) {
## our last message was a packet log message, so lets repeated the
## previously collected data n times.
$count = $3;
$success = 1;
} elsif (m/^\w+\s+\d+\s+\d+:\d+:\d+\s+\S+\s+last\s+message\s+repeated\s+(\d+)\s+times/ && $match) {
## our last message was a packet log message, so lets repeated the
## previously collected data n times.
$count = $1;
$success = 1;
} else {
## reset match, and update offset
$match = 0;
$offset = tell(FD);
}
if ($success) {
$offset = tell(FD);
&queue_attack($last[0],$last[1],$last[2],$last[3],$last[4],$last[5],$count);
}
}
close(FD);
## enter interval delay loop, we want to sleep currdqinterval seconds and
## pop a queued attack off the stack and upload it while we are waiting
## for the interval delay loop to elapse.
local($then) = time;
while ((time - $then) < $interval) {
if (($currdqinterval - (time - $lastdq)) > $interval) {
&printk("debug: (currdqinterval %lu - (time %lu - lastdq %lu)) > interval %lu\n",$currdqinterval,time,$lastdq,$interval) if ($debug >= 2);
## if interval is greater than current remaining dqinterval then
## just sleep the interval
sleep($interval);
} elsif (($currdqinterval - (time - $lastdq)) > $dqinterval) {
&printk("debug: (currdqinterval %lu - (time %lu - lastdq %lu)) > dqinterval %lu\n",$currdqinterval,time,$lastdq,$dqinterval) if ($debug >= 2);
## if the current remaining dqinterval is greater than dqinterval then
## just sleep the remaining value less one dqinterval
sleep($currdqinterval - (time - $lastdq) - $dqinterval);
} else {
&printk("debug: sleeping currdqinterval %lu - (time %lu - lastdq %lu)\n",$currdqinterval,time,$lastdq) if ($debug >= 2);
## otherwise just sleep the current remaining dqinterval, and then
## dequeue an attack
sleep($currdqinterval - (time - $lastdq));
&dequeue_attack;
$lastdq = time;
}
}
}
## looks up protocol number in list and shows given name, only icmp, tcp and
## udp are in here, as they are likely most of the traffic.
sub show_proto_name {
my($num) = shift if @_;
my(%protonum) = ( ## protocol table
1 => 'icmp', ## icmp
6 => 'tcp', ## tcp
17 => 'udp' ## udp
);
&printk("debug: show_proto_name returning results %s\n",($protonum{$num} eq "" ? $num : $protonum{$num})) if ($debug >= 2);
if ($protonum{$num} ne "") {
## we got a valid protocol number, return it's name
return $protonum{$num};
} else {
## we got a invalid protocol number, return it's number
return $num;
}
}
## checks to see if matches input chain
## 0 on failure, 1 on success
sub ischain {
my($in) = shift;
foreach (@chaintbl) {
if ($in eq $_) {
&printk("debug: ischain returning true, %s == %s\n",$in,$_) if ($debug >= 2);
return 1;
}
}
&printk("debug: ischain returning false\n") if ($debug >= 2);
return 0;
}
## checks to see if source address, port, or port and protocol are filtered
sub isfiltered {
my($proto) = shift;
my($srcaddr) = shift;
my($srcport) = shift;
my($dstaddr) = shift;
my($dstport) = shift;
my($newdstaddr);
my($retcode) = 0;
&printk("debug: isfiltered called with arguments %s,%s,%s,%s,%s\n",
$$proto,$$srcaddr,$$srcport,$$dstaddr,$$dstport) if ($debug >= 2);
## parse through filter table
foreach (@filtbl) {
if (@$_[0] == 0) { ## source addr filter
if (&maskaddress(@$_[1],@$_[2]) == &maskaddress($$srcaddr,@$_[2])) {
$retcode=1;
last;
}
} elsif (@$_[0] == 1) { ## target port filter
if (@$_[1] == $$dstport) { ## target port is a filter match
if (defined(@$_[2])) { ## is proto specified, at all?
if (@$_[2] eq &show_proto_name($$proto)) {
$retcode=1; ## proto and port match, reject
last;
}
} else { ## no proto, port already matchs, so reject
$retcode=1;
last;
}
}
} elsif (@$_[0] == 2) { ## proto filter
if (@$_[1] eq &show_proto_name($$proto)) {
$retcode=1; ## protocol matches, reject
last;
}
} elsif (@$_[0] == 3) { ## destination addr filter
if (&maskaddress(@$_[1],@$_[2]) == &maskaddress($$dstaddr,@$_[2])) {
$retcode=1;
last;
}
} elsif (@$_[0] == 4) { ## source port filter
if (@$_[1] == $$srcport) { ## source port is a filter match
if (defined(@$_[2])) { ## is proto specified, at all?
if (@$_[2] eq &show_proto_name($$proto)) {
$retcode=1; ## proto and port match, reject
last;
}
} else { ## no proto, port already matchs, so reject
$retcode=1;
last;
}
}
} elsif (@$_[0] == 5) { ## target address exchange
if (&maskaddress(@$_[1],@$_[2]) == &maskaddress($$dstaddr,@$_[2])) {
$newdstaddr = @$_[3]; ## address is a match, store the new dstaddr
## in a scalar for use after parsing further
## filter rules
}
} else { ## unknown filter element
&warning("unknown filter element, type=%d\n",@$_[0]);
}
}
## okay, we did a target...xchg, need to reparse filter table with new
## dstaddr.
if (defined $newdstaddr) {
$$dstaddr = $newdstaddr;
$retcode = &isfiltered($proto,$srcaddr,$srcport,$dstaddr,$dstport);
}
&printk("debug: isfiltered returning results %s\n",$retcode) if ($debug >= 2);
return $retcode;
}
## apply netmask to address and return result
sub maskaddress {
my($address) = shift;
my($netmask) = shift;
&printk("debug: maskaddress returning results %s\n",&addr_to_32($address) & &addr_to_32($netmask)) if ($debug >= 2);
return (&addr_to_32($address) & &addr_to_32($netmask));
}
## convert dotted ip notation to 32-bit number
sub addr_to_32 {
my($address) = shift;
my($a1,$a2,$a3,$a4);
($a1,$a2,$a3,$a4) = split(/\./,$address);
&printk("debug: addr_to_32 returning results %s\n",($a1 << 24) | ($a2 << 16) | ($a3 << 8) | $a4) if ($debug >= 2);
return ($a1 << 24) | ($a2 << 16) | ($a3 << 8) | $a4;
}
## translate date into format required, and utc
sub transdate {
my($date) = shift;
my($time_t);
my(%monnum) = (
'Jan' => 0,
'Feb' => 1,
'Mar' => 2,
'Apr' => 3,
'May' => 4,
'Jun' => 5,
'Jul' => 6,
'Aug' => 7,
'Sep' => 8,
'Oct' => 9,
'Nov' => 10,
'Dec' => 11
);
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
## if date is in correct format, translate it to utc
if ($date =~ m/^(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$time_t = POSIX::mktime($5,$4,$3,$2,$monnum{$1},$year,0,0,$isdst);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time_t + $gmt);
return sprintf "%04d-%02d-%02d %02d:%02d:%02d",($year + 1900),
($mon + 1),$mday,$hour,$min,$sec;
} elsif ($date =~ m/^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)\s+UTC/) {
return sprintf "%04d-%02d-%02d %02d:%02d:%02d",$1,$2,$3,$4,$5,$6;
} elsif (($date =~ m/^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/) ||
($date =~ m/^(\d+)\/(\d+)\/(\d+),(\d+):(\d+):(\d+)/)) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$time_t = POSIX::mktime($6,$5,$4,$3,($2 - 1),($1 - 1900),0,0,$isdst);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($time_t + $gmt);
return sprintf "%04d-%02d-%02d %02d:%02d:%02d",($year + 1900),
($mon + 1),$mday,$hour,$min,$sec;
}
## otherwise we use current utc time
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);
return sprintf "%04d-%02d-%02d %02d:%02d:%02d",($year + 1900),
($mon + 1),$mday,$hour,$min,$sec;
}
## adds attack data to outbound queue
sub queue_attack {
my($datetime) = shift;
my($proto) = shift;
my($srcaddr) = shift;
my($srcport) = shift;
my($dstaddr) = shift;
my($dstport) = shift;
my($count) = shift;
## we are going to do some prefiltering, even though in some cases we
## don't know the destination address
if (!&isfiltered(\$proto,\$srcaddr,\$srcport,\$dstaddr,\$dstport)) {
## initialize some local variables
my($mqe);
my($success) = 0;
## first thing we want to do is find a matching entry already in the
## queue, we report time on first attack, this shouldn't be a problem
## unless the interval is set too large, say more than 2 minutes.
foreach $mqe (@msgq) {
## if this attack matches a previously queued one then increment
## the attack count. criteria for matching is same proto,
## source address, dest address, dest port.
if (@$mqe[1] == $proto && @$mqe[2] eq $srcaddr &&
@$mqe[4] eq $dstaddr && @$mqe[5] == $dstport) {
## add the attack count of this one to the queued one
@$mqe[6] += $count;
&printk("debug: incq: %s,%s,%s,%s,%s,%s,%s\n",
@$mqe[0],@$mqe[1],@$mqe[2],@$mqe[3],@$mqe[4],@$mqe[5],
@$mqe[6]) if ($debug);
$success = 1;
last;
}
}
## if it wasn't already in the queue, add it now
if (!$success) {
## add it to the outbound attack queue
push(@msgq,[&transdate($datetime),$proto,$srcaddr,$srcport,$dstaddr,$dstport,$count]);
&printk("debug: addq: %s,%s,%s,%s,%s,%s,%s\n",
&transdate($datetime),$proto,$srcaddr,$srcport,$dstaddr,$dstport,
$count) if ($debug);
}
}
}
## dequeue attack and upload to server
sub dequeue_attack {
my($datetime,$proto,$srcaddr,$srcport,$dstaddr,$dstport,$count);
my($lastmq,@mqe);
## only process if there is something in queue
if ($#msgq >= 0) {
## pull last entry out, and store it in some local variables
$lastmq = $msgq[$#msgq];
@mqe = @$lastmq;
$datetime = $mqe[0];
$proto = $mqe[1];
$srcaddr = $mqe[2];
$srcport = $mqe[3];
$dstaddr = $mqe[4];
$dstport = $mqe[5];
$count = $mqe[6];
## attempt to submit the report, if successful then pop it off the msgq
if (&submit_report($datetime,$proto,$srcaddr,$srcport,$dstaddr,$dstport,$count)) {
## we can officially pop it off the stack now, since it was
## successfully uploaded.
pop(@msgq);
&printk("debug: popq: %s,%s,%s,%s,%s,%s\n",
$datetime,$proto,$srcaddr,$srcport,$dstaddr,$dstport,
$count) if ($debug);
} else {
## backoff factor, calculate into currdqinterval
$currdqinterval *= $backoff;
## set currdqinterval to maxbackoff if we exceed it
$currdqinterval = $maxbackoff if ($currdqinterval > $maxbackoff);
## failed, dump whatever server responded with
&warning("unable to upload %d attack(s) from %s:%d to %s:%d/%s, dequeue interval backing off to %lu seconds.\n",$count,$srcaddr,$srcport,$dstaddr,$dstport,&show_proto_name($proto),$currdqinterval);
}
}
}
## uploads data to server and parses
## returns 0 on failure, 1 on success
sub submit_report {
my($datetime) = shift;
my($proto) = shift;
my($srcaddr) = shift;
my($srcport) = shift;
my($dstaddr) = shift;
my($dstport) = shift;
my($count) = shift;
my($request);
my($output);
my($response);
my($sd);
my($success) = 0;
if ($test) {
if (!&isfiltered(\$proto,\$srcaddr,\$srcport,\$dstaddr,\$dstport)) {
## we are in 'test' mode, don't actually upload data
&printk("upload %d attack(s) from %s%s to %s%d/%s successful (test mode).\n",$count,$srcaddr,($srcport >= 0 ? sprintf(":%d",$srcport) : ""),($dstaddr ne "-1" ? sprintf("%s:",$dstaddr) : ""),$dstport,&show_proto_name($proto));
}
return 1;
}
## open new socket to server
{
local $^W = 0;
if (defined $proxyserver && defined $proxyport) {
$sd = IO::Socket::INET->new(
PeerAddr => $proxyserver,
PeerPort => $proxyport,
Proto => 'tcp');
## start building HTTP get request, via proxy
$output = sprintf "GET http://%s:%lu%s",$server,$port,$script;
} else {
$sd = IO::Socket::INET->new(
PeerAddr => $server,
PeerPort => $port,
Proto => 'tcp');
## start building HTTP get request
$output = sprintf "GET %s",$script;
}
if (!defined($sd)) {
## socket error, we bail out with a failure to retry later
&warning("cannot connect to %s: socket: %s\n",$server,$@);
return 0;
}
}
## we only want to probe the IP address if we don't know it, basically for
## log formats such as portsentry.
if ($dstaddr eq "-1") {
&printk("debug: dstaddr is %s, probing\n",$dstaddr) if ($debug);
$dstaddr = sprintf("%s.%s.%s.%s",unpack("C4",(unpack("S n a4 x8",getsockname($sd)))[2]));
&printk("debug: acquired %s address from socket probe\n",$dstaddr) if ($debug);
}
## check to see if this firewall entry is filtered
if (&isfiltered(\$proto,\$srcaddr,\$srcport,\$dstaddr,\$dstport)) {
## packet is filtered, return with a success code
&printk("debug: packet is filtered, dropping\n") if ($debug);
return 1;
}
## build our data submission portion of url
$request = sprintf "AgentEmail=%s&AgentPassword=%s&AttackerIP=%s&DestPort=%s&VictimIP=%s&AttackCount=%s&AttackDateTime=%s&ProtocolID=%s",$agtname,$agtpass,$srcaddr,$dstport,$dstaddr,$count,$datetime,$proto;
## convert spaces to %20
$request =~ s/ /%20/g;
## attach data to end of get
$output .= sprintf "?%s HTTP/1.0\n",$request;
## build out HTTP GET request
$output .= sprintf "Host: %s\n",$server;
$output .= "Content-Type: application/x-www-form-urlencoded\n";
$output .= sprintf "User-Agent: myNetWatchman Perl Agent/%s\n\n",$mnwvers;
## send it via the socket created
print $sd $output;
## print debugging, if requested
&printk("debug: send [%s]\n",$output) if ($debug >= 10);
## read in data from socket, setup for failure
$success=0;
$response="";
while (<$sd>) {
$response .= $_;
&printk("debug: read [%s]\n",$_) if ($debug >= 10);
if (m/Attack\s+Report\s+Insert\s+Successful/) {
## we were successful, success should be 1
$success=1;
}
}
close($sd);
if (!$success) {
if ($response =~ m/Error:\s+(.*?)<BR>/) {
&warning("error response returned: %s\n",$1);
} else {
&warning("unknown response on attack insert from %s.\n",$server);
}
return 0;
} else {
## upload successful
&printk("upload %d attack(s) from %s%s to %s:%d/%s successful.\n",$count,$srcaddr,($srcport >= 0 ? sprintf(":%d",$srcport) : ""),$dstaddr,$dstport,&show_proto_name($proto));
$currdqinterval = $dqinterval;
return 1;
}
## should never reach this far
return 0;
}
## warning message
sub warning
{
printf STDERR "warning: " if (!$quiet);
printf STDERR @_ if (!$quiet);
&printk(@_);
}
## fatal message
sub fatal
{
printf STDERR "fatal: ";
printf STDERR @_;
&printk(@_);
exit 1;
}
## print kernel style message to custom log file
sub printk
{
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
my(%months) = (
0 => 'Jan',
1 => 'Feb',
2 => 'Mar',
3 => 'Apr',
4 => 'May',
5 => 'Jun',
6 => 'Jul',
7 => 'Aug',
8 => 'Sep',
9 => 'Oct',
10 => 'Nov',
11 => 'Dec'
);
## open log file for appending
open(LOGMSG,">>".$errorlog) || die "fatal: unable to append to error log: $!\n";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
printf LOGMSG "%s %2s %02d:%02d:%02d mnwclient[%d]: ",$months{$mon},$mday,
$hour,$min,$sec,$$;
printf LOGMSG @_;
close(LOGMSG);
}
On Sun, 17 Jun 2001, Mike Meyer wrote:
> Dru <genisis@istar.ca> types:
> > However, when I try to start the script manually or when I reboot, I get
> > an error message stating the script is not found:
> >
> > /etc/rc: /usr/local/etc/rc.d/mnwclient.sh: not found
> >
> > What am I missing here besides my sanity? I've attached the script if that
> > helps.
>
> The #! line in the script is fubar for some reason that's causing the
> kernel exec to fail. The report back to the shell is that the file
> isn't executable (stupid, but apparently required by Posix), so the
> shell reports that it can't find the executable.
>
> Joe Clark's guess - that it's pointing at the wrong place - is the
> usual cause for that. There are other things that might make it do
> that as well.
>
> Can you send just that line? I know you attached the script, but
> freebsd.org's mail digester eats the MIME headers, so my mailer can't
> decode what you sent :-(.
>
> <mike
> --
> Mike Meyer <mwm@mired.org> http://www.mired.org/home/mwm/
> Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-questions" in the body of the message
>
>
>
>
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010617141853.S48172-100000>
