漫談 sshd

最後更新: 2024-01-02

目錄

 


安裝
 

Openssh 這工具共分為兩個包:

Server 包: 是指設定檔及daemon(sshd) 本身

Client 包: 主要係 ssh, scp

Server包安裝:

apt-get install openssh-server

主要程式:

/usr/sbin/sshd                               # daemon 本身

設定檔:

/etc/ssh/sshd_config

Server 的公私匙:

ssh_host_dsa_key.pub
ssh_host_dsa_key

ssh_host_rsa_key.pub <-- 多數
ssh_host_rsa_key

P.S.

當安裝 Server包時, 它們會自動生成的 ~

Config Checking

/usr/sbin/sshd -t

-t    Test mode. Only check the validity of the configuration file and sanity of the keys.

echo $?

0

Client包

apt-get install openssh-client

設定檔:

/etc/ssh/ssh_config

主要程式:

/usr/bin/ssh

輔助工具:

/usr/bin/ssh-keygen
/usr/bin/scp

/usr/bin/ssh-add
/usr/bin/ssh-agent
/usr/bin/ssh-copy-id
/usr/bin/ssh-keyscan
/usr/bin/ssh-argv0
/usr/bin/sftp
/usr/bin/slogin
/usr/bin/ssh-vulnkey

 


第一次登入

 

如果係用 Linux 的朋友, client 工具必然是 ssh 了, 不用多說

在 Window 上, ssh 有很多 client 供選擇

而我是用 pietty 的

pietty 它是聞名世界的 putty 中文加強版來,

在中文支援方面尤其出色.

當我們在第一次 login 入 ssh server 時, 我們會見到

注意紅圈部份, 在不同 Server, 就有不用的 fingerprint.

它是 ssh_host_rsa_key.pub 公匙的指紋來,

理論上它是獨一無二的.

我們是用它來分辨是否連上真正的 Server

在第二次連上用一 Server 時, client 就不會再問,

因為 fingerprint 已經保存在 regetry 裡

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys

 


Debug with SyslogFacility

 

SyslogFacility AUTHPRIV
LogLevel Debug

service sshd restart

 


公私匙認證 (authentication key)

 

一般情況下 ssh 是用帳戶名及密碼登入的, 而 authentication key 是以公匙及私匙的形式登入

好處是比較安全 (唔怕比人撞密碼)

作法:

在Server 上行 ssh-ssh-keygen 建立密公匙及私匙

它們是建立在 ./ssh 的目錄下, 分別是 id_rsa 及 id_rsa.pub

id_rsa 是私匙 ( 要好好小心保存, 不用放在 Server 上的 ),

id_rsa.pub 是公匙 ( 要放在Server上 )

之後把 id_rsa.pub 改名成 authorized_keys 就可以用它作認證之用

( mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys )

Server Setting

# 相當於 %h/.ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys

Variable

  • %u by the login name of the use

i.e.

AuthorizedKeysFile /etc/ssh/authorized_keys/%u

sshd為了安全, 對屬主的目錄和文件權限有所要求.

Debug log

Authentication refused: bad ownership or modes for directory

Fix

chmod g-w /home/your_user
chmod 700 .ssh
chmod 600 .ssh/authorized_keys

OR

StrictModes off

authorized_keys format

# key-comment
options keytype base64-encoded_key comment

options: optional. comma-separated option specifications

keytype: ssh-rsa, ssh-dss, ...

The options are supported in authorized_keys files

restrict

Enable all restrictions

i.e. disable port, agent and X11 forwarding, as well as disabling PTY allocation and execution of ~/.ssh/rc

command="cmd"

# Specifies that the command is executed whenever this key is used for authentication.
# The command supplied by the user (if any) is ignored.
# (useful to restrict certain public keys to perform just a specific operation)
# The command is run on a pty if the client requests a pty;
# otherwise it is run without a tty.

environment="NAME=value"

