diff --git a/data/hooks/conf_regen/03-ssh b/data/hooks/conf_regen/03-ssh index 5bb9cf916..54b7c55b7 100755 --- a/data/hooks/conf_regen/03-ssh +++ b/data/hooks/conf_regen/03-ssh @@ -12,7 +12,7 @@ do_pre_regen() { [[ ! -f /etc/yunohost/from_script ]] || return 0 cd /usr/share/yunohost/templates/ssh - + # do not listen to IPv6 if unavailable [[ -f /proc/net/if_inet6 ]] && ipv6_enabled=true || ipv6_enabled=false @@ -23,6 +23,9 @@ do_pre_regen() { ssh_keys="$ssh_keys $(ls /etc/ssh/ssh_host_dsa_key 2>/dev/null || true)" fi + # Support different strategy for security configurations + export compatibility="$(yunohost settings get 'security.ssh.compatibility')" + export ssh_keys export ipv6_enabled ynh_render_template "sshd_config" "${pending_dir}/etc/ssh/sshd_config" diff --git a/data/hooks/conf_regen/15-nginx b/data/hooks/conf_regen/15-nginx index 7ca63c003..60e719743 100755 --- a/data/hooks/conf_regen/15-nginx +++ b/data/hooks/conf_regen/15-nginx @@ -36,6 +36,9 @@ do_pre_regen() { main_domain=$(cat /etc/yunohost/current_host) domain_list=$(sudo yunohost domain list --output-as plain --quiet) + # Support different strategy for security configurations + export compatibility="$(yunohost settings get 'security.nginx.compatibility')" + # add domain conf files for domain in $domain_list; do domain_conf_dir="${nginx_conf_dir}/${domain}.d" @@ -57,6 +60,7 @@ do_pre_regen() { || cp yunohost_local.conf "${domain_conf_dir}/yunohost_local.conf" done + ynh_render_template "plain/yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf" # remove old domain conf files conf_files=$(ls -1 /etc/nginx/conf.d \ diff --git a/data/templates/nginx/plain/yunohost_admin.conf b/data/templates/nginx/plain/yunohost_admin.conf index ff61b8638..e0d9f6bb1 100644 --- a/data/templates/nginx/plain/yunohost_admin.conf +++ b/data/templates/nginx/plain/yunohost_admin.conf @@ -20,6 +20,14 @@ server { ssl_session_timeout 5m; ssl_session_cache shared:SSL:50m; + {% if compatibility == "modern" %} + # Ciphers with modern compatibility + # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern + # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...) + ssl_protocols TLSv1.2; + ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; + ssl_prefer_server_ciphers on; + {% else %} # As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519 ssl_ecdh_curve secp521r1:secp384r1:prime256v1; ssl_prefer_server_ciphers on; @@ -29,20 +37,15 @@ server { ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; - # Ciphers with modern compatibility - # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern - # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...) - #ssl_protocols TLSv1.2; - #ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; - # Uncomment the following directive after DH generation # > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 #ssl_dhparam /etc/ssl/private/dh2048.pem; - + {% endif %} + # Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners # https://wiki.mozilla.org/Security/Guidelines/Web_Security - # https://observatory.mozilla.org/ - more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload"; + # https://observatory.mozilla.org/ + more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload"; more_set_headers "Referrer-Policy : 'same-origin'"; more_set_headers "Content-Security-Policy : upgrade-insecure-requests; object-src 'none'; script-src https: 'unsafe-eval'"; more_set_headers "X-Content-Type-Options : nosniff"; diff --git a/data/templates/nginx/server.tpl.conf b/data/templates/nginx/server.tpl.conf index d8793ef05..fa8b6586b 100644 --- a/data/templates/nginx/server.tpl.conf +++ b/data/templates/nginx/server.tpl.conf @@ -29,6 +29,14 @@ server { ssl_session_timeout 5m; ssl_session_cache shared:SSL:50m; + {% if compatibility == "modern" %} + # Ciphers with modern compatibility + # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern + # The following configuration use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...) + ssl_protocols TLSv1.2; + ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; + ssl_prefer_server_ciphers on; + {% else %} # As suggested by Mozilla : https://wiki.mozilla.org/Security/Server_Side_TLS and https://en.wikipedia.org/wiki/Curve25519 ssl_ecdh_curve secp521r1:secp384r1:prime256v1; ssl_prefer_server_ciphers on; @@ -38,15 +46,10 @@ server { ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; - # Ciphers with modern compatibility - # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.6.2&openssl=1.0.1t&hsts=yes&profile=modern - # Uncomment the following to use modern ciphers, but remove compatibility with some old clients (android < 5.0, Internet Explorer < 10, ...) - #ssl_protocols TLSv1.2; - #ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; - # Uncomment the following directive after DH generation # > openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048 #ssl_dhparam /etc/ssl/private/dh2048.pem; + {% endif %} # Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners # https://wiki.mozilla.org/Security/Guidelines/Web_Security diff --git a/data/templates/ssh/sshd_config b/data/templates/ssh/sshd_config index ed870e5dc..8dc0e8dfc 100644 --- a/data/templates/ssh/sshd_config +++ b/data/templates/ssh/sshd_config @@ -15,10 +15,17 @@ HostKey {{ key }}{% endfor %} # https://infosec.mozilla.org/guidelines/openssh # ############################################## -# Keys, ciphers and MACS -KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,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 +{% if compatibility == "intermediate" %} + KexAlgorithms diffie-hellman-group-exchange-sha256 + Ciphers aes256-ctr,aes192-ctr,aes128-ctr + MACs hmac-sha2-512,hmac-sha2-256 +{% else %} + # By default use "modern" Mozilla configuration + # Keys, ciphers and MACS + KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,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 +{% endif %} # Use kernel sandbox mechanisms where possible in unprivileged processes UsePrivilegeSeparation sandbox diff --git a/locales/en.json b/locales/en.json index 41c68fd16..18ab84be1 100644 --- a/locales/en.json +++ b/locales/en.json @@ -210,8 +210,10 @@ "global_settings_setting_example_enum": "Example enum option", "global_settings_setting_example_int": "Example int option", "global_settings_setting_example_string": "Example string option", + "global_settings_setting_security_nginx_compatibility": "Compatibility vs. security tradeoff for the web server nginx. Affects the ciphers (and other security-related aspects)", "global_settings_setting_security_password_admin_strength": "Admin password strength", "global_settings_setting_security_password_user_strength": "User password strength", + "global_settings_setting_security_ssh_compatibility": "Compatibility vs. security tradeoff for the SSH server. Affects the ciphers (and other security-related aspects)", "global_settings_unknown_setting_from_settings_file": "Unknown key in settings: '{setting_key:s}', discarding it and save it in /etc/yunohost/settings-unknown.json", "global_settings_setting_service_ssh_allow_deprecated_dsa_hostkey": "Allow the use of (deprecated) DSA hostkey for the SSH daemon configuration", "global_settings_unknown_type": "Unexpected situation, the setting {setting:s} appears to have the type {unknown_type:s} but it's not a type supported by the system.", diff --git a/src/yunohost/settings.py b/src/yunohost/settings.py index 5d2d55ede..671ad70e9 100644 --- a/src/yunohost/settings.py +++ b/src/yunohost/settings.py @@ -7,6 +7,7 @@ from collections import OrderedDict from moulinette import m18n from yunohost.utils.error import YunohostError from moulinette.utils.log import getActionLogger +from yunohost.service import service_regen_conf logger = getActionLogger('yunohost.settings') @@ -39,6 +40,10 @@ DEFAULTS = OrderedDict([ ("security.password.admin.strength", {"type": "int", "default": 1}), ("security.password.user.strength", {"type": "int", "default": 1}), ("service.ssh.allow_deprecated_dsa_hostkey", {"type": "bool", "default": False}), + ("security.ssh.compatibility", {"type": "enum", "default": "modern", + "choices": ["intermediate", "modern"]}), + ("security.nginx.compatibility", {"type": "enum", "default": "intermediate", + "choices": ["intermediate", "modern"]}), ]) @@ -278,10 +283,12 @@ def trigger_post_change_hook(setting_name, old_value, new_value): # # =========================================== +@post_change_hook("security.nginx.compatibility") +def reconfigure_nginx(setting_name, old_value, new_value): + if old_value != new_value: + service_regen_conf(names=['nginx']) -#@post_change_hook("example.int") -#def myfunc(setting_name, old_value, new_value): -# print("In hook") -# print(setting_name) -# print(old_value) -# print(new_value) +@post_change_hook("security.ssh.compatibility") +def reconfigure_ssh(setting_name, old_value, new_value): + if old_value != new_value: + service_regen_conf(names=['ssh'])