[SOLVED] Fail2ban email - custom

Does anyone know if it is possible for fail2ban to send out email alerts when a peer goes unreachable instead of when an ip gets banned?

me thinks you need to provide a bit more information on what you are trying to do. fail2ban takes action based on log file entries, so i guess, in theory, you could hack it around to send an email if it found ā€œunreachableā€ in the log fileā€¦

:grin:

This is exactly what I thought of doing this morning when I noticed that one of my trunks failedā€¦

I donā€™t know why it does that but once in a while Asterisk decides that one of its trunk is unreachable and it has to be restarted to work againā€¦

Anybody knows why? It sounds like an Asterisk bug to meā€¦

When I noticed the problem I, of course, restarted Asterisk and started googling around and found a few matches (including one on this forum, Notification when trunk is down, which is unfortunately incomplete and I am no Python guruā€¦).

One of those matches suggested using https://sourceforge.net/projects/swatch/ and when I saw the similarity between it and fail2ban I realized fail2ban could most likely be used to do this.

I have not yet tried to make a fail2ban rule for this but my guess is that it would definitely be doableā€¦

Good luck and have a nice day!

Nick

ps: The trunk that failed is the one that provides 911 service!

we switched away from trunk registration years ago and use ip authentication with all our itspā€™s. the trunks donā€™t go offline, no need to worry about things like user id/passwords - more secure

Fail2ban is probably the wrong tool for the job, itā€™s regexā€™s are optimized to extract IP addresses from log files, and conditionally add them to iptables.

But similar behavior can be achieved very simply from bash

tail -F /var/log/asterisk/full|while read i;do if [[ $i =~ ā€œUNREACHABLEā€ ]];then echo $i|mail [email protected] ;fi;done &

make your version of ā€œunreachableā€ be a regex that matches exactly what you get when your trunk disappears, add that line to /etc/rc.local , you can easily reboot/restart/reload asterisk automatically if you want, and the emails you are getting are not in anyway spurious, for example

tail -F /var/log/asterisk/full|while read i;do if [[ $i =~ ā€œunreachableā€ ]];then echo $i|mail [email protected] ;amportal -a r ;fi;done &

but no it is not an asterisk bug it is almost certainly a badly constructed network setup

(I hope thatā€™s not considered inappropriate ā€œcodeā€ or this post will probably disappear soon :wink: )

1 Like

Dicko - I think you are spot on. Using fail2banā€™s regex and filters you have to have a host in order for the regex to be used by the system and an unreachable message does not include any host. Only lists sip peer.

would your base code be a perpetual watch or would I need to run it each time I wanted to search for unreachable?

thanks for your help!

Something that doesnā€™t require anything besides restarting Asterisk sounds like an Asterisk bug to meā€¦

Maybe at a certain point something happened network-wise but the network recuperated a long time ago and not Asteriskā€¦

Have a nice day,

Nicolas

When the network repairs itself then the UNREACHABLE! Peer bcomes Reachable , if it doesnā€™t then asterisksā€™ attempts tto find that peer will be exposed by ā€œsip set debug ip . . .ā€ And if the replies are missing then tcpdump the host for a better look.

Yes, itt monitors the file through logrotations even. You might want to create/reuse a less noisy log file, you only need NOTICE.

"make your version of ā€œunreachableā€ be a regex that matches exactly what you get when your trunk disappears, add that line to /etc/rc.local "

Can I just input UNREACHABLE! and look for any unreachable peer? Matching the logfile exactly could be difficult with time and other variables changing for each alert.

You will have trouble with the ! character for esoteric reasons but UNREACHABLE would work.

I tried Dickoā€™s excellent suggestion in a previous post. Any event written to the logfile can be used to trigger an alert. I also successfully tested it using netcat to send http notifications instead of emails.

I will eventually use this to generate messages to trigger video recording when the Call button on a doorphone is pressed. I painfully found out how to use elif statements so that several devices can be monitored simultaneously.

1 Like

if [[ $i =~ ā€œUNREACHABLEā€ && $i =~ā€œ805ā€]]ā€¦

Is an ā€˜andā€™ in bash

if [[ $i =~ ā€œUNREACHABLEā€ || $i =~ā€œReachableā€]]ā€¦

Is an ā€˜orā€™

It seems like weā€™re close but I havenā€™t been sent an email alert yet. Hereā€™s what I have.

Logfile: [2016-07-05 15:08:33] NOTICE[3097] chan_sip.c: Peer ā€˜102ā€™ is now UNREACHABLE! Last qualify: 11

Found in asterisk logfiles full.NimbusDemo

Here is the command I put in rc.local folder

tail -F /var/log/asterisk/full.NimbusDemo|while read i;do if [[ $i =~ ā€œUNREACHABLEā€ ]];then echo $i|mail myemail address ;fi;done

Did I miss something? Assuming the answer is yes!

Well, apart from how you made /var/log/asterisk/full.NimbusDemo then it should work IF all the elements in the bash pipes work , so does (your words, intrepret as necessary)

echo ā€œDoes this workā€|mail myemail address

work? If not you need to fix that.

Edit:-

Did you either reboot or run /etc/rc.local after making the changes because the script needs to be running . . . ? Also you forgot putting the script in the backgound ( the final & ) further /etc/rc.local is NOT a folder it is a file!

Thanks dicko, I will be trying your script!

Actually, thatā€™s incorrect. The syntax is:

if [[ $i =~ "UNREACHABLE" -o $i =~ "805" ]]; then

ā€˜Andā€™ is -a. The use of || and && are for handling the exit code of programs, so you could do this as a one-liner:

[[ $i =~ "UNREACHABLE" -o $i =~ "805" ]] && echo This is a one line script

For more information run ā€˜man testā€™ on your machine.

Well that might depend on the version of bash you are using, for me I use

echo $BASH_VERSION
4.3.30(1)-release

and it works fine.

as does a random FreePBX distro

echo $BASH_VERSION
4.1.2(1)-release

i=805
if [[ $i =~ ā€œUNREACHABLEā€ || $i =~ ā€œ805ā€ ]];then echo OK;fi
OK
if [[ $i =~ ā€œUNREACHABLEā€ && $i =~ ā€œ805ā€ ]];then echo OK;else echo no;fi
no

Iā€™m sure the old (and deprecated) -a and -o probably work also but not within the double brackets and not with the =~ either

For more information read:-

http://mywiki.wooledge.org/BashFAQ/031

on any machine :slight_smile:

Much thanks for your help. So far I havenā€™t gotten an email when a phone goes unreachable for my test. Here is what I have in my etc/rc.d/rc.local

the logfile I know has the unreachable notices is the full.NimbusDemo log, any ideas why Iā€™m not getting alerts? Is there a way to test this with a command? thank you for any insight you might have

#!/bin/sh

This script will be executed after all the other init scripts.

You can put your own initialization stuff in here if you donā€™t

want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

Make sure asterisk starts on boot

/usr/local/sbin/amportal start

tail -F /var/log/asterisk/full.NimbusDemo|while read i;do if [[ $i =~ ā€œUNREACHABLE!ā€ ]];then echo $i|mail [email protected] ;fi;done

Donā€™t try and match on ! bash might interpret it as a request for history. Just use REACH, test from bash with

cat /var/log/asterisk/full.NimbusDemo|grep -i reach

if you get a hit(s)

cat /var/log/asterisk/full.NimbusDemo|while read i;do if [[ $i =~ REACH || $i =~ Reach ]];then echo $i ;fi;done

then add the pipe through mail if your email system is working properly.