Compare commits

...

24 commits

Author SHA1 Message Date
Sven Velt 29c024f374 meta: add Alpine as supported platform 2024-11-19 22:03:19 +01:00
Sven Velt 6f39d8db09 Fix version number when ssh client is not available
Old sshd do not know about "-V" but output help output - with SSH
version number (without pX). Works because stderr is redirected to stdin
and output of version string looks familiar to grep expressions :)

% sshd -V
unknown option -- V
OpenSSH_8.7p1, OpenSSL 3.0.7 1 Nov 2022
2024-11-11 12:26:12 +01:00
Sven Velt 4ac6ff2cc8 WIP: support for FreeBSD and NetBSD 2024-07-10 11:22:11 +02:00
Sven Velt a03b1528c7 Ensure ed25519 key ist present 2024-07-10 11:21:47 +02:00
Sven Velt 18ed1ea57e Update README 2024-07-10 11:21:35 +02:00
Sven Velt 7285f77a9c Add vars for SSH 6.7 2024-07-10 11:17:39 +02:00
Sven Velt 37e7623539 Fix Include statement detection (starting with Alpine 3.19) 2024-07-10 11:15:11 +02:00
Sven Velt b588509306 Added OpenBSD support 2023-11-15 21:07:32 +01:00
Sven Velt d96c48af1c README: Update version numbers 2023-11-15 21:01:52 +01:00
Sven Velt a5189e5e98 README: Fixes 2023-11-15 21:01:41 +01:00
Sven Velt bd453a37eb README: Update 2023-10-13 18:45:12 +02:00
Sven Velt bd1c6d5e6d Merge pull request 'Big update to support RHEL9 & clones' (#17) from devel into main
Reviewed-on: #17
2023-03-28 07:31:01 +00:00
Sven Velt 70ab8d6e28 Big update to support RHEL9 & clones
Now crypto-policies include SSH options (not command line arguments)
2023-03-20 20:32:35 +01:00
Sven Velt 9751d3f8e9 Use sntrup761x25519-sha512@openssh.com beginning with 8.5 2022-09-30 20:39:36 +02:00
Sven Velt 8c96e48deb README updated 2022-05-12 15:10:32 +02:00
Sven Velt 7b0fd3e6c6 Make 8.2 config default and remove symlinks for 8.2+
fixes: #13
2022-03-21 13:17:44 +01:00
Sven Velt dd1073d16b Use "ssh" on all debian systems
With non-systemd "sshd" service name is not available

fixes: #12
2022-03-21 13:16:53 +01:00
Sven Velt 7813933ad6 Disable RSA for old SSH versions
closes #10
2021-10-19 10:24:47 +02:00
Sven Velt ed24147b3a Regenerate too small RSA keys
closes #1
2021-10-19 10:23:13 +02:00
Sven Velt 1d08be491a Fixed RedHat crypto policy file 2021-10-19 10:22:00 +02:00
Sven Velt 431bf0c9b7 Fix distribution/OS variables 2021-10-19 10:11:02 +02:00
Sven Velt f12ec3e9e0 Add 'stribika' configuration (for reference)
see https://stribika.github.io/2015/01/04/secure-secure-shell.html
2021-10-19 09:40:45 +02:00
Sven Velt 9ff0979db4 Add 'ed25519-only' configuration 2021-10-19 09:39:54 +02:00
Sven Velt 63895750ca Force config with var "ssh_hardening_force" 2021-10-19 09:38:38 +02:00
27 changed files with 239 additions and 65 deletions

View file

@ -1,17 +1,36 @@
ssh-hardening ssh-hardening
========= =========
SSH hardening, based on https://www.sshaudit.com & more SSH server hardening, based on https://www.sshaudit.com & more
Requirements Requirements
------------ ------------
- tbd - OpenSSH versions 6.5+
Role Variables Role Variables
-------------- --------------
- tbd Defaults:
- `ssh_hardening_hostkeys`: `rsa`, `ed25519`
- `ssh_hardening_hostkeys_all`: `dsa`, `ecdsa`, `rsa`, `ed25519`
- `ssh_hardening_moduli`: `/etc/ssh/moduli`
- `ssh_hardening_moduli_backup`: `/etc/ssh/moduli.not-hardened`
- `ssh_hardening_root_group`: `root`
- `ssh_hardening_service_name`: `sshd`
- `ssh_hardening_sshd_config`: `/etc/ssh/sshd_config`
Included via `vars/ssh_*`:
- `ssh_hardening_opts`: Parameter/Values to set for specific SSH version
Included via `vars/os_*`:
- `ssh_hardening_moduli`
- `ssh_hardening_moduli_backup`
- `ssh_hardening_service_name`
- `ssh_hardening_root_group`
Command line variables (undefined):
- `ssh_hardening_force`: version/id to include, overwrites detected version!
Dependencies Dependencies
------------ ------------
@ -28,26 +47,36 @@ Example Playbook
SSH versions SSH versions
------------ ------------
- 6.0: [_] Debian 7 "wheezy" - 6.0: [_] Debian 7 "wheezy"
- 6.5: - (support for `curve25519-sha256@libssh.org`, `ssh-ed25519`, `chacha20-poly1305@openssh.com`) - 6.5: (support for `curve25519-sha256@libssh.org`, `ssh-ed25519`, `chacha20-poly1305@openssh.com`)
- 6.6: Ubuntu 14.04 "trusty" - 6.6: Ubuntu 14.04 "trusty"
- 6.7: [_] Debian 8 "jessie" - 6.7: Debian 8 "jessie"
- 7.0: - 7.0:
- 7.1: - 7.1:
- 7.2: Ubuntu 16.04 "xenial" - 7.2: Ubuntu 16.04 "xenial"
- 7.4: Debian 9 "stretch", RedHat 7 - (added `curve25519-sha256`) - 7.4: Debian 9 "stretch", RedHat 7 - (added `curve25519-sha256`)
- 7.6: Ubuntu 18.04 "bionic" - 7.6: Ubuntu 18.04 "bionic"
- 7.7: - 7.7:
- 7.8: - 7.8:
- 7.9: Debian 10 "buster" - 7.9: Debian 10 "buster"
- 8.0: RedHat 8 - 8.0: RedHat 8
- 8.1: Suse 15.2 - 8.1: Suse 15.2
- 8.2: Ubuntu 20.04 "focal" - 8.2: Ubuntu 20.04 "focal"
- 8.3: - 8.3:
- 8.4: Debian 11 "bullseye", Fedora 33, Suse 15.3 - 8.4: ✅ Alpine 3.13, ✅ Debian 11 "bullseye", ✅ Fedora 33, ✅ OpenSUSE 15.3/15.4
- 8.5: - 8.5: (added `sntrup761x25519-sha512@openssh.com`)
- 8.6: Fedora 34 - 8.6: ✅ Alpine 3.14, ✅ Fedora 34
- 8.7: Fedora 35 - 8.7: ✅ Fedora 35
- 8.8: Archlinux, Voidlinux - 8.8: ✅ Alpine 3.15, ✅ Fedora 36, ✅ Fedora 37
- 8.9: ✅ Ubuntu 22.04 "jammy"
- 9.0: ✅ Alpine 3.16, ✅ Fedora 38, ✅ Ubuntu 22.10 "kinetic", ✅ Ubuntu 23.04 "lunar"
- 9.1: ✅ Alpine 3.17
- 9.2: ✅ Debian 12 "bookworm"
- 9.3: ✅ Alpine 3.18, ✅ Fedora 39, ✅ Ubuntu 23.10 "mantic"
- 9.4:
- 9.5:
- 9.6: ✅ Alpine 3.19, Fedora 40, Ubuntu 24.04 "noble"
- 9.7: ✅ Alpine 3.20
- 9.8: Archlinux, ✅ Voidlinux
License License
------- -------

View file

@ -12,5 +12,9 @@ ssh_hardening_hostkeys_all:
ssh_hardening_moduli: /etc/ssh/moduli ssh_hardening_moduli: /etc/ssh/moduli
ssh_hardening_moduli_backup: /etc/ssh/moduli.not-hardened ssh_hardening_moduli_backup: /etc/ssh/moduli.not-hardened
ssh_hardening_root_group: root
ssh_hardening_service_name: sshd
ssh_hardening_sshd_config: /etc/ssh/sshd_config ssh_hardening_sshd_config: /etc/ssh/sshd_config

View file

@ -1,7 +1,7 @@
--- ---
- name: Restart SSH - name: Restart SSH
service: service:
name: "{{ ssh_hardening_service_name|default('sshd') }}" name: "{{ ssh_hardening_service_name }}"
state: restarted state: restarted

View file

@ -1,3 +1,4 @@
---
galaxy_info: galaxy_info:
author: Sven Velt author: Sven Velt
description: SSH hardening description: SSH hardening
@ -6,6 +7,7 @@ galaxy_info:
license: AGPL-3.0-or-later license: AGPL-3.0-or-later
min_ansible_version: 2.1 min_ansible_version: 2.1
platforms: platforms:
- name: Alpine
- name: Debian - name: Debian
versions: versions:
- stretch - stretch

View file

@ -2,25 +2,34 @@
- name: Set some variables - name: Set some variables
set_fact: set_fact:
ssh_hardening_backup_suffix: "42.{{ ansible_date_time.date }}@{{ ansible_date_time.time }}~" ssh_hardening_backup_suffix: "42.{{ ansible_date_time.date }}@{{ ansible_date_time.time }}~"
ssh_hardening_distri: "{{ (ansible_distribution|lower).split(' ')[0] }}" ssh_hardening_distri: "{{ (ansible_distribution|lower).split(' ')[0] }}-{{ ansible_distribution_major_version|default(ansible_distribution_version) }}"
- name: Get SSH version number - name: Get SSH version number
shell: 'ssh -V 2>&1 | grep -o "OpenSSH_[0-9]\+\.[0-9]" | grep -o "[0-9]\+\.[0-9]"' shell: 'sshd -V 2>&1 | grep -Eo "OpenSSH_[0-9]+\.[0-9]+" | grep -Eo "[0-9]+\.[0-9]+"'
changed_when: False changed_when: False
register: ssh_hardening_version register: ssh_hardening_version
- name: Read forced config file
include_vars: "ssh_{{ ssh_hardening_force }}.yml"
when: ssh_hardening_force is defined
- name: Read SSH version config file - name: Read SSH version config file
include_vars: "ssh_{{ ssh_hardening_version.stdout_lines.0 }}.yml" include_vars: "{{ item }}"
with_first_found:
- "ssh_{{ ssh_hardening_version.stdout_lines.0 }}.yml"
- "ssh_default.yml"
when: ssh_hardening_force is not defined
- name: Read distribution specific variables - name: Read distribution specific variables
include_vars: "{{ item }}" include_vars: "{{ item }}"
with_first_found: with_first_found:
- "os_{{ ssh_hardening_distri }}.yml" - "os_{{ ssh_hardening_distri }}.yml"
- "os_{{ ansible_distribution_family }}.yml" - "os_{{ (ansible_distribution|lower).split(' ')[0] }}.yml"
- "os_{{ ansible_os_family }}.yml" - "os_{{ (ansible_os_family|lower).split(' ')[0] }}.yml"
- "os_default.yml" - "os_default.yml"
@ -30,19 +39,17 @@
dest: "{{ ssh_hardening_sshd_config }}.{{ ssh_hardening_backup_suffix }}" dest: "{{ ssh_hardening_sshd_config }}.{{ ssh_hardening_backup_suffix }}"
remote_src: yes remote_src: yes
owner: root owner: root
group: root group: "{{ ssh_hardening_root_group }}"
mode: 0600 mode: 0600
#################### ####################
- name: "Hostkeys: Disable (EC)DSA" - name: "Hostkeys: Disable (EC)DSA (and maybe RSA)"
lineinfile: lineinfile:
dest: "{{ ssh_hardening_sshd_config }}" dest: "{{ ssh_hardening_sshd_config }}"
regexp: '(?i)\s*#*\s*hostkey.*{{ item }}_key' regexp: '(?i)\s*#*\s*hostkey.*{{ item }}_key'
state: absent state: absent
loop: loop: "{{ ssh_hardening_hostkeys_all|difference(ssh_hardening_hostkeys) }}"
- dsa
- ecdsa
notify: Restart SSH notify: Restart SSH
@ -54,6 +61,21 @@
loop: '{{ ssh_hardening_hostkeys }}' loop: '{{ ssh_hardening_hostkeys }}'
notify: Restart SSH notify: Restart SSH
- name: "Ensure ED25519 hostkey is available"
openssh_keypair:
path: /etc/ssh/ssh_host_ed25519_key
type: ed25519
when: '"ed25519" in ssh_hardening_hostkeys'
- name: "Renew RSA hostkeys if too short"
openssh_keypair:
path: /etc/ssh/ssh_host_rsa_key
type: rsa
size: 4096
when: '"rsa" in ssh_hardening_hostkeys'
#################### ####################
- name: "INCLUDE: Remove small Diffie-Hellman moduli" - name: "INCLUDE: Remove small Diffie-Hellman moduli"
@ -61,18 +83,62 @@
#################### ####################
- name: "Check for crypto-policies" - name: "Check for SSH include directory"
stat:
path: /etc/ssh/sshd_config.d
register: ssh_hardening_sshd_include_dir
#- name: "SSH include directory exists"
# find:
# path: /etc/ssh/sshd_config.d
# pattern: "*.conf"
# register: ssh_hardening_sshd_include_files
- name: "Check for crypto-policy file"
stat: stat:
path: /etc/crypto-policies/back-ends/opensshserver.config path: /etc/crypto-policies/back-ends/opensshserver.config
register: ssh_hardening_use_policies register: ssh_hardening_policy_file
- name: "The (RedHat) crypto policy way..." - name: "BLOCK: what to do with crypto policy file"
when: ssh_hardening_policy_file.stat.exists
block:
- name: "Get systemd service file location"
service:
name: "{{ ssh_hardening_service_name }}"
register: ssh_hardening_systemd_file
- name: "Check for USED crypto-policies variable"
command: "awk '/CRYPTO_POLICY/{print}' {{ ssh_hardening_systemd_file.status.FragmentPath }}"
changed_when: False
register: ssh_hardening_policy_var
# stdout == "" → SSH-Cfg in CP
# stdout != "" → Variablen in CP
# Nicht bei SUSE Tumbleweed!
- name: "(policy file) Move original link"
command: mv /etc/crypto-policies/back-ends/opensshserver.config /etc/crypto-policies/back-ends/opensshserver.config.not-hardened
args:
creates: /etc/crypto-policies/back-ends/opensshserver.config.not-hardened
when: ssh_hardening_policy_file.stat.islnk
- name: "The (RedHat-8) crypto policy variable way..."
include_tasks: restrictions_crypto_policy.yml include_tasks: restrictions_crypto_policy.yml
when: ssh_hardening_use_policies.stat.exists when: ssh_hardening_policy_var.stdout is defined and ssh_hardening_policy_var.stdout|length > 0
- name: "The (RedHat-X) crypto policy include way..."
include_tasks: restrictions_crypto_policy_include.yml
when: ssh_hardening_policy_var.stdout is defined and ssh_hardening_policy_var.stdout|length == 0 and ssh_hardening_policy_file.stat.exists
- name: "The standard config way..." - name: "The standard config way..."
include_tasks: restrictions_configfile.yml include_tasks: restrictions_configfile.yml
when: not ssh_hardening_use_policies.stat.exists when: not ssh_hardening_policy_file.stat.exists

View file

@ -11,13 +11,13 @@
- name: 'Moduli: Check for small Diffie-Hellman moduli' - name: 'Moduli: Check for small Diffie-Hellman moduli'
shell: "grep -c ' 1535 \\| 2047 ' /etc/ssh/moduli || true" shell: "grep -Ec ' 1535 | 2047 ' {{ ssh_hardening_moduli }} || true"
changed_when: False changed_when: False
register: ssh_hardening_moduli_small register: ssh_hardening_moduli_small
- name: 'Moduli: Remove small Diffie-Hellman moduli' - name: 'Moduli: Remove small Diffie-Hellman moduli'
shell: "TMPF=$(mktemp) && awk '$5 >= 3071' /etc/ssh/moduli >${TMPF} && mv ${TMPF} /etc/ssh/moduli" shell: "TMPF=$(mktemp) && awk '$5 >= 3071' {{ ssh_hardening_moduli }} >${TMPF} && mv ${TMPF} {{ ssh_hardening_moduli }}"
when: ssh_hardening_moduli_small.stdout|int > 0 when: ssh_hardening_moduli_small.stdout|int > 0

View file

@ -1,6 +1,6 @@
--- ---
- name: Check for Include directory - name: Check for Include directory
shell: "awk '/Include/ { print $2; }' /etc/ssh/sshd_config" shell: "awk '/^[^#]*Include/ { print $2; }' /etc/ssh/sshd_config"
changed_when: False changed_when: False
register: ssh_hardening_includedir register: ssh_hardening_includedir

View file

@ -1,22 +1,12 @@
--- ---
- name: Move original link
command: mv /etc/crypto-policies/back-ends/opensshserver.config /etc/crypto-policies/back-ends/opensshserver.config.not-hardened
args:
creates: /etc/crypto-policies/back-ends/opensshserver.config.not-hardened
when: ssh_hardening_use_policies.stat.islnk
- name: Write new crypto policies - name: Write new crypto policies
template: template:
src: '{{ item }}' src: 'crypto-policies/opensshserver.config.j2'
dest: /etc/crypto-policies/back-ends/opensshserver.config dest: /etc/crypto-policies/back-ends/opensshserver.config
owner: root owner: root
group: root group: root
mode: 0644 mode: 0644
backup: yes backup: yes
with_first_found:
- 'crypto-policies/opensshserver_{{ ansible_distribution|lower }}.config.j2'
- 'crypto-policies/opensshserver_{{ ansible_os_family|lower }}.config.j2'
notify: Restart SSH notify: Restart SSH

View file

@ -0,0 +1,12 @@
---
- name: Write restrictions to crypto-policy file
template:
src: 'sshd_config_hardening.j2'
dest: '/etc/crypto-policies/back-ends/opensshserver.config'
owner: root
group: root
mode: 0600
backup: yes
notify: Restart SSH

View file

@ -0,0 +1,2 @@
CRYPTO_POLICY='{% for key in ssh_hardening_opts %}-o{{ key }}={{ ssh_hardening_opts[key]|join(",") }} {% endfor %}'

View file

@ -1 +0,0 @@
../sshd_config_hardening.j2

View file

@ -1,2 +0,0 @@
CRYPTO_POLICY='-o{% for key in ssh_hardening_opts %}{{ key }}={{ ssh_hardening_opts[key]|join(",") }} {% endfor %}'

3
vars/os_freebsd.yml Normal file
View file

@ -0,0 +1,3 @@
---
ssh_hardening_root_group: wheel

6
vars/os_netbsd.yml Normal file
View file

@ -0,0 +1,6 @@
---
ssh_hardening_root_group: wheel
ssh_hardening_moduli: /etc/moduli
ssh_hardening_moduli_backup: /etc/moduli.not-hardened

6
vars/os_openbsd.yml Normal file
View file

@ -0,0 +1,6 @@
---
ssh_hardening_root_group: wheel
ssh_hardening_moduli: /etc/moduli
ssh_hardening_moduli_backup: /etc/moduli.not-hardened

View file

@ -1,4 +0,0 @@
---
ssh_hardening_hostkeys:
- ed25519

View file

@ -1,6 +1,9 @@
# 6.6: Ubuntu 14 # 6.6: Ubuntu 14
# 7.2: Ubuntu 16 # 7.2: Ubuntu 16
ssh_hardening_hostkeys:
- ed25519
ssh_hardening_opts: ssh_hardening_opts:
KexAlgorithms: KexAlgorithms:
- curve25519-sha256@libssh.org - curve25519-sha256@libssh.org

1
vars/ssh_6.7.yml Symbolic link
View file

@ -0,0 +1 @@
ssh_6.6.yml

View file

@ -1,6 +1,9 @@
# 7.4: Debian 9 # 7.4: Debian 9
# 7.4: RedHat/CentOS 7 # 7.4: RedHat/CentOS 7
ssh_hardening_hostkeys:
- ed25519
ssh_hardening_opts: ssh_hardening_opts:
KexAlgorithms: KexAlgorithms:
- curve25519-sha256 - curve25519-sha256

View file

@ -1,8 +1,5 @@
# 8.2: Ubuntu 10 # 8.2: Ubuntu 20.04
# 8.4: Debian 11 & Suse 15.3 # 8.4: Debian 11 & Suse 15.3
# 8.6: Fedora 34 (no diff in *hardened policy* to 8.4)
# 8.7: Fedora 35 (no diff in *hardened policy* to 8.4)
# 8.8: Arch/Void
ssh_hardening_opts: ssh_hardening_opts:
KexAlgorithms: KexAlgorithms:
@ -27,8 +24,8 @@ ssh_hardening_opts:
- ssh-ed25519-cert-v01@openssh.com - ssh-ed25519-cert-v01@openssh.com
- sk-ssh-ed25519@openssh.com - sk-ssh-ed25519@openssh.com
- sk-ssh-ed25519-cert-v01@openssh.com - sk-ssh-ed25519-cert-v01@openssh.com
- rsa-sha2-256
- rsa-sha2-512 - rsa-sha2-512
- rsa-sha2-256-cert-v01@openssh.com
- rsa-sha2-512-cert-v01@openssh.com - rsa-sha2-512-cert-v01@openssh.com
- rsa-sha2-256
- rsa-sha2-256-cert-v01@openssh.com

View file

@ -1 +1 @@
ssh_8.4.yml ssh_8.2.yml

View file

@ -1 +0,0 @@
ssh_8.2.yml

View file

@ -1 +0,0 @@
ssh_8.2.yml

View file

@ -1 +0,0 @@
ssh_8.2.yml

35
vars/ssh_default.yml Normal file
View file

@ -0,0 +1,35 @@
# 8.2: Ubuntu 20.04
# 8.4: Debian 11 & Suse 15.3
# 8.6: Fedora 34 (no diff in *hardened policy* to 8.4)
# 8.7: Fedora 35 (no diff in *hardened policy* to 8.4)
# 8.9: Ubuntu 22.04
ssh_hardening_opts:
KexAlgorithms:
- sntrup761x25519-sha512@openssh.com
- curve25519-sha256
- curve25519-sha256@libssh.org
- diffie-hellman-group16-sha512
- diffie-hellman-group18-sha512
- diffie-hellman-group-exchange-sha256
Ciphers:
- chacha20-poly1305@openssh.com
- aes256-gcm@openssh.com
- aes128-gcm@openssh.com
- aes256-ctr
- aes192-ctr
- aes128-ctr
MACs:
- hmac-sha2-256-etm@openssh.com
- hmac-sha2-512-etm@openssh.com
- umac-128-etm@openssh.com
HostKeyAlgorithms:
- ssh-ed25519
- ssh-ed25519-cert-v01@openssh.com
- sk-ssh-ed25519@openssh.com
- sk-ssh-ed25519-cert-v01@openssh.com
- rsa-sha2-512
- rsa-sha2-512-cert-v01@openssh.com
- rsa-sha2-256
- rsa-sha2-256-cert-v01@openssh.com

25
vars/ssh_stribika.yml Normal file
View file

@ -0,0 +1,25 @@
ssh_hardening_opts:
KexAlgorithms:
- curve25519-sha256@libssh.org
- diffie-hellman-group-exchange-sha256
Ciphers:
- chacha20-poly1305@openssh.com
- aes256-gcm@openssh.com
- aes128-gcm@openssh.com
- aes256-ctr
- aes192-ctr
- aes128-ctr
MACs:
- hmac-sha2-512-etm@openssh.com
- hmac-sha2-256-etm@openssh.com
- umac-128-etm@openssh.com
- hmac-sha2-512
- hmac-sha2-256
- umac-128@openssh.com
HostKeyAlgorithms:
- ssh-ed25519-cert-v01@openssh.com
- ssh-rsa-cert-v01@openssh.com
- ssh-ed25519
- ssh-rsa