SSH - ether42/bootable-usb GitHub Wiki

Setup

On the rootfs:

apt-get install --no-install-recommends openssh-server libpam-google-authenticator nscd
systemctl disable ssh nscd

OpenSSH

The following configurations will allow any user to authenticate via either:

  • public key
  • password and TOTP

The major downside being that the (public key && TOTP) || (password && TOTP) condition can not be expressed for now.

Enabling UsePAM will use PAM for keyboard-interactive and password methods.

If PAM is configured to requires password and TOTP, it will result in:

  • impossibility to log via password only
  • two-factor authentication for keyboard-interactive
  • two-factor authentication for password,keyboard-interactive (the password being asked two times)
  • three-factor authentication for publickey,keyboard-interactive

If PAM is configured to only requires TOTP, it will result in:

  • impossibility to log via password only
  • one-factor authentication for keyboard-interactive
  • two-factor authentication for publickey,keyboard-interactive

The configuration tries to minimize any possible interaction with the basion host: only port forwarding should be possible.

The complete /etc/ssh/sshd_config:

# authentication
AuthenticationMethods publickey keyboard-interactive
UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
MaxAuthTries 1 # every failure will be logged (each method from the user counts as a try)

# disable access
PermitRootLogin no
PermitTTY no
ChrootDirectory /etc/ssh/chroot

# information leakage
Banner none
DebianBanner none

# misc
PrintLastLog no
PrintMotd no
UseDNS no # avoid possible time-consuming resolution of the client's IP

# logging
SyslogFacility AUTH
LogLevel INFO

The configuration can be tested and seen with:

sshd -t
sshd -T

Create the chroot:

mkdir -p /etc/ssh/chroot/var/run/nscd
echo "/var/run/nscd $_ none bind" >> /etc/fstab

For port forwarding using a destination name instead of an IP, glibc needs to be able to dynamically open the name resolution libraries in order to resolve it. However, hard linking /etc/resolv.conf & libnss_dns* is a bad practice: if the files are recreated instead of edited in place, the chroot won't be updated. There is a workaround by making nscd's socket available into the chroot so glibc can use it.

In /etc/pam.d/sshd, append after @include common-password:

# the parent directory must be owned by the user as the library create a temporary ~ file
auth required pam_google_authenticator.so secret=/etc/ssh/google_authenticator/${USER}/secret

debug is an useful option.

Refer to SSSD for the basic LDAP server configuration.

Create a group to authorize some users to connect:

ldapadd -Y EXTERNAL -H ldapi:// -f <(cat << EOF
dn: cn=ssh-allow,ou=groups,dc=lorn,dc=space
objectClass: posixGroup
objectClass: groupOfNames
cn: ssh-allow
gidNumber: 20000
member: uid=$user,ou=users,dc=lorn,dc=space
EOF
)

Configure SSSD to allow access via this group:

access_provider = ldap
ldap_access_filter = memberof=cn=ssh-allow,ou=groups,dc=lorn,dc=space

Setup each user:

mkdir -p /etc/ssh/google_authenticator/$user
google-authenticator --time-based --qr-mode=UTF8 --secret /etc/ssh/google_authenticator/$user/secret --disallow-reuse --minimal-window --no-rate-limit --force --label "[email protected]" --issuer ''
chown -R $user: /etc/ssh/google_authenticator/$user

Here is an example of a session to forward some ports to a private service (sudo is required here only for the privileged ports in order allow the HTTP to HTTPS redirection of the web server):

sudo ssh -N -L 443:www-01.service:443 -L 80:www-01.service:80 -o PreferredAuthentications=keyboard-interactive [email protected]
Password: ******
Verification code: ******