SSH 服务器

SSH 的架构是服务器/客户端模式,两端运行的软件是不一样的。OpenSSH 的客户端软件是 ssh,服务器软件是 sshd。本章介绍 sshd 的各种知识。

如果没有安装 sshd,可以用下面的命令安装。

# Debian
$ sudo aptitude install openssh-server

# Red Hat
$ sudo yum install openssh-server

一般来说,sshd 安装后会跟着系统一起启动。如果当前 sshd 没有启动,可以用下面的命令启动。

$ sshd

上面的命令运行后,如果提示“sshd re-exec requires execution with an absolute path”,就需要使用绝对路径来启动。这是为了防止有人出于各种目的,放置同名软件在$PATH变量指向的目录中,代替真正的 sshd。

# Centos、Ubuntu、OS X
$ /usr/sbin/sshd

上面的命令运行以后,sshd 自动进入后台,所以命令后面不需要加上&。

除了直接运行可执行文件,也可以通过 Systemd 启动 sshd。

# 启动
$ sudo systemctl start sshd.service

# 停止
$ sudo systemctl stop sshd.service

# 重启
$ sudo systemctl restart sshd.service

下面的命令让 sshd 在计算机下次启动时自动运行。

$ sudo systemctl enable sshd.service

1. sshd 配置文件

sshd 的配置文件在/etc/ssh目录,主配置文件是sshd_config,此外还有一些安装时生成的密钥。

  • /etc/ssh/sshd_config:配置文件
  • /etc/ssh/ssh_host_ecdsa_key:ECDSA 私钥。
  • /etc/ssh/ssh_host_ecdsa_key.pub:ECDSA 公钥。
  • /etc/ssh/ssh_host_key:用于 SSH 1 协议版本的 RSA 私钥。
  • /etc/ssh/ssh_host_key.pub:用于 SSH 1 协议版本的 RSA 公钥。
  • /etc/ssh/ssh_host_rsa_key:用于 SSH 2 协议版本的 RSA 私钥。
  • /etc/ssh/ssh_host_rsa_key.pub:用于 SSH 2 协议版本的 RSA 公钥。
  • /etc/pam.d/sshd:PAM 配置文件。

注意,如果重装 sshd,上面这些密钥都会重新生成,导致客户端重新 ssh 连接服务器时,会跳出警告,拒绝连接。为了避免这种情况,可以在重装 sshd 时,先备份/etc/ssh目录,重装后再恢复这个目录。

配置文件sshd_config的格式是,每个命令占据一行。每行都是配置项和对应的值,配置项的大小写不敏感,与值之间使用空格分隔。

Port 2034

上面的配置命令指定,配置项Port的值是2034。Port写成port也可。

配置文件还有另一种格式,就是配置项与值之间有一个等号,等号前后的空格可选。

Port = 2034

配置文件里面,#开头的行表示注释。

# 这是一行注释

注意,注释只能放在一行的开头,不能放在一行的结尾。

Port 2034 # 此处不允许注释

上面的写法是错误的。

另外,空行等同于注释。

sshd 启动时会自动读取默认的配置文件。如果希望使用其他的配置文件,可以用 sshd 命令的-f参数指定。

$ sshd -f /usr/local/ssh/my_config

上面的命令指定 sshd 使用另一个配置文件my_config。

修改配置文件以后,可以用 sshd 命令的-t(test)检查有没有语法错误。

$ sshd -t

配置文件修改以后,并不会自动生效,必须重新启动 sshd。

$ sudo systemctl restart sshd.service

2. sshd 密钥

sshd 有自己的一对或多对密钥。它使用密钥向客户端证明自己的身份。所有密钥都是公钥和私钥成对出现,公钥的文件名一般是私钥文件名加上后缀.pub。

DSA 格式的密钥文件默认为/etc/ssh/ssh_host_dsa_key(公钥为ssh_host_dsa_key.pub),RSA 格式的密钥为/etc/ssh/ssh_host_rsa_key(公钥为ssh_host_rsa_key.pub)。如果需要支持 SSH 1 协议,则必须有密钥/etc/ssh/ssh_host_key。

如果密钥不是默认文件,那么可以通过配置文件sshd_config的HostKey配置项指定。默认密钥的HostKey设置如下。

# HostKey for protocol version 1
# HostKey /etc/ssh/ssh_host_key

# HostKeys for protocol version 2
# HostKey /etc/ssh/ssh_host_rsa_key
# HostKey /etc/ssh/ssh_host_dsa_ke

上面命令前面的#表示这些行都是注释,因为这是默认值,有没有这几行都一样。

如果要修改密钥,就要去掉行首的#,指定其他密钥。

HostKey /usr/local/ssh/my_dsa_key
HostKey /usr/local/ssh/my_rsa_key
HostKey /usr/local/ssh/my_old_ssh1_key

3. sshd 配置项

以下是/etc/ssh/sshd_config文件里面的配置项。

1)AcceptEnv

AcceptEnv指定允许接受客户端通过SendEnv命令发来的哪些环境变量,即允许客户端设置服务器的环境变量清单,变量名之间使用空格分隔(AcceptEnv PATH TERM)。

