Customising the eFa Spam Filter

After deploying eFa there’s a few additional changes that you might want to do but requires customising the eFa spam filter entirely.

These don’t have to be done and really depend on your use case for it.


Customising Outbound IP list

When you change the Outbound IP’s it wipes all settings already stored. It’s fine with a few IP’s but when adding more than a few it becomes more than a little bit annoying. One person can wipe the entire config just by forgetting to copy and paste the previous info. There was no easily solution to this, so I had to modify the postfix file and also re-write one of the modules (or you could just use the script outside EFA).

The rewrite isn’t that complicated and basically makes postfix use a text file instead of modifying the config inline. The re-written module basically just takes a backup of it, opens nano and then when closed restarts the sevice. It doesn’t do any form of IP checking (yet), so an invalid subnet id WILL stop all IP’s after that line.

Create the config file and add the contents of the line below it (or EFA won’t send emails!)

nano /etc/postfix/OutboundIPs
[::1]/128                                       # EFA - DO NOT REMOVE
127.0.0.0/8                                     # EFA - DO NOT REMOVE

Modify /etc/postfix/main.cf. Find the mynetworks line (at the bottom of the file) and modify it to the following:

mynetworks = /etc/postfix/OutboundIPs

The re-written functions can be a bit annoying in that it’ll clear when EFA is updated. This is to be expected and rather than forking the project I just run a simple find a replace script to rename the old function and add in the new one.

Create a txt file to /root/customisations/robsoutboundrelay.txt containing the following:

# +---------------------------------------------------+
# Robs outbound relay
# +---------------------------------------------------+
func_outbound-relay(){
  obmrmenu=1
  while [ $obmrmenu == "1" ]
    do
      RELAYS=`cat /etc/postfix/OutboundIPs`
          postfixstatus=`systemctl show -p ActiveState postfix | sed 's/ActiveState=//g'`
                if [[ ${postfixstatus^^} = "ACTIVE" ]]
                then
                        postfixstatus="$green${postfixstatus^^}$clean"
                else
                        postfixstatus="$red${postfixstatus^^} - PLEASE STOP WHAT YOU ARE DOING AND CHECK THE OUTPUT LIST IS CORRECT OR ASK ROB$clean"
                fi
      func_echo-header
          echo -e "Postfix is currently $postfixstatus"
      echo " "
      echo "This is where to add all the authorised IP addresses outbound."
      echo "IP list:"
      echo "$RELAYS"
          echo ""
          echo -e "Postfix is currently $postfixstatus"
      echo ""
      echo "1) Edit IP list              Please follow standard x.x.x.x/XX   #CUSTCODE - CLIENT (ISP)"
      echo "e) Return to main menu"
      echo ""
      local choice
      read -p "Enter setting you want to change: " choice
      case $choice in
        1)  echo ""
            echo "Add the IPs following the preset standard"
            echo ""
            cp /etc/postfix/OutboundIPs /root/IPBackups/OutboundIPs.bak-`date -Iminutes`
            nano /etc/postfix/OutboundIPs
            sort -k2 -b -o /etc/postfix/OutboundIPs /etc/postfix/OutboundIPs
            postmap /etc/postfix/OutboundIPs
            systemctl reload postfix

            obmrmenu=1
            ;;
            e) mailmenu=1 && return ;;
        *) echo -e "Error \"$choice\" is not an option..." && pause
      esac
    done
}
# +---------------------------------------------------+

Then run the following script to disable the old function and add in the new one:

sed -i 's/func_outbound-relay(){/func_outbound-relay-DISABLED(){/g' /var/eFa/lib/eFa-Configure/func_mailsettings
cat /root/customisations/robsoutboundrelay.txt >> /var/eFa/lib/eFa-Configure/func_mailsettings

Replacing the boring banner with something a bit more fun

So to help identify if the mod from above is in place I thought it would be interesting to adjust the normal eFa banner with some ascii art.

This seemed simple enough to do but ended up being a little bit annoying in trying to escape random characters. That was before I realised I could just cat the output…

I know there’s another tool that could be done to just output it on the fly but in this case this worked nice enough to not need to find another way.

Create the ascii banner you want, save it to /root/customisations/banner.txt and then run the below script:

sed -i '/  echo -e "--------------------------------------------------------------"/d'  /usr/sbin/eFa-Configure
sed -i '/  echo -e "---        Welcome to the eFa Configuration program        ---"/d'  /usr/sbin/eFa-Configure
sed -i 's/  echo -e "---               https:\/\/www.efa-project.org              ---"/cat \/root\/customisations\/banner.txt/g'  /usr/sbin/eFa-Configure

This should replace all the standard banner and add the cat /root/customisations/banner.txt entry. I had tried to make it cleaner by replacing the function like with the Outbound IP’s but for some reason it wouldn’t work and I didn’t really care to spend any longer trying to get a silly banner replaced!


Bulk adding users

The bulk-add script provided by eFa was for v3 and doesn’t directly translate to v4 properly. Noticably the paths are slightly different AND one of the varibles had to be in speech marks for it to actually work.

For long term use I’d rather use LDAP to pull the information directly from AD but in this case only 2 clients needed it and it wouldn’t have been configured for long – so wasn’t worth the extra time spending on it to get multiple LDAP config set up.

The script is just a fix from the original version with an additon to enable the daily quarantine emails. There is no additonal checks on this as I just added it as a last minute additon.

#!/bin/bash
# +--------------------------------------------------------------------+
# EFA Project user immport script fixed by Robachicken
#+--------------------------------------------------------------------+

