From b4c0cd987c51688b6a5b8a78f884e4e039eafe8f Mon Sep 17 00:00:00 2001 From: Zentoo Date: Mon, 8 Jun 2026 19:00:16 +0200 Subject: [PATCH] Add gentoo linux support --- bin/admin/install | 4 ++ etc/pam.d/sshd.gentoo | 90 +++++++++++++++++++++++ etc/ssh/ssh_config.gentoo | 115 ++++++++++++++++++++++++++++++ etc/ssh/sshd_config.gentoo | 142 +++++++++++++++++++++++++++++++++++++ 4 files changed, 351 insertions(+) create mode 100644 etc/pam.d/sshd.gentoo create mode 100644 etc/ssh/ssh_config.gentoo create mode 100644 etc/ssh/sshd_config.gentoo diff --git a/bin/admin/install b/bin/admin/install index 62e1b68..d166d54 100755 --- a/bin/admin/install +++ b/bin/admin/install @@ -282,6 +282,8 @@ if [ "${opt[modify-ssh-config]}" = 1 ] || [ "${opt[modify-sshd-config]}" = 1 ] ; fi elif echo "$DISTRO_LIKE" | grep -q -w suse; then filesuffix=opensuse15 + elif echo "$DISTRO_LIKE" | grep -q -w gentoo; then + filesuffix=gentoo fi elif [ "$OS_FAMILY" = FreeBSD ]; then filesuffix=freebsd @@ -1218,6 +1220,8 @@ if [ "${opt[modify-pam-sshd]}" = 1 ]; then [ "$OS_FAMILY" = FreeBSD ] && pamsuffix=freebsd if [ "$LINUX_DISTRO" = ubuntu ] && [ "$DISTRO_VERSION_MAJOR" -ge 22 ]; then pamsuffix="ubuntu2204" + elif [ "$LINUX_DISTRO" = "'gentoo'" ]; then + pamsuffix="gentoo" elif [ -n "$pamsuffix" ] && [ -e "$basedir/etc/pam.d/sshd.$pamsuffix$DISTRO_VERSION" ]; then pamsuffix="$pamsuffix$DISTRO_VERSION" fi diff --git a/etc/pam.d/sshd.gentoo b/etc/pam.d/sshd.gentoo new file mode 100644 index 0000000..d86e68b --- /dev/null +++ b/etc/pam.d/sshd.gentoo @@ -0,0 +1,90 @@ +# PAM configuration for the Secure Shell service + +# instantly fail if /etc/nologin exists and user is not root: +auth requisite pam_nologin.so + + +# --- PASSWORD CHECK SECTION +# proceed in this section ONLY if the user is in group mfa-password-configd, skip it entirely otherwise (5 lines -> next section) +auth [success=ignore ignore=ignore default=5] pam_succeed_if.so quiet user ingroup mfa-password-configd +# just display a nice message to the user: +auth optional pam_echo.so Your account has Multi-Factor Authentication enabled, an additional authentication factor is required (password). +# also display how many days remain before expiration of their password: +auth optional pam_exec.so quiet debug stdout /opt/bastion/bin/shell/pam_exec_pwd_info.sh +# lock account after 6 password failures, for 5 minutes. 'preauth' -> only fail if count is already reached: +auth required pam_faillock.so preauth deny=6 unlock_time=300 +# now actually ask for the password, and skip the next line if it's correct: +auth [success=1 new_authtok_reqd=1 ignore=ignore default=bad] pam_unix.so +# this line is only called if password failed. 'authfail' -> we increment the fail counter and abort auth: +auth [default=die] pam_faillock.so authfail deny=6 unlock_time=300 + + +# --- TOTP CHECK SECTION +# if root is logging in, enable TOTP check in all cases (nullok is used below, so if TOTP is not configured for root, it'll pass through): +auth [success=ignore ignore=ignore default=1] pam_succeed_if.so quiet uid eq 0 +# [success=ok new_authtok_reqd=ok ignore=ignore default=bad module_unknown=ignore] == required + module_unknown:ignore +# if you have a recent enough libpam-google-authenticator, you can customize the prompt with the following option: [authtok_prompt=Verification Code (OTP): ] +# you can also add "debug" for more verbose logs (requires a not too old version of the pam module) +# note the nullok parameter, instructing that if TOTP is not configured for root, it shouldn't be asked +# if you know you've configured TOTP for root and prefer blocking access if there is a problem with the secret file, remove `nullok' +auth [success=ok new_authtok_reqd=ok ignore=ignore default=bad module_unknown=ignore] pam_google_authenticator.so nullok secret=/var/otp/root +# if root, TOTP check has already been done just above, so skip this subsection (3 lines -> next section): +auth [success=3 ignore=ignore default=ignore] pam_succeed_if.so quiet uid eq 0 +# else (if not root), proceed in this subsection ONLY if the user is in group mfa-totp-configd, skip it entirely otherwise (2 lines -> next section): +auth [success=ignore ignore=ignore default=2] pam_succeed_if.so quiet user ingroup mfa-totp-configd +# just display a nice message to the user: +auth optional pam_echo.so Multi-Factor Authentication enabled, an additional authentication factor is required (OTP). +# now actually ask for the TOTP: +auth [success=ok new_authtok_reqd=ok ignore=ignore default=bad module_unknown=ignore] pam_google_authenticator.so secret=~/.otp + + +# Read environment variables from /etc/environment and +# /etc/security/pam_env.conf. +session required pam_env.so # [1] +# In Debian 4.0 (etch), locale-related environment variables were moved to +# /etc/default/locale, so read that as well. +session required pam_env.so user_readenv=1 envfile=/etc/env.d/02locale + +# Disallow non-root logins when /etc/nologin exists. +account required pam_nologin.so + +# Reset counter if auth succeeded +account required pam_faillock.so + +# Uncomment and edit /etc/security/access.conf if you need to set complex +# access limits that are hard to express in sshd_config. +# account required pam_access.so + +# Standard Un*x authorization. +account include system-login + +# Standard Un*x session setup and teardown. +session include system-login + +# Print the message of the day upon successful login. +session optional pam_motd.so noupdate + +# Print the status of the user's mailbox upon successful login. +#session optional pam_mail.so standard noenv # [1] + +# Set up user limits from /etc/security/limits.conf. +session required pam_limits.so + +# Set the loginuid process attribute. +session required pam_loginuid.so + +# Create a new session keyring. +session optional pam_keyinit.so force revoke + +# SELinux needs to be the first session rule. This ensures that any +# lingering context has been cleared. Without this it is possible that a +# module could execute code in the wrong domain. +session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close + +# SELinux needs to intervene at login time to ensure that the process starts +# in the proper default security context. Only sessions which are intended +# to run in the user's context should be run after this. +session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open + +# Standard Un*x password updating. +password include system-auth diff --git a/etc/ssh/ssh_config.gentoo b/etc/ssh/ssh_config.gentoo new file mode 100644 index 0000000..e6ff930 --- /dev/null +++ b/etc/ssh/ssh_config.gentoo @@ -0,0 +1,115 @@ +# Hardened SSH bastion config -- modify wisely! +# Based on https://wiki.mozilla.org/Security/Guidelines/OpenSSH +# With modifications where applicable/needed + +# hardened params follow. every non-needed feature is disabled by default, +# following the principle of least rights and least features (more enabled +# features mean a more important attack surface). + +# === FEATURES === + +# disable non-needed sshd features +Tunnel no +ForwardAgent no +ForwardX11 no +GatewayPorts no +ControlMaster no + +# === CRYPTOGRAPHY === + +# enforce the use of ssh version 2 protocol, version 1 is disabled. +# all sshd_config options regarding protocol 1 are therefore omitted. +Protocol 2 + +# list of allowed ciphers. +# chacha20-poly1305 is a modern cipher, considered very secure +# aes is still the standard, we prefer gcm cipher mode, but also +# allow ctr cipher mode for compatibility (ctr is considered secure) +# we deny arcfour(rc4), 3des, blowfish and cast +# for older remote servers (or esoteric hardware), we might need to add: aes256-cbc,aes192-cbc,aes128-cbc +# known gotchas: +# - BSD (https://lists.freebsd.org/pipermail/freebsd-bugs/2013-June/053005.html) needs aes256-gcm@openssh.com,aes128-gcm@openssh.com DISABLED +# - Old Cisco IOS (such as v12.2) only supports aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc +# - Ancient Debians (Sarge) and RedHats (7) only support aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes128-ctr,aes192-ctr,aes256-ctr +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr + +# list of allowed message authentication code algorithms. +# etm (encrypt-then-mac) are considered the more secure, we +# prefer umac (has been proven secure) then sha2. +# for older remote servers, fallback to the non-etm version of +# the algorithms. we deny md5 entirely. +# for older remote servers (or esoteric hardware), we might need to add: hmac-sha1 +# Known gotchas: +# - Old Cisco IOS (such as v12.2) only supports hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96 +# - Ancient Debians (Sarge) and RedHats (7) only support hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 +MACs umac-128-etm@openssh.com,umac-64-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128@openssh.com,umac-64@openssh.com,hmac-sha2-512,hmac-sha2-256 + +# List of allowed key exchange algorithms. +# we prefer curve25519-sha256 which is considered the most modern/secure, +# and still allow diffie hellman with group exchange using sha256 which is +# the most secure dh-based kex. +# we avoid algorithms based on the disputed NIST curves, and anything based +# on sha1. +# known gotchas: +# - Windows needs diffie-hellman-group14-sha1 and also needs to NOT have diffie-hellman-group-exchange-sha1 present in the list AT ALL +# - OmniOS 5.11 needs diffie-hellman-group1-sha1 +# - Old Cisco IOS (such as v12.2) only supports diffie-hellman-group1-sha1 +# - Ancient Debians (Sarge) and RedHats (7) only support diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1 +KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 + +# === AUTHENTICATION === + +# we allow only public key authentication ... +PubkeyAuthentication yes +# ... not password nor keyboard-interactive +# ... (set to yes if sshpass is to be used) +PasswordAuthentication no +# ChallengeResponseAuthentication=yes forces KbdInteractiveAuthentication=yes in the openssh code! +ChallengeResponseAuthentication yes +KbdInteractiveAuthentication yes +# ... not host-based +HostbasedAuthentication no +# ... and not gssapi auth: [ uncomment if USE=kerberos ] +#GSSAPIAuthentication no +#GSSAPIKeyExchange no +#GSSAPIDelegateCredentials no +# now we specify the auth methods order we want for manual ssh calls. +# NOTE1: as per the ssh source code, an auth method omitted hereafter +# will not be used, even if set to "yes" above. +# NOTE2: the bastion code (namely, ttyrec), will always set the proper +# value explicitly on command-line (pubkey OR sshpass), so the value +# specified hereafter will be ignored. if you want to force-disable +# a method, set it to "no" in the list above, as those will never be +# overridden by the code. +PreferredAuthentications publickey,keyboard-interactive + +# === LOGIN ### + +# disable escape character use +EscapeChar none + +# detect if a hostkey changed due to DNS spoofing +CheckHostIP yes + +# ignore ssh-agent, only use specified keys (-i) +IdentitiesOnly yes +# disable auto-lookup of ~/.ssh/id_rsa ~/.ssh/id_ecdsa etc. +IdentityFile /dev/non/existent/file + +# carry those vars to the other side (includes LC_BASTION) +SendEnv LANG LC_* + +# allow usage of SSHFP DNS records +VerifyHostKeyDNS ask + +# yell if remote hostkey changed +StrictHostKeyChecking ask + +# === SYSTEM === + +# don't hash the users known_hosts files, in the context of a bastion, this adds no security +HashKnownHosts no + +# send an ssh ping each 57 seconds to the client and disconnect after 5 no-replies +ServerAliveInterval 57 +ServerAliveCountMax 5 diff --git a/etc/ssh/sshd_config.gentoo b/etc/ssh/sshd_config.gentoo new file mode 100644 index 0000000..3904488 --- /dev/null +++ b/etc/ssh/sshd_config.gentoo @@ -0,0 +1,142 @@ +# Hardened SSHD bastion config -- modify wisely! +# Based on https://wiki.mozilla.org/Security/Guidelines/OpenSSH +# With additional restrictions where applicable + +# -lo and -rt users only have local console login +DenyUsers *-rt +DenyUsers *-lo + +# hardened params follow. every non-needed feature is disabled by default, +# following the principle of least rights and least features (more enabled +# features mean a more important attack surface). + +# === FEATURES === + +# disable non-needed sshd features +AllowAgentForwarding no +AllowTcpForwarding no +AllowStreamLocalForwarding no +X11Forwarding no +PermitTunnel no +PermitUserEnvironment no +PermitUserRC no +GatewayPorts no + +# === INFORMATION DISCLOSURE === + +# however, display a legal notice for each connection +Banner /etc/ssh/banner + +# don't print the bastion MOTD on connection +PrintMotd no + +# === CRYPTOGRAPHY === + +# enforce the use of ssh version 2 protocol, version 1 is disabled. +# all sshd_config options regarding protocol 1 are therefore omitted. +Protocol 2 + +# only use hostkeys with secure algorithms, and omit the ones using NIST curves +HostKey /etc/ssh/ssh_host_ed25519_key +HostKey /etc/ssh/ssh_host_rsa_key + +# list of allowed ciphers. +# chacha20-poly1305 is a modern cipher, considered very secure +# aes is still the standard, we prefer gcm cipher mode, but also +# allow ctr cipher mode for compatibility (ctr is still considered secure) +# we deny arcfour(rc4), 3des, blowfish and cast +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr + +# list of allowed message authentication code algorithms. +# etm (encrypt-then-mac) are considered the more secure, we +# prefer umac (has been proven secure) then sha2. +# for older ssh client, fallback to the non-etm version of +# the algorithms. +# we deny md5 and sha1 +MACs umac-128-etm@openssh.com,umac-64-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128@openssh.com,umac-64@openssh.com,hmac-sha2-512,hmac-sha2-256 + +# List of allowed key exchange algorithms. +# we prefer curve25519-sha256 which is considered the most modern/secure, +# and still allow diffie hellman with group exchange using sha256 which is +# the most secure dh-based kex. +# we avoid algorithms based on the disputed NIST curves, and anything based +# on sha1. +KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 + +# force rekey every 512M of data or 6 hours of connection, whichever comes first +RekeyLimit 512M 6h + +# === AUTHENTICATION === + +# we allow only public key authentication ... +PubkeyAuthentication yes +# ... not password +PasswordAuthentication no +# ... keyboard interactive (needed for MFA through PAM) +KbdInteractiveAuthentication yes +# ... not kerberos: [ uncomment if USE=kerberos ] +#KerberosAuthentication no +# ... challenge-response (needed for MFA through PAM) +ChallengeResponseAuthentication yes +# ... not host-based +HostbasedAuthentication no +# ... and not gssapi auth: [ uncomment if USE=kerberos ] +#GSSAPIAuthentication no +#GSSAPIKeyExchange no + +# just in case, we also explicitly deny empty passwords +PermitEmptyPasswords no + +# this needs to be set at "yes" to allow PAM keyboard-interactive authentication, +# which is not a security issue because the AuthenticationMethods below force the use of +# either publickey or publickey+keyboard-interactive, hence password-only login is never +# possible, for root or any other account for that matter +PermitRootLogin yes + +# === LOGIN === + +# disconnect after 30 seconds if user didn't log in successfully +LoginGraceTime 30 + +# not more than 1 session per network connection (connection sharing with ssh client's master/shared mode) +MaxSessions 1 + +# maximum concurrent unauth connections to the sshd daemon +MaxStartups 50:30:500 + +# accept LANG and LC_* vars (also includes LC_BASTION) +AcceptEnv LANG LC_* + +# === SYSTEM === + +# sshd log level at verbose in auth facility for auditing purposes +LogLevel VERBOSE +SyslogFacility AUTH + +# check sanity of user HOME dir before allowing user to login +StrictModes yes + +# never use dns (slows down connections) +UseDNS no + +# use PAM facility +UsePAM yes + +# === AuthenticationMethods vs potential root OTP vs potential user MFA === +# If 2FA has been configured for root, we force pubkey+PAM for it. If this is the case +# on your system, uncomment the next two lines (see +# https://ovh.github.io/the-bastion/installation/advanced.html#fa-root-authentication) +#Match User root +# AuthenticationMethods publickey,keyboard-interactive:pam +# Unconditionally skip PAM auth for members of the bastion-nopam group +Match Group bastion-nopam + AuthenticationMethods publickey +# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam +Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional + AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam +# if in one of the mfa groups, use publickey AND pam +Match Group mfa-totp-configd,mfa-password-configd + AuthenticationMethods publickey,keyboard-interactive:pam +# by default, always ask the publickey (no PAM) +Match All + AuthenticationMethods publickey