Chapter 26. Configuring the OpenSSH server and client by using RHEL system roles
Chapter 26. Configuring the OpenSSH server and client by using RHEL system roles You can use the sshd RHEL system role to configure OpenSSH servers and the ssh RHEL system role to configure OpenSSH clients consistently, in an automated fashion, and on any number of RHEL systems at the same time. Such configurations are necessary for any system where secure remote interaction is needed, for example: Remote system administration: securely connecting to your machine from another computer using an SSH client. Secure file transfers: the Secure File Transfer Protocol (SFTP) provided by OpenSSH enable you to securely transfer files between your local machine and a remote system. Automated DevOps pipelines: automating software deployments that require secure connection to remote servers (CI/CD pipelines). Tunneling and port forwarding: forwarding a local port to access a web service on a remote server behind a firewall. For example a remote database or a development server. Key-based authentication: more secure alternative to password-based logins. Certificate-based authentication: centralized trust management and better scalability. Enhanced security: disabling root logins, restricting user access, enforcing strong encryption and other such forms of hardening ensures stronger system security. 26.1. How the sshd RHEL system role maps settings from a playbook to the configuration file In the sshd RHEL system role playbook, you can define the parameters for the server SSH configuration file. If you do not specify these settings, the role produces the sshd_config file that matches the RHEL defaults. In all cases, booleans correctly render as yes and no in the final configuration on your managed nodes. You can use lists to define multi-line configuration items. For example: renders as: Additional resources /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file /usr/share/doc/rhel-system-roles/sshd/ directory 26.2. Configuring OpenSSH servers by using the sshd RHEL system role You can use the sshd RHEL system role to configure multiple OpenSSH servers. These ensure secure communication environment for remote users by providing namely: Management of incoming SSH connections from remote clients Credentials verification Secure data transfer and command execution Note You can use the sshd RHEL system role alongside with other RHEL system roles that change SSHD configuration, for example the Identity Management RHEL system roles. To prevent the configuration from being overwritten, ensure the sshd RHEL system role uses namespaces (RHEL 8 and earlier versions) or a drop-in directory (RHEL 9). Prerequisites You have prepared the control node and the managed nodes . You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: SSH server configuration hosts: managed-node-01.example.com tasks: - name: Configure sshd to prevent root and password login except from particular subnet ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd: PermitRootLogin: no PasswordAuthentication: no Match: - Condition: "Address 192.0.2.0/24" PermitRootLogin: yes PasswordAuthentication: yes The settings specified in the example playbook include the following: PasswordAuthentication: yes|no Controls whether the OpenSSH server ( sshd ) accepts authentication from clients that use the username and password combination. Match: The match block allows the root user login using password only from the subnet 192.0.2.0/24 . For details about the role variables and the OpenSSH configuration options used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file and the sshd_config(5) manual page on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification Log in to the SSH server: Verify the contents of the sshd_config file on the SSH server: Check that you can connect to the server as root from the 192.0.2.0/24 subnet: Determine your IP address: If the IP address is within the 192.0.2.1 - 192.0.2.254 range, you can connect to the server. Connect to the server as root : Additional resources /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file /usr/share/doc/rhel-system-roles/sshd/ directory 26.3. Using the sshd RHEL system role for non-exclusive configuration By default, applying the sshd RHEL system role overwrites the entire configuration. This may be problematic if you have previously adjusted the configuration, for example, with a different RHEL system role or a playbook. To apply the sshd RHEL system role for only selected configuration options while keeping other options in place, you can use the non-exclusive configuration. You can apply a non-exclusive configuration: In RHEL 8 and earlier by using a configuration snippet. In RHEL 9 and later by using files in a drop-in directory. The default configuration file is already placed in the drop-in directory as /etc/ssh/sshd_config.d/00-ansible_system_role.conf . Prerequisites You have prepared the control node and the managed nodes . You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: For managed nodes that run RHEL 8 or earlier: --- - name: Non-exclusive sshd configuration hosts: managed-node-01.example.com tasks: - name: Configure SSHD to accept environment variables ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_config_namespace: <my-application> sshd: # Environment variables to accept AcceptEnv: LANG LS_COLORS EDITOR For managed nodes that run RHEL 9 or later: - name: Non-exclusive sshd configuration hosts: managed-node-01.example.com tasks: - name: Configure sshd to accept environment variables ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_config_file: /etc/ssh/sshd_config.d/ <42-my-application> .conf sshd: # Environment variables to accept AcceptEnv: LANG LS_COLORS EDITOR The settings specified in the example playbooks include the following: sshd_config_namespace: <my-application> The role places the configuration that you specify in the playbook to configuration snippets in the existing configuration file under the given namespace. You need to select a different namespace when running the role from different context. sshd_config_file: /etc/ssh/sshd_config.d/ <42-my-application> .conf In the sshd_config_file variable, define the .conf file into which the sshd system role writes the configuration options. Use a two-digit prefix, for example 42- to specify the order in which the configuration files will be applied. AcceptEnv: Controls which environment variables the OpenSSH server ( sshd ) will accept from a client: LANG : defines the language and locale settings. LS_COLORS : defines the displaying color scheme for the ls command in the terminal. EDITOR : specifies the default text editor for the command-line programs that need to open an editor. For details about the role variables and the OpenSSH configuration options used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file and the sshd_config(5) manual page on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification Verify the configuration on the SSH server: For managed nodes that run RHEL 8 or earlier: For managed nodes that run RHEL 9 or later: Additional resources /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file /usr/share/doc/rhel-system-roles/sshd/ directory sshd_config(5) manual page 26.4. Overriding the system-wide cryptographic policy on an SSH server by using the sshd RHEL system role When the default cryptographic settings do not meet certain security or compatibility needs, you may want to override the system-wide cryptographic policy on the OpenSSH server using the sshd RHEL system role. Especially, in the following notable situations: Compatibility with older clients: necessity to use weaker-than-default encryption algorithms, key exchange protocols, or ciphers. Enforcing stronger security policies: simultaneously, you can disable weaker algorithms. Such a measure could exceed the default system cryptographic policies, especially in the highly secure and regulated environments. Performance considerations: the system defaults could enforce stronger algorithms that can be computationally intensive for some systems. Customizing for specific security needs: adapting for unique requirements that are not covered by the default cryptographic policies. Warning It is not possible to override all aspects of the cryptographic policies from the sshd RHEL system role. For example, SHA1 signatures might be forbidden on a different layer so for a more generic solution, see Setting a custom cryptographic policy by using RHEL system roles . Prerequisites You have prepared the control node and the managed nodes . You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: - name: Deploy SSH configuration for OpenSSH server hosts: managed-node-01.example.com tasks: - name: Overriding the system-wide cryptographic policy ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_sysconfig: true sshd_sysconfig_override_crypto_policy: true sshd_KexAlgorithms: ecdh-sha2-nistp521 sshd_Ciphers: aes256-ctr sshd_MACs: hmac-sha2-512-etm@openssh.com sshd_HostKeyAlgorithms: rsa-sha2-512,rsa-sha2-256 The settings specified in the example playbook include the following: sshd_KexAlgorithms You can choose key exchange algorithms, for example, ecdh-sha2-nistp256 , ecdh-sha2-nistp384 , ecdh-sha2-nistp521 , diffie-hellman-group14-sha1 , or diffie-hellman-group-exchange-sha256 . sshd_Ciphers You can choose ciphers, for example, aes128-ctr , aes192-ctr , or aes256-ctr . sshd_MACs You can choose MACs, for example, hmac-sha2-256 , hmac-sha2-512 , or hmac-sha1 . sshd_HostKeyAlgorithms You can choose a public key algorithm, for example, ecdsa-sha2-nistp256 , ecdsa-sha2-nistp384 , ecdsa-sha2-nistp521 , or ssh-rsa . For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file on the control node. On RHEL 9 managed nodes, the system role writes the configuration into the /etc/ssh/sshd_config.d/00-ansible_system_role.conf file, where cryptographic options are applied automatically. You can change the file by using the sshd_config_file variable. However, to ensure the configuration is effective, use a file name that lexicographically precedes the /etc/ssh/sshd_config.d/50-redhat.conf file, which includes the configured crypto policies. On RHEL 8 managed nodes, you must enable override by setting the sshd_sysconfig_override_crypto_policy and sshd_sysconfig variables to true . Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification You can verify the success of the procedure by using the verbose SSH connection and check the defined variables in the following output: Additional resources /usr/share/ansible/roles/rhel-system-roles.sshd/README.md file /usr/share/doc/rhel-system-roles/sshd/ directory 26.5. How the ssh RHEL system role maps settings from a playbook to the configuration file In the ssh RHEL system role playbook, you can define the parameters for the client SSH configuration file. If you do not specify these settings, the role produces a global ssh_config file that matches the RHEL defaults. In all the cases, booleans correctly render as yes or no in the final configuration on your managed nodes. You can use lists to define multi-line configuration items. For example: renders as: Note The configuration options are case sensitive. Additional resources /usr/share/ansible/roles/rhel-system-roles.ssh/README.md file /usr/share/doc/rhel-system-roles/ssh/ directory 26.6. Configuring OpenSSH clients by using the ssh RHEL system role You can use the ssh RHEL system role to configure multiple OpenSSH clients. These enable the local user to establish a secure connection with the remote OpenSSH server by ensuring namely: Secure connection initiation Credentials provision Negotiation with the OpenSSH server on the encryption method used for the secure communication channel Ability to send files securely to and from the OpenSSH server Note You can use the ssh RHEL system role alongside with other system roles that change SSH configuration, for example the Identity Management RHEL system roles. To prevent the configuration from being overwritten, make sure that the ssh RHEL system role uses a drop-in directory (default in RHEL 8 and later). Prerequisites You have prepared the control node and the managed nodes . You are logged in to the control node as a user who can run playbooks on the managed nodes. The account you use to connect to the managed nodes has sudo permissions on them. Procedure Create a playbook file, for example ~/playbook.yml , with the following content: --- - name: SSH client configuration hosts: managed-node-01.example.com tasks: - name: Configure ssh clients ansible.builtin.include_role: name: rhel-system-roles.ssh vars: ssh_user: root ssh: Compression: true GSSAPIAuthentication: no ControlMaster: auto ControlPath: ~/.ssh/.cm%C Host: - Condition: example Hostname: server.example.com User: user1 ssh_ForwardX11: no The settings specified in the example playbook include the following: ssh_user: root Configures the root user's SSH client preferences on the managed nodes with certain configuration specifics. Compression: true Compression is enabled. ControlMaster: auto ControlMaster multiplexing is set to auto . Host Creates alias example for connecting to the server.example.com host as a user called user1 . ssh_ForwardX11: no X11 forwarding is disabled. For details about the role variables and the OpenSSH configuration options used in the playbook, see the /usr/share/ansible/roles/rhel-system-roles.ssh/README.md file and the ssh_config(5) manual page on the control node. Validate the playbook syntax: Note that this command only validates the syntax and does not protect against a wrong but valid configuration. Run the playbook: Verification Verify that the managed node has the correct configuration by displaying the SSH configuration file: Additional resources /usr/share/ansible/roles/rhel-system-roles.ssh/README.md file /usr/share/doc/rhel-system-roles/ssh/ directory ssh_config(5) manual page
sshd_ListenAddress: - 0.0.0.0 - '::' ListenAddress 0.0.0.0 ListenAddress :: --- - name: SSH server configuration hosts: managed-node-01.example.com tasks: - name: Configure sshd to prevent root and password login except from particular subnet ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd: PermitRootLogin: no PasswordAuthentication: no Match: - Condition: "Address 192.0.2.0/24" PermitRootLogin: yes PasswordAuthentication: yes ansible-playbook --syntax-check ~/playbook.yml ansible-playbook ~/playbook.yml ssh <username> @ <ssh_server> cat /etc/ssh/sshd_config PasswordAuthentication no PermitRootLogin no Match Address 192.0.2.0/24 PasswordAuthentication yes PermitRootLogin yes hostname -I 192.0.2.1 ssh root@ <ssh_server> --- - name: Non-exclusive sshd configuration hosts: managed-node-01.example.com tasks: - name: Configure SSHD to accept environment variables ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_config_namespace: <my-application> sshd: # Environment variables to accept AcceptEnv: LANG LS_COLORS EDITOR - name: Non-exclusive sshd configuration hosts: managed-node-01.example.com tasks: - name: Configure sshd to accept environment variables ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_config_file: /etc/ssh/sshd_config.d/ <42-my-application> .conf sshd: # Environment variables to accept AcceptEnv: LANG LS_COLORS EDITOR ansible-playbook --syntax-check ~/playbook.yml ansible-playbook ~/playbook.yml cat /etc/ssh/sshd_config BEGIN sshd system role managed block: namespace <my-application> Match all AcceptEnv LANG LS_COLORS EDITOR END sshd system role managed block: namespace <my-application> cat /etc/ssh/sshd_config.d/42-my-application.conf Ansible managed # AcceptEnv LANG LS_COLORS EDITOR - name: Deploy SSH configuration for OpenSSH server hosts: managed-node-01.example.com tasks: - name: Overriding the system-wide cryptographic policy ansible.builtin.include_role: name: rhel-system-roles.sshd vars: sshd_sysconfig: true sshd_sysconfig_override_crypto_policy: true sshd_KexAlgorithms: ecdh-sha2-nistp521 sshd_Ciphers: aes256-ctr sshd_MACs: hmac-sha2-512-etm@openssh.com sshd_HostKeyAlgorithms: rsa-sha2-512,rsa-sha2-256 ansible-playbook --syntax-check ~/playbook.yml ansible-playbook ~/playbook.yml ssh -vvv <ssh_server> debug2: peer server KEXINIT proposal debug2: KEX algorithms: ecdh-sha2-nistp521 debug2: host key algorithms: rsa-sha2-512,rsa-sha2-256 debug2: ciphers ctos: aes256-ctr debug2: ciphers stoc: aes256-ctr debug2: MACs ctos: hmac-sha2-512-etm@openssh.com debug2: MACs stoc: hmac-sha2-512-etm@openssh.com LocalForward: - 22 localhost:2222 - 403 localhost:4003 LocalForward 22 localhost:2222 LocalForward 403 localhost:4003 --- - name: SSH client configuration hosts: managed-node-01.example.com tasks: - name: Configure ssh clients ansible.builtin.include_role: name: rhel-system-roles.ssh vars: ssh_user: root ssh: Compression: true GSSAPIAuthentication: no ControlMaster: auto ControlPath: ~/.ssh/.cm%C Host: - Condition: example Hostname: server.example.com User: user1 ssh_ForwardX11: no ansible-playbook --syntax-check ~/playbook.yml ansible-playbook ~/playbook.yml cat ~/root/.ssh/config Ansible managed Compression yes ControlMaster auto ControlPath ~/.ssh/.cm%C ForwardX11 no GSSAPIAuthentication no Host example Hostname example.com User user1