OpenSSH
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
的选项包括用户、主机和地址。这时,host
和 addr
分别指代运行 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)
管道处理。有关更多选项,请参见“调试服务器配置”部分。
默认情况下,所有组的登录都是允许的。然而,如果指定了 AllowGroups
或 AllowUsers
,则所有未列出的用户或组将被禁止登录。允许/拒绝指令按以下顺序处理:
- DenyUsers
- AllowUsers
- DenyGroups
- AllowGroups
第一个匹配的模式生效,因此如果 AllowUsers
存在,它将完全覆盖 AllowGroups
,无论它们在配置文件中的顺序如何。因此,为了获得最大的灵活性,建议使用 AllowGroups
。与此相反,DenyUsers
和 DenyGroups
互不干扰,可以一起使用。列出组名或组名的模式,组名之间用空格分隔。如果指定了,登录仅允许或拒绝属于匹配组或模式的用户。仅组名或用户名有效,数值型的组或用户 ID 无法识别。
在 inetd / xinetd 下的 sshd
互联网服务守护进程(inetd
和 xinetd
)是一种按需启动其他服务的守护进程。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
,并可以利用 tcpd
的 tcpwrappers
来进一步控制访问或日志记录。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)
中的 PermitUserEnvironment
和 AcceptEnv
配置指令,以及 ssh_config(5)
中的 SendEnv
指令。
以下是 ssh(1)
可设置的变量,具体取决于情况:
-
DISPLAY
:如果 X11 被隧道传输,设置该变量以指示 X11 服务器的位置。由ssh(1)
自动设置时,它的格式为hostname:n
,其中hostname
表示 shell 所在的主机,n
是大于等于 1 的整数。 -
HOME
:用户的主目录路径。 -
LOGNAME
:USER
的同义词,主要用于与使用该变量的系统兼容。 -
MAIL
:用户的邮箱路径。 -
PATH
:ssh(1)
编译时指定的默认路径。 -
SSH_ASKPASS
:如果同时设置了DISPLAY
和SSH_ASKPASS
,且 SSH 会话没有关联的终端或伪终端,则指定的程序会执行并打开 X11 窗口以读取密码短语,通常用于从 xsession 或相关脚本调用ssh(1)
时。 -
SSH_AUTH_SOCK
:客户端机器上指定 UNIX 域套接字的路径,用于与 SSH 密钥代理通信。 -
SSH_CONNECTION
:标识客户端和服务器端的连接,包含四个用空格分隔的值:客户端 IP 地址、客户端端口号、服务器 IP 地址和服务器端口号。 -
SSH_ORIGINAL_COMMAND
:如果使用了ForceCommand
指令或在密钥中设置了Command="..."
,则该变量包含原始命令及其选项。 -
SSH_TTY
:设置为当前 shell 或命令关联的 TTY 名称(设备路径)。如果当前会话没有 TTY,该变量不会设置。 -
SSH_USER_AUTH
:如果在sshd_config(5)
中设置了ExposeAuthInfo
,则此变量将包含用于此会话的认证方法的临时文件名。 -
TZ
:如果在守护进程启动时设置了该变量,则它表示当前的时区。SSH 守护进程会将此值传递给新连接。 -
USER
:设置为登录用户的名称。