2)AllowGroups

AllowGroups指定允许登录的用户组(AllowGroups groupName,多个组之间用空格分隔。如果不使用该项,则允许所有用户组登录。

3)AllowUsers

AllowUsers指定允许登录的用户,用户名之间使用空格分隔(AllowUsers user1 user2),也可以使用多行AllowUsers命令指定,用户名支持使用通配符。如果不使用该项,则允许所有用户登录。该项也可以使用用户名@域名的格式(比如AllowUsers jones@example.com)。

4)AllowTcpForwarding

AllowTcpForwarding指定是否允许端口转发,默认值为yes(AllowTcpForwarding yes),local表示只允许本地端口转发,remote表示只允许远程端口转发。

5)AuthorizedKeysFile

AuthorizedKeysFile指定储存用户公钥的目录,默认是用户主目录的ssh/authorized_keys目录(AuthorizedKeysFile .ssh/authorized_keys)。

6)Banner

Banner指定用户登录后,sshd 向其展示的信息文件(Banner /usr/local/etc/warning.txt),默认不展示任何内容。

7)ChallengeResponseAuthentication

ChallengeResponseAuthentication指定是否使用“键盘交互”身份验证方案,默认值为yes(ChallengeResponseAuthentication yes)。

从理论上讲,“键盘交互”身份验证方案可以向用户询问多重问题,但是实践中,通常仅询问用户密码。如果要完全禁用基于密码的身份验证,请将PasswordAuthentication和ChallengeResponseAuthentication都设置为no。

8)Ciphers

Ciphers指定 sshd 可以接受的加密算法(Ciphers 3des-cbc),多个算法之间使用逗号分隔。

9)ClientAliveCountMax

ClientAliveCountMax指定建立连接后,客户端失去响应时,服务器尝试连接的次数(ClientAliveCountMax 8)。

10)ClientAliveInterval

ClientAliveInterval指定允许客户端发呆的时间,单位为秒(ClientAliveInterval 180)。如果这段时间里面,客户端没有发送任何信号,SSH 连接将关闭。

11)Compression

Compression指定客户端与服务器之间的数据传输是否压缩。默认值为yes(Compression yes)

12)DenyGroups

DenyGroups指定不允许登录的用户组(DenyGroups groupName)。

13)DenyUsers

DenyUsers指定不允许登录的用户(DenyUsers user1),用户名之间使用空格分隔,也可以使用多行DenyUsers命令指定。

14)FascistLogging

SSH 1 版本专用,指定日志输出全部 Debug 信息(FascistLogging yes)。

15)HostKey

HostKey指定 sshd 服务器的密钥,详见前文。

16)KeyRegenerationInterval

KeyRegenerationInterval指定 SSH 1 版本的密钥重新生成时间间隔,单位为秒,默认是3600秒(KeyRegenerationInterval 3600)。

17)ListenAddress

ListenAddress指定 sshd 监听的本机 IP 地址,即 sshd 启用的 IP 地址,默认是 0.0.0.0(ListenAddress 0.0.0.0)表示在本机所有网络接口启用。可以改成只在某个网络接口启用(比如ListenAddress 192.168.10.23),也可以指定某个域名启用(比如ListenAddress server.example.com)。

如果要监听多个指定的 IP 地址,可以使用多行ListenAddress命令。

ListenAddress 172.16.1.1
ListenAddress 192.168.0.1

18)LoginGraceTime

LoginGraceTime指定允许客户端登录时发呆的最长时间,比如用户迟迟不输入密码,连接就会自动断开,单位为秒(LoginGraceTime 60)。如果设为0,就表示没有限制。

19)LogLevel

LogLevel指定日志的详细程度,可能的值依次为QUIET、FATAL、ERROR、INFO、VERBOSE、DEBUG、DEBUG1、DEBUG2、DEBUG3,默认为INFO(LogLevel INFO)。

20)MACs

MACs指定sshd 可以接受的数据校验算法(MACs hmac-sha1),多个算法之间使用逗号分隔。

21)MaxAuthTries

MaxAuthTries指定允许 SSH 登录的最大尝试次数(MaxAuthTries 3),如果密码输入错误达到指定次数,SSH 连接将关闭。

22)MaxStartups

MaxStartups指定允许同时并发的 SSH 连接数量(MaxStartups)。如果设为0,就表示没有限制。

这个属性也可以设为A:B:C的形式,比如MaxStartups 10:50:20,表示如果达到10个并发连接,后面的连接将有50%的概率被拒绝;如果达到20个并发连接,则后面的连接将100%被拒绝。

23)PasswordAuthentication

PasswordAuthentication指定是否允许密码登录,默认值为yes(PasswordAuthentication yes),建议改成no(禁止密码登录,只允许密钥登录)。

24)PermitEmptyPasswords

PermitEmptyPasswords指定是否允许空密码登录,即用户的密码是否可以为空,默认为yes(PermitEmptyPasswords yes),建议改成no(禁止无密码登录)。

25)PermitRootLogin

PermitRootLogin指定是否允许根用户登录,默认为yes(PermitRootLogin yes),建议改成no(禁止根用户登录)。

