OpenSSH 服务器(sshd(8))监听来自客户端的连接,并为每个新的传入连接启动一个或多个进程,处理密钥交换、加密、身份验证、程序执行和数据交换。在多路复用的情况下,一些进程会被重用。它可以独立运行并在后台等待,也可以在前台运行,或者可以由任何互联网服务守护进程按需加载。

自版本 8.2 起,ps(1) 显示的监听进程标题还显示待身份验证的连接数量。

$ ps -p $(pgrep -u root sshd) -o pid,user,args
  PID USER     COMMAND
44476 root     sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)

请注意,这是待身份验证的连接数量,而不是那些已经通过身份验证的连接数量。每个已通过身份验证的连接都有其自己的处理进程,该进程由已通过身份验证的账户拥有。

sshd

sshd(8) 是安全的 Shell 守护进程,它监听传入的连接。ssh(1) 的标准端口由 IANA 指定为 22。如果 sshd(8) 不监听特权端口,则不必由 root 启动。然而,几乎没有情况下需要使用非标准端口。sshd(8) 可以绑定到多个地址,或者仅绑定到特定的地址。可以在同一台机器上运行多个不同配置的 sshd(8) 实例,这在多网卡机器上可能很有用。必须提供 sshd(8) 的绝对路径,例如 /usr/sbin/sshd

配置数据首先从传递给 Shell 的参数和选项解析,其次是用户特定的文件,最后是系统范围的配置文件。

  • sshd(8) - 允许登录的 SSH 守护进程。
  • sftp-server(8) - SFTP 服务器子系统,在需要时由 sshd(8) 自动启动。
  • ssh-keysign(8) - 用于基于主机的身份验证的辅助程序。
  • sshd_config(5) - 服务器配置文件。

sshd(8) 守护进程可以解析配置文件,测试其有效性,并报告有效的配置设置。这可以通过运行扩展测试模式(-T)来完成。扩展测试将输出实际的服务器设置。它还可以报告通过 Match 指令修改的设置,当与连接规范(-C)参数结合使用时,-C 的选项包括用户、主机和地址。这时,hostaddr 分别指代运行 sshd(8) 的主机和发起连接的地址。

以下命令将打印出如果用户“fred”尝试从地址 192.168.100.5 登录到主机 server.example.org 时应用的配置:

$ /usr/sbin/sshd -TC user=fred,host=server.example.org,addr=192.168.100.5

输出可能很长,因此可以通过 sort(1)less(1) 管道处理。有关更多选项,请参见“调试服务器配置”部分。

默认情况下,所有组的登录都是允许的。然而,如果指定了 AllowGroupsAllowUsers,则所有未列出的用户或组将被禁止登录。允许/拒绝指令按以下顺序处理:

  1. DenyUsers
  2. AllowUsers
  3. DenyGroups
  4. AllowGroups

第一个匹配的模式生效,因此如果 AllowUsers 存在,它将完全覆盖 AllowGroups,无论它们在配置文件中的顺序如何。因此,为了获得最大的灵活性,建议使用 AllowGroups。与此相反,DenyUsersDenyGroups 互不干扰,可以一起使用。列出组名或组名的模式,组名之间用空格分隔。如果指定了,登录仅允许或拒绝属于匹配组或模式的用户。仅组名或用户名有效,数值型的组或用户 ID 无法识别。

在 inetd / xinetd 下的 sshd

互联网服务守护进程(inetdxinetd)是一种按需启动其他服务的守护进程。xinetd(8)inetd(8) 是两种变体,都可以用来指定额外的参数和约束条件,包括以特定用户和组身份运行启动的服务。通过让一个守护进程在需要时调用其他守护进程,可以减少系统负载。通过这种方式启动 sshd(8) 意味着 inetd(8) 等待传入请求,启动 sshd(8),然后在 SSH 会话结束时关闭 sshd(8)

               包
互联网 --> 过滤器 --> tcpwrappers --> (x)inetd --> sshd
             (防火墙)  (也叫 tcpd)

这两种方式都可以用于额外的日志记录,如成功或失败的登录、访问限制(包括时间限制)、CPU 优先级和连接数等。还有很多其他的可能性。有关配置选项的完整概述,请参见 xinetd.conf(5)inetd.conf(5) 手册页。

inetd(8) 支持 tcpd,并可以利用 tcpdtcpwrappers 来进一步控制访问或日志记录。sshd(8) 自身也支持这一点,直到版本 6.6。但从 6.7 版本开始,OpenSSH 不再支持 tcpwrappers,因为当前的包过滤器已使其基本上变得多余。

使用 inetd(8)xinetd(8) 的两个主要缺点是连接启动时可能会稍微增加延迟,且 sshd(8) 必须配置为允许从服务守护进程启动。这个延迟仅影响初始连接,因此不会妨碍实际的操作。互联网服务守护进程不应该用于无状态服务,如 HTTP 和 HTTPS,因为每个操作本质上都是一次新的连接。有关详细信息,请参见 xinetd.conf(5)inetd.conf(5) 手册页。

来自 xinetd.conf(5) 的示例:

service ssh
{
	socket_type     = stream
	protocol        = tcp
	wait            = no
	user            = root
	server          = /usr/sbin/sshd
	server_args     = -i
	per_source      = UNLIMITED
	log_on_failure  = USERID HOST
	# log_on_success  = PID HOST DURATION TRAFFIC EXIT
	# instances       = 10
	# nice            = 10
	# bind            = 192.168.0.100
	# only_from       = 192.168.0.0
	# access_times    = 08:00-15:25
	# no_access       = 192.168.54.0
	# no_access       += 192.168.33.0
	# banner          = /etc/banner.inetd.connection.txt
	# banner_success  = /etc/banner.inetd.welcome.txt
	# banner_fail     = /etc/banner.inetd.takeahike.txt
}

