{{ :supportukraine.gif|}} ====== Fail2ban: Set up E-Mail and/or Telegram messenger smtp.py-notifications with Tux ====== {{en:tux.png |Hey, my name is "Tux"!}} **Did you ever wonder how you can set up //Fail2ban// on Linux with E-Mail and/or [[https://telegram.org/|Telegram messenger]] notification?** \\ \\ Hey, my name is "Tux" and this tutorial will show you how to set up //Fail2ban// so it can notify you about banning events by E-Mail and/or your personal and specific //Telegram// messenger channel by using //Fail2ban//'s ''smtp.py'' pre-defined Python script. ---- \\ ===== First thoughts ===== There are already a lot of [[https://www.cyberciti.biz/faq/how-to-protect-ssh-with-fail2ban-on-centos-8/|good tutorials]] on the internet of how to install and configure //Fail2ban// on a Linux system so I won't get into this. This tutorial is all about including the built-in notification tool [[https://github.com/fail2ban/fail2ban/issues/1930|smtp.py]] into your //Fail2ban// configuration file and make it work. This tutorial is based on: * Linux server with //SSH// service enabled * Fail2ban version 0.11.1 package \\ You can check your current installed version by executing the following command:$ fail2ban-server -V $ fail2ban-client -V In addition, for E-Mail and/or //Telegram// notifications, it is assumed you've already set up a working E-Mail client and/or the specific [[https://github.com/KostyaEsmukov/smtp_to_telegram|smtp-to-telegram]] docker application. Optionally, to make //smtp-to-telegram// run on a //Synology NAS// with //Docker// package capability, you can also refer to [[https://medium.com/@nicholaschum/synology-dsm-6-x-telegram-bot-alerts-2f069eb3e9f2|this tutorial]]. \\ ===== Start of tutorial ===== As you are aware of the information boxes above we move to practice now. \\ \\ Let's begin! \\ \\ ==== Step 1: Configuring the jail file for smtp.py-notifications ==== Calling the //Fail2ban//'s included ''smtp.py'' Python script with the according parameters as an action from your //Fail2ban// jail-file is really straight forward. Just for your information: It might be helpful to take a look on the available defined parameters on the ''Parameters''-section inside the ''smtp.py''-script (Note that this is just an outtake, the whole script has a lot more content, of course): Parameters ---------- jail : Jail The jail which the action belongs to. name : str Named assigned to the action. host : str, optional SMTP host, of host:port format. Default host "localhost" and port "25" user : str, optional Username used for authentication with SMTP server. password : str, optional Password used for authentication with SMTP server. sendername : str, optional Name to use for from address in email. Default "Fail2Ban". sender : str, optional Email address to use for from address in email. Default "fail2ban". dest : str, optional Email addresses of intended recipient(s) in comma space ", " delimited format. Default "root". matches : str, optional Type of matches to be included from ban in email. Can be one of "matches", "ipmatches" or "ipjailmatches". Default None (see man jail.conf.5). As you can see on the script outtake above that there are only two parameters required when executing the ''smtp.py''-action, all other parameters are optional (Note that the required parameters ''jail'' and ''name'' are being transferred automatically, you don't have to add them when calling the ''smtp.py''-action. But you can override them if you need to.). But be aware, that those parameters with pre-defined default values actually do(!) send their default value by default when executing the ''smtp.py''-action! For example: For //Telegram// notifications it is just enough to just call the pre-defined ''smtp.py''-action like this, all other parameters are not necessary to be set (Of course for E-Mail notification with user authentication you would have to set more parameters, in this case just do as your //SMTP// server requires!): smtp.py[host=":", sender="", dest="foo@bar.com"] Note that the parameter ''sender'' has to be included with an empty string in case you are configuring //smtp-to-telegram// notifications because if you leave it unset it takes the default value ''fail2ban'' which did not work in my case (I've had to learn it the hard way!). \\ The ''destination'' content on the other hand really does not matter when using the //smtp-to-telegram// service, you can just put in ''foo@bar.com'' like I did, if you like.). Here is an example of a running and fully working ''jail.local''-file: [DEFAULT] ignoreip = 127.0.0.1/8 bantime = 10m findtime = 10m maxretry = 5 banaction = iptables-multiport [sshd] enabled = true backend = systemd filter = sshd action = iptables[name=SSH, port=ssh, protocol=tcp] smtp.py[host="172.16.0.2:2500", sender="", dest="foo@bar.com"] logpath = /var/log/secure bantime = -1 findtime = 300 maxretry = 3 You can see on the ''jail.local''-content above that there are the folowing two actions being called: \\ action = iptables[name=SSH, port=ssh, protocol=tcp] smtp.py[host="172.16.0.2:2500", sender="", dest="foo@bar.com"] Please note: It is important to know that //Fail2ban// jail-files are not very tolerant when it comes into whitespaces and tabulators. In my case, directly after the first action ''iptables[name=SSH, port=ssh, protocol=tcp]'', I had to add a page break followed by a single tabulator. Please do not add any whitespaces and don't copy-paste from this website! Type it all down by your own to make sure it is being formatted correctly! \\ \\ Also note that //Fail2ban// does take the //SSH// port-number defined inside the ''/etc/ssh/sshd_config''-file. So if you have changed the default port number from ''22'' to whatever number, //Fail2ban// will take the correct port number so you don't have to worry about that. Also note that you can repeat the ''smtp.py''-action as many times as you want in case you want to have multiple notification channels (for example //Telegram// **and** E-Mail). Now, after configuring everything similar as showed above please restart the //Fail2ban// service: $ systemctl restart fail2ban The tutorial should be finished here. Just check it by doing some //SSH// failure attempts (according to your jail-file configuration) manually to provoke an //SSH//-ban. You should get notified on your personal //Telegram// or E-Mail channel. If not, you have either misconfigured your //smtp-to-telegram// docker service or -like in my case- you have a Linux system with enabled //SELinux// service set to ''enforced'' so you will not get any notifications yet as //SELinux// will prevent the Python script from being executed by default. In this case, please follow the tutorial below. \\ \\ \\ ==== Step 2: Configuring SELinux for allowing smtp.py-notifications ==== After everything has been set up as described above, let's get to the tricky part now. First, edit the following file: $ vi /etc/selinux/config Now change the following line SELINUX=enforcing to SELINUX=permissive After the next system reboot //SELinux// is will be set to ''permissive'' mode which is required to capture the events preventing the ''smtp.py''-script from being executed. So let's now reboot the system: $ reboot now After reboot //SELinux// is now in ''permissive'' mode. Check this by executing: $ getenforce Which should give you the following output: \\ ''Permissive'' \\ \\ You will note soon that //Telegram// and/or E-Mail notifications should now work as //SELinux// is not in blocking mode anymore for now. But you don't want //SELinux// being disabled permanently as this takes down your system's security! So just keep following the tutorial! Login again with user ''root'' via //SSH//. Now make sure to provoke a few //Fail2ban// //SSH//-bans so the //smtp.py//-script blocking events will be captured by //SELinux// logs. After that (as already mentioned at least you now should have got new //Telegram// and/or E-Mail notifications), check the logs if it got blocked some ''smtp.py''-script dependencies: $ cat /var/log/audit/audit.log | grep fail2ban_t If you see something like... type=AVC msg=audit(1598509657.351:59): avc: denied { search } for pid=1175 comm="f2b/server" name="__pycache__" dev="dm-0" ino=12590952 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=dir permissive=1 type=AVC msg=audit(1598509657.351:59): avc: denied { read } for pid=1175 comm="f2b/server" name="smtp.cpython-36.pyc" dev="dm-0" ino=12590953 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=1 type=AVC msg=audit(1598509657.351:59): avc: denied { open } for pid=1175 comm="f2b/server" path="/etc/fail2ban/action.d/__pycache__/smtp.cpython-36.pyc" dev="dm-0" ino=12590953 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=1 type=AVC msg=audit(1598509657.353:60): avc: denied { getattr } for pid=1175 comm="f2b/server" path="/etc/fail2ban/action.d/__pycache__/smtp.cpython-36.pyc" dev="dm-0" ino=12590953 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=1 type=AVC msg=audit(1598509657.873:61): avc: denied { name_connect } for pid=1175 comm="f2b/a.sshd" dest=2500 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=1 type=AVC msg=audit(1598509705.324:115): avc: denied { name_connect } for pid=1175 comm="f2b/a.sshd" dest=2500 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=1 type=AVC msg=audit(1598509705.998:120): avc: denied { search } for pid=1652 comm="f2b/server" name="__pycache__" dev="dm-0" ino=12590952 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=dir permissive=1 type=AVC msg=audit(1598509705.998:120): avc: denied { read } for pid=1652 comm="f2b/server" name="smtp.cpython-36.pyc" dev="dm-0" ino=12590953 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=1 type=AVC msg=audit(1598509705.998:120): avc: denied { open } for pid=1652 comm="f2b/server" path="/etc/fail2ban/action.d/__pycache__/smtp.cpython-36.pyc" dev="dm-0" ino=12590953 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=1 type=AVC msg=audit(1598509705.998:121): avc: denied { getattr } for pid=1652 comm="f2b/server" path="/etc/fail2ban/action.d/__pycache__/smtp.cpython-36.pyc" dev="dm-0" ino=12590953 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=1 type=AVC msg=audit(1598509706.147:122): avc: denied { name_connect } for pid=1652 comm="f2b/a.sshd" dest=2500 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=1 ...it is clear that //SELinux// is preventing the ''smtp.py''-script from being executed successfully. If so, let's create our own //SELinux// policy package. First, let's create the following directory: $ mkdir /root/selinux Navigate into it: $ cd /root/selinux Now let's create our own //SELinux// policy package inside the current directory: $ grep "fail2ban_t" /var/log/audit/audit.log | audit2allow -M fail2ban-smtp-py Now let's load/activate the custom //SELinux// module: $ semodule -i /root/selinux/fail2ban-smtp-py.pp Finally turn //SELinux// back to ''enforcing'' mode: $ vi /etc/selinux/config Chage the following line SELINUX=permissive to SELINUX=enforcing Now reboot the system: $ reboot now After reboot //SELinux// is now set back to ''enforcing'' mode. Check this by executing: $ getenforce Which should give you the following output: \\ ''Enforcing'' \\ \\ //Telegram// and/or E-Mail notification should work now. Note that you can always unload/disable the custom //SELinux// module by executing: $ semodule -r fail2ban-smtp-py \\ ===== End of tutorial ===== \\ \\ Appreciate my work? \\ [[https://www.buymeacoffee.com/fabioU|Buy me a coffee]] {{:buymeacoffee.png|}} or [[https://www.paypal.com/donate/?hosted_button_id=TH8Q3NTJCAJBA|PayPal]] {{:paypal.png|}} \\ \\ **Source(s):** \\ [[https://github.com/fail2ban/fail2ban/issues/1930|Github: Fail2ban: Issues: Does fail2ban support send email use third-party SMTP server, like Gmail and so on, not use sendmail]] \\ [[https://www.reddit.com/r/CentOS/comments/igc49p/fail2ban_smtppy_action_not_working/g2wqd91/|Reddit: fail2ban: "smtp.py" action not working]] {{htmlmetatags>metatag-robots=()}}