还有一种写法是写成prohibit-password,表示 root 用户不能用密码登录,但是可以用密钥登录。

PermitRootLogin prohibit-password

26)PermitUserEnvironment

PermitUserEnvironment指定是否允许 sshd 加载客户端的~/.ssh/environment文件和~/.ssh/authorized_keys文件里面的environment= options环境变量设置。默认值为no(PermitUserEnvironment no)。

27)Port

Port指定 sshd 监听的端口,即客户端连接的端口,默认是22(Port 22)。出于安全考虑,可以改掉这个端口(比如Port 8822)。

配置文件可以使用多个Port命令,同时监听多个端口。

Port 22
Port 80
Port 443
Port 8080

上面的示例表示同时监听4个端口。

28)PrintMotd

PrintMotd指定用户登录后,是否向其展示系统的 motd(Message of the day)的信息文件/etc/motd。该文件用于通知所有用户一些重要事项,比如系统维护时间、安全问题等等。默认值为yes(PrintMotd yes),由于 Shell 一般会展示这个信息文件,所以这里可以改为no。

29)PrintLastLog

PrintLastLog指定是否打印上一次用户登录时间,默认值为yes(PrintLastLog yes)。

30)Protocol

Protocol指定 sshd 使用的协议。Protocol 1表示使用 SSH 1 协议,建议改成Protocol 2(使用 SSH 2 协议)。Protocol 2,1表示同时支持两个版本的协议。

31)PubKeyAuthentication

PubKeyAuthentication指定是否允许公钥登录,默认值为yes(PubKeyAuthentication yes)。

32)QuietMode

SSH 1 版本专用,指定日志只输出致命的错误信息(QuietMode yes)。

33)RSAAuthentication

RSAAuthentication指定允许 RSA 认证,默认值为yes(RSAAuthentication yes)。

34)ServerKeyBits

ServerKeyBits指定 SSH 1 版本的密钥重新生成时的位数,默认是768(ServerKeyBits 768)。

35)StrictModes

StrictModes指定 sshd 是否检查用户的一些重要文件和目录的权限。默认为yes(StrictModes yes),即对于用户的 SSH 配置文件、密钥文件和所在目录,SSH 要求拥有者必须是根用户或用户本人,用户组和其他人的写权限必须关闭。

36)SyslogFacility

SyslogFacility指定 Syslog 如何处理 sshd 的日志,默认是 Auth(SyslogFacility AUTH)。

37)TCPKeepAlive

TCPKeepAlive指定打开 sshd 跟客户端 TCP 连接的 keepalive 参数(TCPKeepAlive yes)。

38)UseDNS

UseDNS指定用户 SSH 登录一个域名时,服务器是否使用 DNS,确认该域名对应的 IP 地址包含本机(UseDNS yes)。打开该选项意义不大,而且如果 DNS 更新不及时,还有可能误判,建议关闭。

39)UseLogin

UseLogin指定用户认证内部是否使用/usr/bin/login替代 SSH 工具,默认为no(UseLogin no)。

40)UserPrivilegeSeparation

UserPrivilegeSeparation指定用户认证通过以后,使用另一个子线程处理用户权限相关的操作,这样有利于提高安全性。默认值为yes(UsePrivilegeSeparation yes)。

41)VerboseMode

SSH 2 版本专用,指定日志输出详细的 Debug 信息(VerboseMode yes)。

42)X11Forwarding

X11Forwarding指定是否打开 X window 的转发,默认值为 no(X11Forwarding no)。

修改配置文件以后,可以使用下面的命令验证,配置文件是否有语法错误。

$ sshd -t

新的配置文件生效,必须重启 sshd。

$ sudo systemctl restart sshd

4. sshd 的命令行配置项

sshd 命令有一些配置项。这些配置项在调用时指定,可以覆盖配置文件的设置。

(1)-d

-d参数用于显示 debug 信息。

$ sshd -d

(2)-D

-D参数指定 sshd 不作为后台守护进程运行。

$ sshd -D

(3)-e

-e参数将 sshd 写入系统日志 syslog 的内容导向标准错误(standard error)。

(4)-f

-f参数指定配置文件的位置。

(5)-h

-h参数用于指定密钥。

$ sshd -h /usr/local/ssh/my_rsa_key

(6)-o

-o参数指定配置文件的一个配置项和对应的值。

$ sshd -o "Port 2034"

配置项和对应值之间,可以使用等号。

$ sshd -o "Port = 2034"

如果省略等号前后的空格,也可以不使用引号。

$ sshd -o Port=2034

-o参数可以多个一起使用,用来指定多个配置关键字。

(7)-p

-p参数指定 sshd 的服务端口。

$ sshd -p 2034

上面命令指定 sshd 在2034端口启动。

-p参数可以指定多个端口。

$ sshd -p 2222 -p 3333

(8)-t

-t参数检查配置文件的语法是否正确。

下一章:SSH 端口转发

SSH 除了登录服务器,还有一大用途,就是作为加密通信的中介,充当两台服务器之间的通信加密跳板,使得原本不加密的通信变成加密通信。这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)端口转发有三种使用方法:动态转发,本地转发,远程转发。