Table of Contents
Reaction the new fail2ban
Context
When you have a server reachable from internet, it is a very good idea to control who has access to it and how. For years I am using the very good tool called iptables in a very restricted way. But it happened to me a story that I am going to share with you that made change my mind…
Architecture
Here is how I designed the secure SSH access to my server from the two places I have a physical access.
So I configured iptables on my server the most restrictive way I know from network perspective: only the two public IPs of my two ḧomes can access to SSH service. And it works fine. But by design, there is an issue about this choice I made. Indeed, my ISPs 1) provide me dynamic IPs. It may change without notice but for the last 3 years it did not. I accepted the risk because of two facts:
- Since IPs don't change very often and I have two different ISP, the probability that both of them change at the same time is very low. So if one IP changes and I lose access to my server I can go the second home and update the configuration accordingly.
- Worst case scenario, I can use the emergency console access from my server provider and update the configuration of iptables.
Odds always win
One day, one of my ISP put down my internet access for a few days. They had to fix something to improve bandwidth. No problem, I still have access to my server using my second ISP. But the following morning, bad news: all my backup reports came back to me with errors 2). Long story short, my second ISP decided to change my IP during the night 3). I decided that I was going to use my last option: emergency console access to my server from the provider. But bad surprise again, my provider did not provide such a service.
As a result, I lost access to my server for days. In the meantime, I was looking for a more robust design. That's how fail2ban came back to my mind and even better I remembered that one person from the CHATONS Picasoft was working on the perfect tool for me: reaction.
New architecture
In this new architecture, I introduced a new server “Bastion SSH Server” which has only SSH server and reaction.
Why not Fail2ban ?
Well, for two main reasons I decided to use reaction instead of fail2ban:
- Fail2ban is an old software with few new features
- Reaction uses recent technologies and is very efficient. And cherry on the cake, it has an ultimate goal of federating black-listed-IPs.
And since a good drawing is always better than long speech, let me share with you this one made by Gee.
Feedback
I am using this tool within this new architecture for weeks now and I am very satisfied.
Usage
Ansible playbook
Here is my playbook I use to setup it on my server. It is not perfect but if it can help you to test easily
- name: install packages required to have logs package: name: "{{ item }}" state: latest with_items: - iptables - iptables-persistent - logrotate - rsyslog become: True - name: stop reaction if running service: name: reaction.service state: stopped become: True ignore_errors: yes - name: download binary ansible.builtin.get_url: url: https://static.ppom.me/reaction/releases/v1.4.1/reaction dest: /usr/local/bin/reaction mode: '0755' become: True - name: copy systemd file copy: src: files/reaction.service dest: /etc/systemd/system/reaction.service owner: root group: root mode: 0700 become: True - name: copy reaction.yml copy: src: files/reaction.yml dest: /etc/reaction.yml owner: root group: root mode: 0755 become: True - name: reload daemon command: "systemctl daemon-reload" become: True - name: enable reaction command: "systemctl enable reaction.service" become: True - name: restart reaction service: name: reaction.service state: restarted become: True
and the config file for SSH based on official documentation
patterns: ip: regex: '(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})' streams: ssh: cmd: ['tail', '-F', '/var/log/auth.log'] filters: fail: regex: - 'authentication failure;.*rhost=<ip>' - 'Connection (reset|closed) by (authenticating|invalid) user .* <ip>' - 'Failed password for .* from <ip>' retry: 3 retryperiod: '3h' actions: ban: cmd: ['iptables', '-w', '-A', 'reaction', '-s', '<ip>', '-j', 'DROP'] unban: cmd: ['iptables', '-w', '-D', 'reaction', '-s', '<ip>', '-j', 'DROP'] after: '24h' start: - [ 'iptables', '-w', '-N', 'reaction' ] - [ 'iptables', '-w', '-I', 'INPUT', '-p', 'all', '-j', 'reaction' ] stop: - [ 'iptables', '-w', '-D', 'INPUT', '-p', 'all', '-j', 'reaction' ] - [ 'iptables', '-w', '-F', 'reaction' ] - [ 'iptables', '-w', '-X', 'reaction' ]
and the service
[Install] WantedBy=multi-user.target [Service] ExecStart=/usr/local/bin/reaction start -c /etc/reaction.yml StateDirectory=reaction RuntimeDirectory=reaction WorkingDirectory=/var/lib/reaction
This code is based on the one you can find on the official blog of reaction.
Conclusion
This tool is a very good initiative that everybody should support! At least everybody that needs such tool should give a try. The creator is very talented and tries to push the tool into a direction that can make everything more safe.