#!/usr/local/bin/perl -Tw ###################################################################### # Thomas P. Kelliher, Goucher College. (c) 2000. # # This telnet, ssh, etc. replacement will send e-mail to $recipient. # The e-mail will contain the IP address and, if possible, the FQDN # of the client attempting the connection. The contact information in # $contact is returned to the client. # # The purpose of this script is to monitor connections to ports which # shouldn't be receiving connections. # # We assume we're being called via inetd. inetd.conf should be # configured to run this as nobody, but we'll be paranoid and try # to guarantee that. If we're being run as root we'll change UID to # nobdy. So, this script assumes that there's a nobody user on the # system. This is true for BSD/OS, Solaris, and Linux. # # The inetd parent process will fork a child on connection. The # child closes all its descriptors, save for the socket, dups the # socket to STDIN, STDOUT, and STDERR, and exec's the service handler # (this program). Thus the socket calls on STDIN below. Also note # this allows us to use standard I/O to communicate with the client. # # Some constants below need to be configured. The shebang line may # need to be modified. ###################################################################### use strict; use Socket; ###################################################################### # Constants. These need to be configured. ###################################################################### #Path to mail client. my $mailPath = "/usr/bin/mail"; # Recipient of the e-mail. Also part of contact information. my $recipient = "kelliher\@bluebird.goucher.edu"; # Contact information. my $contact = " Tom Kelliher\r\n" . " (410) 337-6189\r\n" . " $recipient"; # How many seconds to sleep before exiting. my $delay = 10; # Index of UID field in a passwd file entry. my $uidIndex = 2; ###################################################################### MAIN: ###################################################################### { # Port and IP address of either end of socket. my $port; my $ipaddr; my $rootUid; # UID of root. my $nobodyUid = ""; # UID of nobody user. my $lsocket; # Socket at this end. my $rsocket; # Socket at remote end. my $host; # FQDN. my $straddr; # Remote IP address in ASCII. my $service; # Local port contacted. $ENV{"PATH"} = ""; # Clean things up. # If we're running as root, change UIDs to nobody. $rootUid = (getpwnam("root"))[$uidIndex]; if ($< == $rootUid) { $nobodyUid = (getpwnam("nobody"))[$uidIndex]; $< = $nobodyUid; } # Get all relevant socket information. If we're not connected to a # socket, just exit. if (!($lsocket = getsockname(STDIN))) { exit(1); } $rsocket = getpeername(STDIN); # Determine what local port we're on. ($port, $ipaddr) = unpack_sockaddr_in($lsocket); $service = getservbyport($port, "tcp") || "Port $port"; # Get remote IP address and try to get a FQDN. ($port, $ipaddr) = unpack_sockaddr_in($rsocket); $host = gethostbyaddr($ipaddr, AF_INET) || "Could not reverse map IP address"; $straddr = inet_ntoa($ipaddr); # Log connection via a piece of e-mail. open(MAIL, "|$mailPath -s \"$service connection\" $recipient"); print MAIL "$service connection received from: $host [$straddr].\n"; if ($nobodyUid) { print MAIL "\nThis script was running as root originally.\n" } close(MAIL); # If we're ssh, just quietly exit. if ($service eq "ssh") { exit(0); } # Unbuffer output and send contact information to remote client. $| = 1; print "\r\n\r\n", "If you need access to this machine, please contact:\r\n\r\n", "$contact\r\n\r\n"; # Give them some time to read it. sleep $delay; exit 0; }