# The patterns may use "*" as wildcard
# CIDR address/masklen notation
# An exclamation mark ! can be used in front of a pattern to negate it.
# Support DNS Name
from="pattern-list"

i.e.

from="*.sales.example.net,!pc.sales.example.net"

no-pty

# Prevents allocation of a pseudo-tty

no-user-rc

# Disables execution of .ssh/rc when using the key.

forwarding

no-agent-forwarding

no-port-forwarding

no-x11-forwarding

permitopen="host:port"         # -L option

permitlisten="[host:]port"      # -R option

tunnel="n"

 


認證方式

 

... sshd[27691]: debug1: KEX done [preauth]
... sshd[27691]: debug1: userauth-request for user MyUserName service ssh-connection method none [preauth]
... sshd[27691]: debug1: attempt 0 failures 0 [preauth]
... sshd[27691]: debug1: PAM: initializing for "MyUserName"
... sshd[27691]: debug1: PAM: setting PAM_RHOST to "IP.ctinets.com"
... sshd[27691]: debug1: PAM: setting PAM_TTY to "ssh"
... sshd[27691]: debug1: userauth_send_banner: sent [preauth]
--------------------------------
... sshd[27691]: debug1: userauth-request for user MyUserName service ssh-connection method publickey [preauth]
... sshd[27691]: debug1: attempt 1 failures 0 [preauth]
... sshd[27691]: debug1: userauth_pubkey: test whether pkalg/pkblob are acceptable for RSA SHA256:?/? [preauth]
... sshd[27691]: debug1: temporarily_use_uid: 1063/1063 (e=0/0)
... sshd[27691]: debug1: trying public key file /root/.ssh/authorized_keys
... sshd[27691]: debug1: Could not open authorized keys '/root/.ssh/authorized_keys': Permission denied
... sshd[27691]: debug1: restore_uid: 0/0
... sshd[27691]: Failed publickey for MyUserName from R.R.R.R port 57044 ssh2: RSA SHA256:?/?
--------------------------------
... sshd[27691]: debug1: userauth-request for user MyUserName service ssh-connection method keyboard-interactive [preauth]
... sshd[27691]: debug1: attempt 2 failures 1 [preauth]
... sshd[27691]: debug1: keyboard-interactive devs  [preauth]
... sshd[27691]: debug1: auth2_challenge: user=MyUserName devs= [preauth]
... sshd[27691]: debug1: kbdint_alloc: devices 'pam' [preauth]

 


加強安全性

 

設定安全:

# root 用戶不可經由 ssh login

PermitRootLogin no

Opts:

  • yes
  • prohibit-password (default)
  • without-password
  • forced-commands-only (public key authentication + command)
  • no

# 一定要用公匙及私匙 login

PasswordAuthentication no

# 只用 Protocol 2

Protocol 2

# 只可以給同時在 AllowUsers 及 AllowGroups 的帳戶登入
# 亦即是說要同時滿足這兩個條規則 !!
# 就算 PermitRootLogin yes 時, root 都不能 login

AllowUsers root sysadmin
AllowGroups admin

網絡安全

link

 


重新建立 host key

 

Error msg

Could not load host key: /etc/ssh/ssh_host_key

建立

ssh-keygen -A

ssh-keygen: generating new host keys: RSA1 ECDSA

 * "host keys do not exist" 才會建立新的 Key

OR

# ssh-keygen [-q] [-b bits] -t type [-N new_passphrase] [-C comment] [-f output_keyfile]

# -q      Silence ssh-keygen

cd /etc/ssh

ssh-keygen -t dsa -f ssh_host_dsa_key

ssh-keygen -t rsa -f ssh_host_rsa_key

ssh-keygen -t ecdsa -f ssh_host_ecdsa_key

查看 server 的 fingerprint

ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub

 


Alive

 

make your OpenSSH server keep alive all connections with clients

# send a null packet to the other side every 30 seconds

# give up if it doesn’t receive any response after 2 tries

