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.

Architecture with one server

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:

  1. 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.
  2. 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.

Architecture with Bastion SSH server

Why not Fail2ban ?

Well, for two main reasons I decided to use reaction instead of fail2ban:

  1. Fail2ban is an old software with few new features
  2. 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.

Reaction the new Fail2ban

Feedback

I am using this tool within this new architecture for weeks now and I am very satisfied.

Usage

The service is up for 2 weeks and 2 days and memory usage is very low.

Reaction systemctl status

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 8-)

- 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.

1)
Internet Service Provider
2)
yes I use this server for backup
3)
I challenged them to know what happened and they decided to switch the subnet I was part of to a smaller/cheaper one