#!/bin/bash # #!F:reject-masq # #!P:/usr/local/sbin # #!D:Reject old connections after shutting down ISDN link #!D: for kernel 2.1.102+ (usage of ipchains) # #!C:Copyright 1999-2001 by Peter Bieringer #!C: Idea taken from reject-masq.c (usage of ipfwadm) #!C: with Copyright (C) Jochen Roedenbeck 1998 # Changes to # 1.01: first published release # 1.02: also locally outgoing connections # 1.03: do not block "localhost" connections, add log file output # 20000129: add dial device # 20000624: Adapt localnet # 20010124 [feature]: get local network from local interfaces instead from a define # 20010124 [bugfix]: also recognize outgoing UDP connections, fix lockfile output #### Defines (perhaps to change) # Dialout device DIALOUTDEVICE="ippp+" # default timeout in seconds TIMEOUT=3600 #### Defines (normally not for changing) # A debug value can be set here DEBUG=$[ 65535 - 256 -128 -1 -512 -2 -4 -64] #DEBUG=0 # & 1: show given options # & 2: print option runtime echos # & 4: show connections to test # & 64: do not execute $BIN_IPCHAINS # & 128: use file instead of real connections # & 256: Exctraction of local network addresses # & 512: Show extracted network addresses # Prefix of names of local interfaces NAMEPREFIXIFACE="^eth|^tr|^lo" # Prefix of the lock file IPMASQLOCKPREFIX="MASQ" ## Define used binaries BIN_IFCONFIG="/sbin/ifconfig" BIN_IPCHAINS="/sbin/ipchains" BIN_NETSTAT="/bin/netstat" ## Define of used tmpfiles FILE_TMP="/tmp/reject-masq-ng.tmp" # Log file name FILELOG=/var/log/reject-masq # Log active? DOLOG=1 #DOLOG=0 #### Known bugs # Works only with subnet masks of 8, 16 or 24 bit #### ToDo # Abstract rules to use also iptables (netfilter) #### Description is taken from reject-masq.c # # If dynamic IP address allocation is used to connect the Internet # all connections become invalid when the ISDN link is shut down. # Nevertheless data for these old connections can be sent. This program # installs firewall rules to reject these data and to prevent the ISDN # system from calling out for a dead connection. # # usage: # a) reject-masq --insert # # /proc/net/ip_masquerade is read. For each line in this file a # forwarding firewall rule is installed to reject all packets # for the connection. A file /var/run/MASQ.* is written containing # the options for deleting the installed firewall rules. # # This command should be used in /etc/ppp/ip-down. # # b) reject-masq --delete [time-out value] # # /var/run/ is scanned for MASQ.* files. If creation time of the file # is more than "time-out value" seconds ago the firewall entries # listed in the file are deleted by calling /sbin/ipfwadm. The file # is deleted, too. If no time-out value is specified 3600s (1h) is # used. # # This command should be called periodically by a crontab entry. # # c) reject-masq --deleteall # # like b), but delete all firewall entries regardless of time-out value # # d) reject-masq -l # # list /proc/net/ip_masquerade and /var/run/MASQ.* # #### Start here umask 0077 # Remove tmp file rm -rf $FILE_TMP #set -x [ "$DEBUG" != "0" ] && echo "Debug level is $DEBUG" if [ $[ $DEBUG & 128 ] != 0 ]; then echo " Using file instead of kernel-proc" IPMASQEXEC="cat ./ip_masquerade" IPCONEXEC="cat ./ip_localconn" IPMASQLOCK="." else IPMASQEXEC="$BIN_NETSTAT --masquerade --numeric -A inet" IPCONEXEC="$BIN_NETSTAT --numeric -A inet" IPMASQLOCK="/var/run" fi ## Get local network addresses # Get local interfaces cat /proc/net/dev | grep ':' | awk -F: '{ print $1 }' | awk '{ print $1 }' | egrep $NAMEPREFIXIFACE | while read interface rest; do if [ $[ $DEBUG & 256 ] != 0 ]; then echo "Found interface: $interface" >&2 fi # Get IP addresses and netmask $BIN_IFCONFIG $interface |grep 'inet addr:'| while IFS=": " read tag tag ip tag broad tag mask; do if [ "$interface" = "lo" ]; then # fix localhost mask=$broad broad="" fi if [ $[ $DEBUG & 256 ] != 0 ]; then echo -n " IP:$ip Bcast:$broad Mask:$mask" >&2 fi # calculate network network=`ipcalc --network $ip $mask | awk -F= '{ print $2 }'` if [ $[ $DEBUG & 256 ] != 0 ]; then echo " Network:$network" >&2 fi # Cut off suffix if [ "$mask" = "255.255.255.0" ]; then networkprefix=`echo $network | awk -F. '{ print $1 "." $2 "." $3 "." }'` elif [ "$mask" = "255.255.0.0" ]; then networkprefix=`echo $network | awk -F. '{ print $1 "." $2 "." }'` elif [ "$mask" = "255.0.0.0" ]; then networkprefix=`echo $network | awk -F. '{ print $1 "." }'` else echo -e "\a Unsupported netmask $mask on interface $interface" >&2 exit 1 fi echo -n " $networkprefix" done done >$FILE_TMP # Echo networks if [ $[ $DEBUG & 512 ] != 0 ]; then echo "Extracted local network prefixes: " >&2 cat $FILE_TMP >&2 echo fi # Convert extracted local networks to a egrep match rule LOCALNETPREFIX=`cat $FILE_TMP | sed 's/\./\\\./g' | sed 's/ /|\^/g' | cut -c 2-` # Echo networks if [ $[ $DEBUG & 512 ] != 0 ]; then echo " For match: $LOCALNETPREFIX" >&2 fi ## some functions usage() { echo " Options: (see script contents for details)" echo " reject-masq [--insert|--delete [timeout]|--deleteall|--list|-l]" } insertFWrules() { date=`date +%s` LOCKFILE=$IPMASQLOCK/$IPMASQLOCKPREFIX.$date # Delete lockfile, if exists if [ -f $LOCKFILE ]; then cat /dev/null >$LOCKFILE fi [ $[ $DEBUG & 4 ] != 0 ] && echo "Test masqueraded connections" $IPMASQEXEC | while read proto expire srcip dstip srcprt dummy dstprt dummy; do if [ "$proto" = "tcp" -o "$proto" = "udp" -o "$proto" = "icmp" ]; then [ $[ $DEBUG & 4 ] != 0 ] && echo " Got: $srcip:$srcprt / $dstip:$dstprt" fwruleinfo="forward -p $proto -s $srcip $srcprt -d $dstip $dstprt -i $DIALOUTDEVICE -j REJECT" if [ $[ $DEBUG & 64 ] != 0 ]; then echo " Exec: $BIN_IPCHAINS -I $fwruleinfo" else if [ "$DOLOG" = "1" ]; then echo "Insert: $fwruleinfo" >>$FILELOG fi $BIN_IPCHAINS -I $fwruleinfo echo $fwruleinfo >>$LOCKFILE fi fi done [ $[ $DEBUG & 4 ] != 0 ] && echo "Test outgoing connections" $IPCONEXEC | egrep "^tcp|^udp" | while read proto recvQ sendQ source destination status; do if [ "$proto" = "tcp" -o "$proto" = "udp" ]; then srcip=`echo $source | awk -F: '{ print $1 }'` srcprt=`echo $source | awk -F: '{ print $2 }'` dstip=`echo $destination | awk -F: '{ print $1 }'` dstprt=`echo $destination | awk -F: '{ print $2 }'` [ $[ $DEBUG & 4 ] != 0 ] && echo " Test: $srcip:$srcprt / $dstip:$dstprt" if ! echo $srcip | egrep -q $LOCALNETPREFIX ; then echo " Get: $srcip:$srcprt / $dstip:$dstprt" fwruleinfo="output -p $proto -s $srcip $srcprt -d $dstip $dstprt -i $DIALOUTDEVICE -j REJECT" if [ $[ $DEBUG & 64 ] != 0 ]; then echo " Exec: $BIN_IPCHAINS -I $fwruleinfo" else if [ "$DOLOG" = "1" ]; then echo "Insert: $fwruleinfo" >>$FILELOG fi $BIN_IPCHAINS -I $fwruleinfo echo $fwruleinfo >>$LOCKFILE fi fi fi done } ## main if [ $[ $DEBUG & 1 ] != 0 ]; then echo " Option1: $1" fi # insert # if [ "#$1" = "#--insert" ]; then [ $[ $DEBUG & 2 ] != 0 ] && echo " 'insert': start" if [ "$DOLOG" = "1" ]; then echo "Triggered: INSERT at `date`" >>$FILELOG fi insertFWrules [ $[ $DEBUG & 2 ] != 0 ] && echo "'insert': done" # delete # elif [ "#$1" = "#--delete" ]; then [ $[ $DEBUG & 2 ] != 0 ] && echo " 'delete': start" if ! [ "$2" = "" ]; then TIMEOUT=$2 fi if [ "$DOLOG" = "1" ]; then echo "Triggered: DELETE with timeout $TIMEOUT at `date`" >>$FILELOG fi date=`date +%s` for i in $IPMASQLOCK/$IPMASQLOCKPREFIX.*; do if ! [ "$i" = "$IPMASQLOCK/$IPMASQLOCKPREFIX.*" ]; then fwdate=`echo $i | awk -F. '{ print $NF }'` difftime=$[ $date - $fwdate ] # echo "Current time: $date, fwrule: $fwdate, diff: $difftime" if [ $difftime -ge $TIMEOUT ]; then [ $[ $DEBUG & 2 ] != 0 ] && echo " Rule has reached timeout" cat $i | while read line; do if [ $[ $DEBUG & 64 ] != 0 ]; then echo " Exec: $BIN_IPCHAINS -D $line" else $BIN_IPCHAINS -D $line 2>/dev/null fi if [ "$?" = "0" ]; then if [ "$DOLOG" = "1" ]; then echo "Remove: $line" >>$FILELOG fi fi done rm -f $i fi fi done [ $[ $DEBUG & 2 ] != 0 ] && echo " 'delete': done" # deleteall # elif [ "#$1" = "#--deleteall" ]; then [ $[ $DEBUG & 2 ] != 0 ] && echo " 'deleteall': start" if [ "$DOLOG" = "1" ]; then echo "Triggered: DELETEALL at `date`" >>$FILELOG fi for i in $IPMASQLOCK/$IPMASQLOCKPREFIX.*; do if ! [ "$i" = "$IPMASQLOCK/$IPMASQLOCKPREFIX.*" ]; then cat $i | while read line; do if [ $[ $DEBUG & 64 ] != 0 ]; then echo " Exec: $BIN_IPCHAINS -D $line" else $BIN_IPCHAINS -D $line 2>/dev/null fi if [ "$?" = "0" ]; then if [ "$DOLOG" = "1" ]; then echo "Remove: $line" >>$FILELOG fi fi done rm -f $i fi done [ $[ $DEBUG & 2 ] != 0 ] && echo " 'deleteall': done" # command --list elif [ "#$1" = "#-l" -o "#$1" = "#--list" ]; then [ $[ $DEBUG & 2 ] != 0 ] && echo " 'list': start" echo " List current masquerading information" $IPMASQEXEC echo " List current installed firewalling rules" find $IPMASQLOCK -type f -name "$IPMASQLOCKPREFIX.*" | while read lockfile; do echo "Lockfile: $lockfile" cat $lockfile done [ $[ $DEBUG & 2 ] != 0 ] && echo " 'list': done" else usage exit 1 fi