来自 inetd.conf(5) 的示例:

ssh    stream  tcp     nowait  root /usr/sbin/sshd -i
ssh    stream  tcp6    nowait  root /usr/sbin/sshd -i

xinetd(8) 相比 inetd(8) 在功能上有多个优势,但在实际应用中,两者的使用场景相对较少。

SFTP 服务器子系统

SFTP 子系统首次出现在 OpenBSD 2.8 / OpenSSH 2.3[2] 中。它是通过 sshd(8) 根据需要调用的,使用 Subsystem 配置指令,并不是为了独立运行。SFTP 子系统有两种形式:一种是常规的 sftp-server(8),另一种是在进程内运行的 SFTP 服务器,这种方式在与 ChrootDirectory 指令一起使用时不需要支持文件。可以通过 Subsystem 配置指令传递选项:

  • -d:指定用户的替代起始目录,默认为用户的主目录。(首次出现在 6.2 版本)

    Subsystem sftp internal-sftp -d /var/www
    
  • -e:将日志信息发送到 stderr 而不是 syslog(3)

    Subsystem sftp internal-sftp -e
    
  • -f:指定日志记录时使用的 syslog(3) 功能代码。可能的值有:DAEMON、USER、AUTH、LOCAL0、LOCAL1、LOCAL2、LOCAL3、LOCAL4、LOCAL5、LOCAL6、LOCAL7。

    Subsystem    sftp    /usr/libexec/sftp-server -f LOCAL0
    
  • -l:指定哪些信息将由 sftp-server(8) 记录。默认值为 AUTH。其他可能的值有:QUIET、FATAL、ERROR、INFO、VERBOSE、DEBUG、DEBUG1、DEBUG2 和 DEBUG3。INFO 和 VERBOSE 记录 sftp-server客户端执行的事务。DEBUG 和 DEBUG1 等价,而 DEBUG2 和 DEBUG3 分别表示更高层次的调试输出。日志级别 DEBUG 到 DEBUG3 会违反用户隐私,应该避免在常规操作中使用。默认日志级别为 ERROR。

    Subsystem    sftp    /usr/libexec/sftp-server -l VERBOSE
    
  • -p-P:分别指定白名单和黑名单协议请求。如果两者都使用,黑名单优先。

  • -Q:提供服务器支持的协议功能列表。自版本 6.5 起,只有请求协议功能可以查询。

    $ /usr/libexec/sftp-server -Q requests
    
  • -R:将 SFTP 子系统置于只读模式。尝试修改文件系统(包括打开文件进行写操作)将失败。

  • -u:覆盖用户的默认 umask 并显式设置 umask(2) 用于创建文件和目录。

    Subsystem sftp internal-sftp -u 0002
    

环境变量

ssh(1)sshd(8) 在登录时会自动设置一些环境变量。如果文件 ~/.ssh/environment 存在并且用户允许更改环境变量,可以显式定义其他变量。环境变量也可以在 authorized_keys 文件中按键设置,前提是用户允许更改环境变量。

~/.ssh/environment 中,使用 NAME=value 格式设置变量。在 ~/.ssh/authorized_keys/etc/ssh/authorized_keys 中,格式是 environment="NAME=value"。有关更多信息,请参见 sshd_config(5) 中的 PermitUserEnvironmentAcceptEnv 配置指令,以及 ssh_config(5) 中的 SendEnv 指令。

以下是 ssh(1) 可设置的变量,具体取决于情况:

  • DISPLAY:如果 X11 被隧道传输,设置该变量以指示 X11 服务器的位置。由 ssh(1) 自动设置时,它的格式为 hostname:n,其中 hostname 表示 shell 所在的主机,n 是大于等于 1 的整数。

  • HOME:用户的主目录路径。

  • LOGNAMEUSER 的同义词,主要用于与使用该变量的系统兼容。

  • MAIL:用户的邮箱路径。

  • PATHssh(1) 编译时指定的默认路径。

  • SSH_ASKPASS:如果同时设置了 DISPLAYSSH_ASKPASS,且 SSH 会话没有关联的终端或伪终端,则指定的程序会执行并打开 X11 窗口以读取密码短语,通常用于从 xsession 或相关脚本调用 ssh(1) 时。

  • SSH_AUTH_SOCK客户端机器上指定 UNIX 域套接字的路径,用于与 SSH 密钥代理通信。

  • SSH_CLIENT:标识连接的客户端端,包含客户端 IP 地址、客户端端口号和服务器端口号。

  • SSH_CONNECTION:标识客户端和服务器端的连接,包含四个用空格分隔的值:客户端 IP 地址、客户端端口号、服务器 IP 地址和服务器端口号。

  • SSH_ORIGINAL_COMMAND:如果使用了 ForceCommand 指令或在密钥中设置了 Command="...",则该变量包含原始命令及其选项。

  • SSH_TTY:设置为当前 shell 或命令关联的 TTY 名称(设备路径)。如果当前会话没有 TTY,该变量不会设置。

  • SSH_USER_AUTH:如果在 sshd_config(5) 中设置了 ExposeAuthInfo,则此变量将包含用于此会话的认证方法的临时文件名。

  • TZ:如果在守护进程启动时设置了该变量,则它表示当前的时区。SSH 守护进程会将此值传递给新连接。

  • USER:设置为登录用户的名称。

最后修改: 2025年01月19日 星期日 21:43