SQLTMPFILE="userimport.sql"
SQLTMPDIR="/tmp/EFA/"
infile=""
append="0"
overwrite="0"
quiet="0"


function help(){
  echo 
  echo "EFA Mass User Import Help"
  echo 
  echo "userimport.sh  Copyright (C) 2014  efa-project.org"
  echo "Licensed GNU GPL v3. This program comes with ABSOLUTELY NO WARRANTY"
  echo "This is free software, and you are welcome to redistribute it under"
  echo "certain conditions.  See http://www.gnu.org/licenses for more details"
  echo 
  echo "Usage: userimport.sh -f mylist -a|-o [-q]"
  echo "-a      append to existing list"
  echo "-q      force overwrite database tables without prompting"
  echo "-o      overwrite existing list (admins and domain admins exempt)"
  echo
  echo "user list mylist is newline comma separated list with each"
  echo "line in the following format:"
  echo 
  echo '<username>,<password>,<fullname>,<type>,<qreport>'
  echo 'type={A,D,U,R,H}'
  echo 'qreport={0,1}'
}

if [[ "$#" == "0" ]]; then
  help  
fi

if [[ `whoami` != "root" ]]; then
  echo "Root access is required to execute script, exiting."
  exit 1
fi

while [[ $# > 0 ]]
do
  param="$1"
  shift

  case $param in
    -f|--file)
    infile="$1"
    shift
    ;;
    -a|--append)
    append="1"
    ;;
    -q|--quiet)
    quiet="1"
    ;;
    -o|--overwrite)
    overwrite="1"
    ;;
    *)
    help
    ;;
  esac  
done

flag="0"
# parameter sanity check
if [[ $overwrite == "1" && $append == "1" ]]; then
  echo "Incompatible parameter combination (-a and -o)"
  flag="1"
fi

if [[ $quiet == "1" && $overwrite == "0" ]]; then
  echo "Quiet flag (-q) used without overwrite (-o)"
  flag="1"
fi

if [[ $infile == "" ]]; then
  echo "No input file specified"
  flag="1"
elif [[ ! -f $infile ]]; then
  echo "File not found or not a regular file"
  flag="1"
fi

[ $flag == "1" ] && exit 1

# get access to mysql
MAILWATCHSQLPWD=`grep MAILWATCHSQLPWD /etc/eFa/MailWatch-Config | sed 's/.*://'`
if [[ -z $MAILWATCHSQLPWD ]]; then
  echo "Unable to access SQL password from /etc/EFA-Config, exiting."
fi

# Build SQL SCript Header and prompt for overwrite if needed
mkdir -p $SQLTMPDIR
rm -f $SQLTMPDIR$SQLTMPFILE
touch $SQLTMPDIR$SQLTMPFILE
echo 'LOCK TABLES `users` WRITE;' >> $SQLTMPDIR$SQLTMPFILE

if [[ $overwrite == "1" ]]; then
  if [[ $quiet == "0" ]]; then
    flag="0"
    echo "The table in mySQL will be overwritten with values from your file."
    echo -n "Continue? (y/N):"
    read CONFIRM
    while [ $flag -eq 0 ]
      do
        if [[ $CONFIRM == "y" || $CONFIRM == "Y" ]] 
        then
          flag="1"
        elif [[ $CONFIRM == "n" || $CONFIRM == "N" || $CONFIRM == "" ]]; then
          exit 1
        else
          echo -n "Continue? (y/N):"
          read CONFIRM
        fi
      done
  fi
  
  echo "DELETE from \`users\` where type RLIKE '[UHR]';" >> $SQLTMPDIR$SQLTMPFILE 
  
  fi

# Lock Tables for writing and begin input
  echo -n 'INSERT INTO `users` (username,password,fullname,type,quarantine_report) VALUES ' >> $SQLTMPDIR$SQLTMPFILE
  
  # Process each line of file

firstloop="1"
TMPIFS=$IFS
IFS=","
while read col1 col2 col3 col4 col5
do
  username=""
  password=""
  fullname=""
  type=""
  quarantine_report="1"
  # check input length 
  username=$col1
  if [[ $username != "" && $username =~ ^.{2,60}$ ]]; then
    password=$col2
    
    if [[ $col2 != "" && $col2 =~ ^.{4,32}$ ]]; then
      password=$col2
      if [[ $col3 =~ ^.{0,50}$ ]]; then
        fullname=$col3
        if [[ $col4 != "" && $col4 =~ ^[ADURH]$ ]]; then
            type=$col4
		quarantine_report=$col5
        fi
      fi
     fi
   if [[ $firstloop != "1" ]]; then
      echo -n "," >> $SQLTMPDIR$SQLTMPFILE
    else
      firstloop="0"
    fi
    echo -n "('$username',md5('$password'),'$fullname','$type','$quarantine_report')" >> $SQLTMPDIR$SQLTMPFILE
  fi  

done < "$infile"
IFS=$TMPIFS

echo ";" >> $SQLTMPDIR$SQLTMPFILE
echo "UNLOCK TABLES;" >> $SQLTMPDIR$SQLTMPFILE

# Import into MySQL
 mysql -u mailwatch --password=$MAILWATCHSQLPWD mailscanner < /tmp/EFA/userimport.sql

# Cleanup
rm -f /tmp/EFA/userimport.sql
rmdir /tmp/EFA

This should be used using the below standard but don’t forget to remove the original lines before running!

EmailAddress,Password,Fullname,UserType,QReport

As an example:

[email protected],Password,FullName,U,1