ClientAliveInterval 30
ClientAliveCountMax 2

 


sshd listen to multiple ports

 

Port 22
Port 2201

 


Performance

 

sshd_config

# disable dns lookup the remote host name

UseDNS no

 


 

Banner none | /path/to/file

...

VersionAddendum String....

additional text to append to the SSH protocol banner sent by the server upon connection.

telnet localhost 22

SSH-2.0-OpenSSH_7.4 Private SFTP

 


sshd per user configuration

 

e.g.

Match User USERNAME
  PasswordAuthentication no

不是所有的 Setting 都可以 per user 的, 只有以下 Setting 適用

AllowAgentForwarding, AllowTcpForwarding,

AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner, ChrootDirectory,

ForceCommand, GatewayPorts,

GSSAPIAuthentication,

HostbasedAuthentication, HostbasedUsesNameFromPacketOnly,

KbdInteractiveAuthentication, KerberosAuthentication,

MaxAuthTries, MaxSessions, PasswordAuthentication,

PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTunnel,

PubkeyAuthentication,

RhostsRSAAuthentication, RSAAuthentication,

X11DisplayOffset, X11Forwarding and X11UseLocalHost.

 


Environment Variable

 

PermitUserEnvironment

# The default is no

Specifies whether "~/.ssh/environment" and "environment=" options in ~/.ssh/authorized_keys are processed by sshd

AcceptEnv

Specifies what environment variables sent by the client will be copied into the session's environ(7). 

See SendEnv in ssh_config(5) for how to configure the client. 

The TERM environment variable is always sent whenever the client requests a pseudo-terminal as it is required by the protocol. 

Variables are specified by name, which may contain the wildcard characters ‘*’and ‘?’. 

Multiple environment variables may be separated by whitespace or spread across multiple AcceptEnv directives. 

Bewarned that some environment variables could be used to bypass restricted user environments. 

For this reason, care should be taken in the use of this directive.  The default is not to accept any environment variables.

 


ForceCommand

 

The command is invoked by using the user's login shell with the -c option.

This applies to shell, command, or subsystem execution.

 

 

 


Login 後顯示的 message(motd)

 

/etc/motd

支援中文

"Last login" & Motd message

它們 default 都是 yes

/etc/ssh/sshd_config

PrintLastLog yes
PrintMotd yes

~/.hushlogin

Suppress printing the "PrintLastLog" & "PrintMotd"

It does not suppress printing "Banner"

pam_motd

Link

Example

Rocky 8 Login 後會有:

Activate the web console with: systemctl enable --now cockpit.socket

# Stop 它

rm -f /etc/issue.d/cockpit.issue /etc/motd.d/cockpit

 


UsePAM

 

UsePAM (Default: no)

yes: this will enable PAM authentication using ChallengeResponseAuthentication and PasswordAuthentication
in addition to PAM account and session module processing for all authentication types.

Because PAM challenge-response authentication usually serves an equivalent role to PasswordAuthentication,

You should disable either PasswordAuthentication or ChallengeResponseAuthentication.

建議

UsePAM yes
PasswordAuthentication yes
ChallengeResponseAuthentication no

 * If UsePAM is enabled, you will not be able to run sshd as a non-root user.

---

ChallengeResponseAuthentication (Default: yes)

Specifies whether challenge-response authentication is allowed.

---

 * PAM authentication via ChallengeResponseAuthentication may bypass the setting of

  • PasswordAuthentication no
  • PermitRootLogin without-password

---

WARNING: 'UsePAM no' is not supported in RHEL and may cause several problems.

 


History

 

UseLogin no    # /usr/bin/login

UseLogin option is disabled by default in OpenSSH for many years

telnet 年代的事:

init start getty & telnetd
 getty opened a serial port -> login (prompt for the password)
 telnetd                    -> login (prompt for the password)

 


Troubleshoot

 

Debug 方式

sshd re-exec requires execution with an absolute path

