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…
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:
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.
In this new architecture, I introduced a new server “Bastion SSH Server” which has only SSH server and reaction.
Well, for two main reasons I decided to use reaction instead of fail2ban:
And since a good drawing is always better than long speech, let me share with you this one made by Gee.
I am using this tool within this new architecture for weeks now and I am very satisfied.
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.
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.