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

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的值是2034Port写成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

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_configHostKey配置项指定。默认密钥的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

sshd 配置项

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

  • AcceptEnv指定允许接受客户端通过SendEnv命令发来的哪些环境变量,即允许客户端设置服务器的环境变量清单,变量名之间使用空格分隔(AcceptEnv PATH TERM)。
  • AllowGroups指定允许登录的用户组(AllowGroups groupName,多个组之间用空格分隔。如果不使用该项,则允许所有用户组登录。
  • AllowUsers指定允许登录的用户,用户名之间使用空格分隔(AllowUsers user1 user2),也可以使用多行AllowUsers命令指定,用户名支持使用通配符。如果不使用该项,则允许所有用户登录。该项也可以使用用户名@域名的格式(比如AllowUsers jones@example.com)。
  • AllowTcpForwarding指定是否允许端口转发,默认值为yesAllowTcpForwarding yes),local表示只允许本地端口转发,remote表示只允许远程端口转发。
  • AuthorizedKeysFile指定储存用户公钥的目录,默认是用户主目录的ssh/authorized_keys目录(AuthorizedKeysFile .ssh/authorized_keys)。
  • Banner指定用户登录后,sshd 向其展示的信息文件(Banner /usr/local/etc/warning.txt),默认不展示任何内容。
  • ChallengeResponseAuthentication指定是否使用“键盘交互”身份验证方案,默认值为yesChallengeResponseAuthentication yes)。
    • 从理论上讲,“键盘交互”身份验证方案可以向用户询问多重问题,但是实践中,通常仅询问用户密码。如果要完全禁用基于密码的身份验证,请将PasswordAuthenticationChallengeResponseAuthentication都设置为no
  • Ciphers指定 sshd 可以接受的加密算法(Ciphers 3des-cbc),多个算法之间使用逗号分隔。
  • ClientAliveCountMax指定建立连接后,客户端失去响应时,服务器尝试连接的次数(ClientAliveCountMax 8)。
  • ClientAliveInterval指定允许客户端发呆的时间,单位为秒(ClientAliveInterval 180)。如果这段时间里面,客户端没有发送任何信号,SSH 连接将关闭。
  • Compression指定客户端与服务器之间的数据传输是否压缩。默认值为yesCompression yes
  • DenyGroups指定不允许登录的用户组(DenyGroups groupName)。
  • DenyUsers指定不允许登录的用户(DenyUsers user1),用户名之间使用空格分隔,也可以使用多行DenyUsers命令指定。
  • FascistLoggingSSH 1 版本专用,指定日志输出全部 Debug 信息(FascistLogging yes)。
  • HostKey指定 sshd 服务器的密钥,详见前文。
  • KeyRegenerationInterval指定 SSH 1 版本的密钥重新生成时间间隔,单位为秒,默认是3600秒(KeyRegenerationInterval 3600)。
  • 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
      
  • LoginGraceTime指定允许客户端登录时发呆的最长时间,比如用户迟迟不输入密码,连接就会自动断开,单位为秒(LoginGraceTime 60)。如果设为0,就表示没有限制。
  • LogLevel指定日志的详细程度,可能的值依次为QUIETFATALERRORINFOVERBOSEDEBUGDEBUG1DEBUG2DEBUG3,默认为INFOLogLevel INFO)。
  • MACs指定sshd 可以接受的数据校验算法(MACs hmac-sha1),多个算法之间使用逗号分隔。
  • MaxAuthTries指定允许 SSH 登录的最大尝试次数(MaxAuthTries 3),如果密码输入错误达到指定次数,SSH 连接将关闭。
  • MaxStartups指定允许同时并发的 SSH 连接数量(MaxStartups)。如果设为0,就表示没有限制。
    • 这个属性也可以设为A:B:C的形式,比如MaxStartups 10:50:20,表示如果达到10个并发连接,后面的连接将有50%的概率被拒绝;如果达到20个并发连接,则后面的连接将100%被拒绝。
  • PasswordAuthentication指定是否允许密码登录,默认值为yesPasswordAuthentication yes),建议改成no(禁止密码登录,只允许密钥登录)。
  • PermitEmptyPasswords指定是否允许空密码登录,即用户的密码是否可以为空,默认为yesPermitEmptyPasswords yes),建议改成no(禁止无密码登录)。
  • PermitRootLogin指定是否允许根用户登录,默认为yesPermitRootLogin yes),建议改成no(禁止根用户登录)。
    • 还有一种写法是写成prohibit-password,表示 root 用户不能用密码登录,但是可以用密钥登录。
    • PermitRootLogin prohibit-password
  • PermitUserEnvironment指定是否允许 sshd 加载客户端的~/.ssh/environment文件和~/.ssh/authorized_keys文件里面的environment= options环境变量设置。默认值为noPermitUserEnvironment no)。
  • Port指定 sshd 监听的端口,即客户端连接的端口,默认是22(Port 22)。出于安全考虑,可以改掉这个端口(比如Port 8822)。
    • 配置文件可以使用多个Port命令,同时监听多个端口。
    • Port 22
      Port 80
      Port 443
      Port 8080
      
    • 上面的示例表示同时监听4个端口。
  • PrintMotd指定用户登录后,是否向其展示系统的 motd(Message of the day)的信息文件/etc/motd。该文件用于通知所有用户一些重要事项,比如系统维护时间、安全问题等等。默认值为yesPrintMotd yes),由于 Shell 一般会展示这个信息文件,所以这里可以改为no
  • PrintLastLog指定是否打印上一次用户登录时间,默认值为yesPrintLastLog yes)。
  • Protocol指定 sshd 使用的协议。Protocol 1表示使用 SSH 1 协议,建议改成Protocol 2(使用 SSH 2 协议)。Protocol 2,1表示同时支持两个版本的协议。
  • PubKeyAuthentication指定是否允许公钥登录,默认值为yesPubKeyAuthentication yes)。
  • QuietModeSSH 1 版本专用,指定日志只输出致命的错误信息(QuietMode yes)。
  • RSAAuthentication指定允许 RSA 认证,默认值为yesRSAAuthentication yes)。
  • ServerKeyBits指定 SSH 1 版本的密钥重新生成时的位数,默认是768(ServerKeyBits 768)。
  • StrictModes指定 sshd 是否检查用户的一些重要文件和目录的权限。默认为yesStrictModes yes),即对于用户的 SSH 配置文件、密钥文件和所在目录,SSH 要求拥有者必须是根用户或用户本人,用户组和其他人的写权限必须关闭。
  • SyslogFacility指定 Syslog 如何处理 sshd 的日志,默认是 Auth(SyslogFacility AUTH)。
  • TCPKeepAlive指定打开 sshd 跟客户端 TCP 连接的 keepalive 参数(TCPKeepAlive yes)。
  • UseDNS指定用户 SSH 登录一个域名时,服务器是否使用 DNS,确认该域名对应的 IP 地址包含本机(UseDNS yes)。打开该选项意义不大,而且如果 DNS 更新不及时,还有可能误判,建议关闭。
  • UseLogin指定用户认证内部是否使用/usr/bin/login替代 SSH 工具,默认为noUseLogin no)。
  • UserPrivilegeSeparation指定用户认证通过以后,使用另一个子线程处理用户权限相关的操作,这样有利于提高安全性。默认值为yesUsePrivilegeSeparation yes)。
  • VerboseModeSSH 2 版本专用,指定日志输出详细的 Debug 信息(VerboseMode yes)。
  • X11Forwarding指定是否打开 X window 的转发,默认值为 no(X11Forwarding no)。
    • 修改配置文件以后,可以使用下面的命令验证,配置文件是否有语法错误。
    • $ sshd -t
    • 新的配置文件生效,必须重启 sshd。
    • $ sudo systemctl restart sshd

sshd 的命令行配置项

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

  • -d参数用于显示 debug 信息。$ sshd -d
  • -D参数指定 sshd 不作为后台守护进程运行。$ sshd -D
  • -e参数将 sshd 写入系统日志 syslog 的内容导向标准错误(standard error)。
  • -f参数指定配置文件的位置。
  • -h参数用于指定密钥。$ sshd -h /usr/local/ssh/my_rsa_key
  • -o参数指定配置文件的一个配置项和对应的值。$ sshd -o "Port 2034"
    • 配置项和对应值之间,可以使用等号。
    • $ sshd -o "Port = 2034"
    • 如果省略等号前后的空格,也可以不使用引号。
    • $ sshd -o Port=2034
    • -o参数可以多个一起使用,用来指定多个配置关键字。
  • -p参数指定 sshd 的服务端口。
    • $ sshd -p 2034
    • 上面命令指定 sshd 在2034端口启动。
    • -p参数可以指定多个端口。
    • $ sshd -p 2222 -p 3333
  • -t参数检查配置文件的语法是否正确。
下一节:SSH 除了登录服务器,还有一大用途,就是作为加密通信的中介,充当两台服务器之间的通信加密跳板,使得原本不加密的通信变成加密通信。这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。