elnappo/ansible-role-secure-openssh-server

Might run SSH on several ports

Pamplemousse opened this issue · 3 comments

Actually, if we change the ssh_port variable, it ends up adding a line containing port <ssh_port value> to the sshd_config file. Thus, the daemon is listening on several ports, and the related ufw rules are added.

IMHO, the expected behaviour would be to have the daemon listening on a single port. It is actually a bit misleading: reading the config, we can expect ssh to be accessible on a single port, which might not be the case based on the "history" of the changes...

Thank you! Your'e right. Unfortunately this is hard to fix correctly. If we use a regexp for this only the last occurrence of "^Port\ " will be overwritten with the specified port, leaving other port definitions untouched. I can't estimate how often people are using multiple ports.

My best idea at the moment is:

lineinfile: dest=/etc/ssh/sshd_config regexp="^Port\ " state=absent
lineinfile: dest=/etc/ssh/sshd_config line="Port 22" state=present

or for multiple ports

lineinfile: dest=/etc/ssh/sshd_config regexp="^Port\ " state=absent
lineinfile: dest=/etc/ssh/sshd_config line="{{ item }}" state=present
  with_items:¬
    - "Port 22"¬
    - "Port 42"

Both of these solutions are not idempotence.

Under the assumption that only one port is set in sshd_config (for a new server) and we don't want multiple ports the simplest solution would be:

lineinfile: dest=/etc/ssh/sshd_config regexp="^Port\ " line="Port 22" state=present

This should allow setting more ports via a separate task with insertbefore="^Port 22"?

Another options would be to remove the possibility to set the SSH port as it is not completely in the scope of a secure OpenSSH server. In this case its hard to open SSH port(s) via ufw.

I think this fits perfectly in the scope of a secure OpenSSH server. It helps avoiding bots trying to bruteforce your ssh endpoint, mislead quick scans based on default ports list, etc.

Case 1: users have only one port open

This is heavily opinionated, but can be implemented waiting to see of multiple ports is a requested feature. I agree with your quickest and simplest solution:

lineinfile: dest=/etc/ssh/sshd_config regexp="^Port\ " line="Port 22" state=present

But need to think about updating the ufw rules though, as it needs to not respond on the old port and accept connections on the new one.

Case 2: allow to configure multiple ports
lineinfile: dest=/etc/ssh/sshd_config regexp="^Port\ " state=absent
lineinfile: dest=/etc/ssh/sshd_config line="{{ item }}" state=present
  with_items: "{{ ssh_ports }}" # ssh_ports being defined in the user's task calling the role

I do not understand how this is breaking idempotence: as is, users defined a list of ports, and the role is responsible of implementing them the right way.
However, this solution needs as well to update ufw rules.

I do not understand how this is breaking idempotence: as is, users defined a list of ports, and the role is responsible of implementing them the right way.

Lets assume ports are already set correctly. In the first step you delete all occurrences of "^Port\ ", this is a change. After that these ports are added again to the sshd config which is also a change.

I will fix this issue with

lineinfile: dest=/etc/ssh/sshd_config regexp="^Port\ " line="Port 22" state=present

the problem with ufws remains. But I think this is a common problem of ansible and other configuration management tools in contrast to e.g. NixOS.