The following examples use DNS hostnames for clarity. However, in general, it is more secure to use TCP Wrappers with explicit IP addresses. Suppose that you want to allow all connections to your computer, except those from the computers in the domain pirate.net , with a simple /etc/ hosts .allow file. Specify: # # /etc/hosts.allow: # # Allow anybody to connect to our machine except people from pirate.net. # all : .pirate.net : deny all : all : allow Suppose that you want to modify your rules to allow the use of finger from any of your internal machines, but you want to have external finger requests met with a canned message. You might try this configuration file: # # /etc/hosts.allow: # # Allow finger from internal machines; give banner to others. # Otherwise, allow anybody to connect except people from pirate.net. # # in.fingerd : LOCAL : allow in.fingerd : all : twist /usr/local/bin/external_fingerd_message all : .pirate.net : deny all : all : allow If you don't want to allow pirate.net hosts to finger at all, reverse the order of the second and third rule so that the rules denying pirate.net hosts would match first. If you discover repeated break-in attempts through telnet and rlogin from all over the world, but you have a particular user who needs to telnet into your computer from the host sleepy.com , you could accomplish this somewhat more complex security requirement with the following configuration file: # # /etc/hosts.allow: # # Allow email from pirate.net, but nothing else. # Allow telnet and rlogin from sleepy.com, but nowhere else. # telnetd,rlogind : sleepy.com : allow telnetd,rlogind : all : deny in.fingerd : LOCAL : allow in.fingerd : all : twist /usr/local/bin/external_fingerd_message all : .pirate.net : deny all : all : allow Better yet, teach that user to use ssh instead of telnet or rlogin , and disable the telnet and rlogin daemons entirely in /etc/inetd.conf : # # /etc/hosts.allow: # # Allow email from pirate.net, but nothing else. # Allow ssh from sleepy.com, but nowhere else. # telnetd and rlogind are disabled in /etc/inetd.conf, but we list them # here anyway in case someone accidentally re-enables them. This may cause # tcpdchk to produce a warning, though. # sshd : sleepy.com : allow sshd : all : deny in.fingerd : LOCAL : allow in.fingerd : all : twist /usr/local/bin/external_fingerd_message all : .pirate.net : deny telnetd,rlogind : all : deny all : all : allow Here's an example that combines two possible options: # # /etc/hosts.deny: # # Don't allow logins from pirate.net and log attempts. # telnetd,rlogind,sshd : pirate.net : \ spawn=(/security/logit %d deny %c %p %a %h %u)&\ : linger 10 : banners /security/banners In the file /security/banners/telnetd , you would have the following text:
The file should also be linked to /security/banners/rlogind and /security/banners/sshd . The banner will be displayed if anyone from pirate.net tries to log in over the Internet. The system will pause 10 seconds for the message to be fully displayed before disconnecting. In the /security/logit shell file, you could have something similar to the script in Example 12-5. This script puts an entry into the syslog about the event, and attempts to raise a very visible alert window on the screen of the security administrator's workstation. Furthermore, it does a reverse finger on the calling host, and for good measure does a netstat and ps on the local machine. This process is done in the event that some mischief is already occurring that hasn't triggered an alarm. Example 12-5. alert script#!/bin/ksh set -o nolog -u -h +a +o bgnice +e -m # Capture some information about whatever site is twisting my doorknob. # It is probably higher overhead than I need, # but... export PATH=/usr/ucb:/usr/bin:/bin:/usr/etc:/etc mkdir /tmp/root; chown root /tmp/root; chmod 700 /tmp/root # Create /tmp/root in case it doesn't exist (chown it in case it does). print "Subject: Notice\nFrom: operator\n\n$@" /usr/lib/sendmail security typeset daemon="" status="" client="" pid= addr= host= user= # For most things, we simply want a notice. # Unsuccessful attempts are warnings. # Unsuccessful attempts on special accounts merit an alert. typeset level=notice [[ $status != allow ]] && level=warning [[ $daemon = in.@(rshdrlogind) && $user = @(rootsecurity) ]] && level=alert /usr/ucb/logger -t tcpd -p auth.$level "$*" & umask 037 function mktemp { typeset temp=/security/log.$$ typeset -Z3 suffix=0 while [[ -a $temp.$suffix ]] do let suffix+=1 done logfile=$temp.$suffix chgrp security $logfile } function Indent { sed -e 's/^//' >> $logfile } exec 3>&1 >>$logfile 2>&1 date print "Remote host: $host Remote user: $user" print "" print "Local processes:" ps axg Indent print "" print "Local network connections:" netstat -n -a -f inet Indent print "" print "Finger of $host" safe_finger -s @$hostIndent print "" [[ $user != unknown ]] && safe_finger -h -p -m $user@$host Indent exec >> /netc/log/$daemon.log 2>&1 print "-----------------------" print "\npid=$pid client=$client addr=$addr user=$user" print Details in $logfile date print "" # Now bring up an alert box on the admin's workstation. { print "\ndaemon=$daemon client=$client addr=$addr user=$user" print Details in $logfile date print "" print -n "(press return to close window.)" >> /tmp/root/alert.$$ } > /tmp/root/alert.$$ integer lines=$(wc -l < /tmp/root/alert.$$ tr -d ' ') xterm -display security:0 -fg white -bg red -fn 9x15 -T "ALERT" -fn 9x15B\ -geom 60x$lines+20+20 -e sh -c "cat /tmp/root/alert.$$;read nothing" /bin/rm /tmp/root/alert.$$ Note the -n option to the netstat command in the script. This is specified because DNS can be slow to resolve all the IP numbers to names . You want the command to complete before the connection is dropped; it is always possible to look up the hostnames later from the log file. In addition, reverse DNS servers under the control of the attacker might be gimmicked to give misleading information. |