直接在 cli 行 "sshd" 係 start 唔到 sshd 的

原因:

For every new connection, sshd will re-execute itself,

to ensure that all execute-time randomisations are re-generated for each new connection.

In order for sshd to re-execute itself, it needs to know the full path to itself.

which sshd

/usr/sbin/sshd

sshd foreground debug on another port

# The server also will not fork and will only process one connection

# Multiple -d options increase the debugging level. (Maximum is 3)

/usr/sbin/sshd -d -p 9999

  • -d Debug mode
  • -p port 9999

[Issue] 某 user login 唔到

debug1: kbdint_alloc: devices 'pam'
debug1: auth2_challenge_start: trying authentication method 'pam'
Postponed keyboard-interactive for ???? from ::ffff:192.168.168.4 port 39132 ssh2
...
debug1: session_pty_req: session 0 alloc /dev/ttyp0
debug1: server_input_channel_req: channel 0 request shell reply 0
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req shell
debug1: PAM: setting PAM_TTY to "/dev/ttyp0"
debug1: Setting controlling tty using TIOCSCTTY.
debug1: Received SIGCHLD.                                       <-- 問題來了
debug1: session_by_pid: pid 4273
debug1: session_exit_message: session 0 channel 0 pid 4273
debug1: session_exit_message: release channel 0
debug1: session_close: session 0 pid 4273
debug1: session_by_tty: session 0 tty /dev/ttyp0
debug1: session_pty_cleanup: session 0 release /dev/ttyp0
debug1: channel 0: free: server-session, nchannels 1
Connection closed by ::ffff:192.168.168.4
debug1: do_cleanup
debug1: PAM: cleanup
Closing connection to ::ffff:192.168.168.4
debug1: PAM: cleanup

Fix

cat /etc/shells                                       # 查看系統有什麼 Shell

usermod -s /bin/bash USERNAME

[Issue] ssh login slow

log:

Jul 22 10:44:20 myserver sshd(pam_unix)[25925]: session opened for user root by (uid=0)
Jul 22 10:44:20 myserver sshd[25927]: nss_ldap: reconnecting to LDAP server (sleeping 4 seconds)...
Jul 22 10:44:20 myserver sshd[25927]: nss_ldap: reconnecting to LDAP server (sleeping 8 seconds)...
...................

[fix] Speed up SSH logon

GSSAPIAuthentication

GSSAPIAuthentication no

Generic Security Services API. In SSH's case its designed to talk to Kerberos.

GSSAPI is a IETF standard for doing strong encrypted authentication in network based applications.

OPENssh uses this API and the underlying kerberos 5 code to provide a alternative means of authentication other than ssh_keys.

# The "-v" maximum is 3

ssh -vvv

debug3: preferred gssapi-keyex,gssapi-with-mic,gssapi,publickey,keyboard-interactive,password

nsswitch

在 nsswitch.conf 內停用 ldap

/etc/nsswitch.conf

passwd:     files
shadow:     files
group:      files

[Issue]

sshd:Privilege separation user sshd does not exist

解決

UsePrivilegeSeparation no

說明

The default is ''yes''.

sshd separates privileges by creating an unprivileged child process to deal with incoming network traffic.

After successful authentication, another process will be created that has the privilege of the authenticated user.

The goal of privilege separation is to prevent privilege escalation by containing any corruption within the unprivileged processes.

[Issue]

OS: Centos 6

/var/log/secure

sshd[400]: fatal: daemon() failed: No such device

沒有 /dev/null

[Issue]

OS: Centos 7

ssh 時見到它時見到

... Server refused to allocate pty

查看

ls -la /dev/pts/*

lsof /dev/pts/*

/var/log/secure

error openpty read-only file system

mount | grep devpts

mount -t devpts devpts /dev/pts

mount -t devpts -o remount,rw,nosuid,noexec,relatime,uid=0,gid=5,mode=620 devpts /dev/pts

 

 

Creative Commons license icon Creative Commons license icon