Erik's Blog

SSH 详解:服务器、客户端和密钥

Linux#SSH

SSH (Secure Shell) 采用的是 非对称密钥系统,即耳熟能详的公钥私钥加密系统,其安全验证又分为 基于口令的安全验证基于密匙的安全验证 两种级别。SSH 为一项创建在应用层和传输层基础上的安全协议,通过 SSH 可以对所有传输的数据进行加密,利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题,也能够防止DNS欺骗和IP欺骗。最近好好研究了下这东西, 做一下记录。

客户端与服务端的通讯认证流程

  1. 双方协商 SSH 版本号和协议, 协商过程数据不加密
  2. 双方协商 RSA/DSA 主机密钥, 数据加密算法, 消息摘要
  3. 客户端根据选择的认证方式发起登录验证申请, 服务端对客户端提供的密码等信息进行校验
  4. 如认证不通过, 则试图进行下一种认证方式的申核, 直到成功/失败, 或者超时
  5. 客户端如果校验成功, 则服务端会创建一个客户端的 session(进程), 同时会转送环境变量, 最后给客户端一个 shell 的机会

GSSAPI 身份验证

GSSAPI (公共安全事务应用程序接口, GSS-API) 以一种统一的模式为使用者提供安全事务, 由于它支持最基本的机制和技术, 所以保证不同的应用环境下的可移植性。 该规范定义了 GSS-API 事务和基本元素, 并独立于基本的机制和程序设计语言环境, 并借助于其它相关的文档规范实现。

  • GSSAPIAuthentication : 是否允许使用基于 GSSAPI 的用户认证, 默认值为 “no”, 仅用于 SSH-2
  • GSSAPICleanupCredentials : 是否在用户退出登录后自动销毁用户凭证缓存, 默认值是 “yes”, 仅用于 SSH-2

打开 GSSAPIAuthentication 配置项会在客户端登录服务端时用 gssapi-keyex/gssapi-with-mic 进行身份校验,同样客户端也要支持这种身份验证。 如果我们不用这种方式进行身份验证的话, 建议关闭这个选项, 这样可以提高验证时的速度。

RSA/DSA 密钥认证

除了可以用 UNIX 密码方式登录系统外,还可以选择 RSA/DSA 密钥认证方式登录系统,这两种加密算法都是非对称加密算法。

  • RSA : 由RSA公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;
  • DSA (Digital Signature Algorithm) : 数字签名算法,是一种标准的 DSS (数字签名标准);

RSA 密钥认证

首先用 ssh-keygen 生成一对 RSA(公/私钥), 用 ssh-copy-id 将公钥 COPY 到 SSH 服务端 最后登录 SSH 服务端进行测试

# 用 rsa 的认证方式生成公/私钥
ssh-keygen -t rsa

# 用 ssh-copy-id 将 id_rsa.pub(公钥) COPY 到 SSH 服务端
ssh-copy-id -i .ssh/id_rsa.pub llissery@llissery.net

# 登录
ssh llissery@llissery.net

我们用 ssh-keygen 生成一只公钥和私钥,将公钥转到远程待登录的服务器,要用 RSA 登录的时候,我们只要在本地的控制台键入 ssh remotehost,这时 :

  1. SSH 告诉 remotehost 的 sshd 它想使用 RSA 认证协议。
  2. remotehost 的 sshd 会生成一个随机数,并用我们先前拷贝过去的公钥对这个随机数进行加密。
  3. sshd 把加密了的随机数发回 clienthost 的 ssh 客户端程序。
  4. 我们的 ssh 用密钥对这个随机数进行解密后,再把它发回给 remotehost。
  5. sshd 得出结论,既然我们持有匹配的专用密钥,就应当允许我们登录。

因此,我们有匹配的专用密钥这一事实授权我们访问 remotehost。

服务端通过下面两个选项来控制是否采用公/密钥的方式进行身份验证 PubkeyAuthentication yes #AuthorizedKeysFile %h/.ssh/authorized_keys, 改成 PubkeyAuthentication no 则关闭公/私钥认证。

DSA 密钥认证

# 生成 DSA 公/私钥
ssh-keygen -t dsa

# 同样将 id_dsa.pub(公钥) COPY到远程服务器
ssh-copy-id -i .ssh/id_dsa.pub llissery@llissery.net

# 登录
ssh -v llissery@llissery.net

如果要关闭用 DSA 公密钥认证的方式, 也要将 PubkeyAuthentication 改成 no。DSA 应用于 ssh v2,而 RSA 在 ssh v1 上也得到支持。

定义用于公/私钥认证的公钥文件物理位置,修改 AuthorizedKeysFile .ssh/authorized_keys

如果采用 RSA/DSA 这种公/私钥认证方式,我们建议这个采用默认配置,而不去更改它,因为 ssh-copy-id 等命令传输到被登录服务器的公钥文件就是 ~/.ssh/authorized_keys

免密码登入

在 RSA/DSA 生成密钥对的时候,不输入口令,直接回车,以这样的密钥对进行登录,将不会提示用户输入密码。

拒绝用 UNIX/password 的方式登录系统

UNIX/password 是传统的认证方式, 我们可以通过 ssh 配置参数拒绝以这种方式登录服务器

  • PasswordAuthentication yes : 默认是 UNIX/password 登录方式是开启的,如果关闭 UNIX/password 登录方式将 yes 改成 no 即可

X11 转发

X11 转发允许在 SSH 客户端上显示应用程序的图形部分,而程序逻辑依然在远程服务器上执行。 通过使用这种方法,用户可以避免通过连接转发整个桌面带来的网络开销,并且仅接收到有关显示部分的内容。 我们需要 SSH 客户端有 X 服务器和 SSH 客户端 (如 Cygwin-X,XmanagerEnterprise 或者是一个 Xwindows),而 SSH 服务端要安装 ssh 服务端以及任何要执行的 x 程序, 如 xclock 或 gnome-terminal 等等。

我们 ssh 客户端执行 : ssh -X llissery@llissery.net gnome-terminal

此时客户端上会弹出一个 gnome-terminal,在 gnome-terminal 执行命令其实就是在服务端上执行。

服务端不一定要进入到 x-windows 里面,但它一定要有 x 客户端程序。

而要完成上面的功能,我们就要保证 X11Forwarding 选项是 yes,X11Forwarding yes 。如果是 X11Forwarding 选项是 no,转发 X11 程序则不会成功。

如果不需要这个功能,建议关闭该选项。

SSH的日志级别

SSH 有 9 个日志级别 : QUIET < FATAL < ERROR < INFO(默认) < VERBOSE < DEBUG = DEBUG1 < DEBUG2 < DEBUG3

建议将日志级别调整为 VERBOSE : LogLevel VERBOSE,这样可以检测对 SSH 服务的探测。

客户端与服务端的环境变量传递

AcceptEnv 指定客户端发送的哪些环境变量将会被传递到会话环境中,但只有 SSH-2 协议支持环境变量的传递。可以使用 *? 做为通配符 AcceptEnv LC* 这样就可以接受所有以 LC 开头的环境变量。

默认是不传递任何环境变量,若要支持环境变量传递,我们要在客户端和服务端都要做相关的配置。

# 传递环境变量 CMD

# 客户端
## 定义环境变量 CMD
declare -x CMD="hostname"
## 在 ssh 客户端配置文件中增加发送环境变量的配置项
vim /etc/ssh/ssh_config
SendEnv CMD

# 服务端
## 在 ssh 服务端配置文件 sshd_config 中增加接收环境变量的配置
vim /etc/ssh/sshd_config
AcceptEnv CMD
## 保存退出
## 重启 ssh 服务
/etc/init.d/ssh restart

# 测试
ssh host
echo $CMD
hostname
$CMD
ssh-server

并不是所有的环境变量都会如我们所希望的那样传递,比如 PATH,原因是在 ssh 登录的时候,系统也会做一些环境变量的设置,这时 PATH 会被改变,而不会是我们发送接受的变量。

AllowUsers/AllowGroups 与 DenyUsers/DenyGroups

AllowUsers 允许指定的用户可以通过 ssh 服务登录该服务器,如果使用了 AllowUsers,则只有 AllowUsers 的用户可以登录服务器,其它用户不能登录服务器。

  • 如果我们使用 PermitRootLogin no (阻止Root用户登录),那样 AllowUsers root 是不会生效的
  • 如果我们使用 DenyUsers 阻止某用户登录,而 AllowUsers 开放某用户登录,则以 DenyUsers 为准
  • 如果我们使用 DenyGroups 阻止某用户组登录,而 AllowUsers 开放某用户登录,也以 DenyGroups 为准
  • 如果增加多个用户,各用户名之间用空格分隔,例如 : AllowUsers root user1 user2

端口转发

AllowTcpForwarding 选项

  • 如果采用本地转发方式,此时服务端 AllowTcpForwarding 选项是 no,则不允许转发。
  • 如果采用远程转发方式,此时客户端 AllowTcpForwarding 选项是 no,则不允许转发。

SSH 有两种端口转发方式,分别是本地转发和远端转发 :

本地转发

ssh 本地转发可以将连接本地端口的 SOCKET 数据转发到远程 SSH 服务端。

一台 SSH 服务端提供 ftp 服务,因为 ftp 传输是明文密码,如果不做 ssh 端口之前,我们可以通过 tcpdump 命令很容易的捕捉到明文信息,所以我们要对21端口进行转发:

ssh -CNf -L 2001:localhost:21 root@llissery.net

  • -C 压缩数据传输
  • -N 不执行脚本或命令,通常与 -f 连用
  • -f 后台认证用户/密码,通常和 -N 连用,不用登录到远程主机

此时我们在客户端连接 localhost 的 2001 端口,ssh 即将数据转发到 ssh 服务端的 21 端口。而如果我们没有使用 SSH 映射的方式进行 FTP 连接,则会产生明文数据。

远程转发

将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口。

在 SSH 服务端执行下面远程转发的命令 ssh -CNf -R 2001:localhost:21 root@client

此时 ssh 远程转发我们的端口。

我们可以选择远程端口转发的方式来绕过防火墙。

远程主机连接本地转发端口

GatewayPorts : 是否允许远程主机连接本地的转发端口,默认值是 no。no 表示仅允许本地连接,yes 表示强制将远程端口转发绑定到统配地址(wildcard address)。

我们通过打开 GatewayPorts 选项,使用我们即可以用回环地址转发,也可以用其它 IP 地址转发,这样就使我们可以通过 ssh 将该服务器做成一个转发机。

我们关闭 GatewayPorts 选项后,只能使用本地连接。

sshd 默认将远程端口转发绑定到 loopback 地址,这样将阻止其它远程主机连接到转发端口。 GatewayPorts 指令可以让 sshd 将远程端口转发绑定到非 loopback 地址,这样就可以允许远程主机连接了。

vim /etc/ssh/ssh_config
GatewayPorts yes

ssh -v -CNf -L 2001:llissery.me:22 root@llissery.net
# llissery.net 为当前客户端的IP,而 llissery.me 是远程 SSH 服务端

# 此时连接本地的 eth1 网卡地址
ssh -p llissery.me

登录时显示的信息

有如下的选项可以控制登录 ssh 时显示的信息

  • Banner

Banner 用于在登录之前显示在用户屏幕上, 如果定义为 none, 则不显示任何信息, 我们可以指定 Banner 为相应的文件

Banner /etc/issue

  • PrintLastLog

PrintLastLog 用于显示在每一次成功登录后显示最后一位用户的登录信息

PrintLastLog yes

  • PrintMotd

PrintMotd 用于显示在每一次成功登录后显示 /etc/motd 中的信息

  • ShowPatchLevel

ShowPatchLevel 用于在连接 ssh 端口时, 是否返回 SSH 的补丁版本信息

我们建议如下的设置

  1. Banner : /etc/issue, /etc/issue放入警告信息
  2. PrintMotd yes : 在 /etc/motd 放入登录后的欢迎信息
  3. ShowPatchLevel no : 不显示 ssh 的补丁信息
  4. PrintLastLog no : 不显示最后一次的登录信息

数据加密算法

我们可以通过 Ciphers 配置项来选择数据加密算法,如果服务端仅支持 aes128-cbc, 而客户端指定用 arcfour 加密算法连接登录服务端则不会成功。 sshv2 支持如下的加密算法,相同默认值也是如下的算法 : aes128-cbc / aes192-cbc / aes256-cbc / aes128-ctr / aes192-ctr / aes256-ctr / 3des-cbc / arcfour128 / arcfour256 / arcfour / blowfish-cbc / cast128-cbc

上面的这些算法都是对称加密算法 / 而 arcfour 是最快的, 这里的 arcfour 算法也就是 rc4。

arcfour(rc4) 对称加密算法的说明:

会话密钥的前 16 个字节被服务器用作加密密钥,紧接着的下一个 16 字节被客户端用作加密密钥,结果是两个数据流方向上有两个独立的 129 位密钥。这种加密算法非常快。

如果我们没有指 Ciphers,将支持所有的加密算法,而客户端没有指定加密算法的话,我们首先使用的将是 aes128-ctr 对称加密算法。 如果我们在服务端同时指定 Ciphers arcfour,blowfish-cbc,aes128-ctr,而优先使用 aes128-ctr 其次是 blowfish-cbc,最后是 arcfour。

我们建议在服务端的 ciphers 选项上仅指定 arcfour算法,这样能最优化的进行数据加密传输。

使用 login 程序登录

UseLogin 默认值是 “no”, 如果指定 UseLogin yes, 我们将在登录的过程中使用 ssh 服务端的 login 程序进行登录验证。

超时断开

可以通过 ClientAliveCountMaxClientAliveInterval 两个选项控制客户端在无响应的情况下断开连接。

  • ClientAliveCountMax : sshd 在未收到任何客户端回应前最多允许发送多少个 “alive” 消息,到达这个上限后,sshd 将强制断开连接,关闭会话。

alive 消息与 TCPKeepAlive 有很大差异。alive 消息是通过加密连接发送的,因此不会被欺骗,而 TCPKeepAlive 却是可以被欺骗的。 如果 ClientAliveInterval 被设为 15 并且将 ClientAliveCountMax 保持为默认值(3),那么无应答的客户端大约会在 45 秒后被强制断开,这个指令仅可以用于 SSH-2 协议。

  • ClientAliveInterval : 设置一个以秒记的时长,如果超过这么长时间没有收到客户端的任何数据,sshd 将通过安全通道向客户端发送一个 alive 消息,并等候应答。默认值 0 表示不发送 alive 消息,这个选项仅对 SSH-2 有效。

host-based 验证

我们这里看到了另外一种验证 (此前我们接触了password,rsa/dsa,GSSAPI 等三种验证方式),这种验证方式基于主机名和公/私钥。其中 host-based 验证是基于 ssh-v2。

# 首先我们要在客户端/服务端加入对方的主机名及 IP 对映
## 服务端
vim /etc/hosts
192.168.27.142  ssh-server      # Added by NetworkManager
192.168.27.143  ssh-client      # Added by NetworkManager

## 客户端
vi /etc/hosts
192.168.27.142  ssh-server      # Added by NetworkManager
192.168.27.143  ssh-client      # Added by NetworkManager

# 修改服务端的 ssh 配置
vim /etc/ssh/sshd_config

## 打开 host_based 的验证
HostbasedAuthentication yes

## 不允许忽略 ~/.ssh/known_hosts
IgnoreUserKnownHosts no

## 不允许忽略 ~/.shosts
IgnoreRhosts no


# 在服务端生成客户主机的密钥对
ssh-keyscan -t rsa,dsa ssh-client > ~/.ssh/known_hosts

# 将客户端主机名写入到用户主目录的 .shosts 文件中
vim ~/.shosts
ssh-client

# 重启 ssh 服务端
/etc/init.d/sshd restart


# 在客户端修改 ssh 配置
vi /etc/ssh/ssh_config

## 打开客户端的 host_based 验证
HostbasedAuthentication yes
EnableSSHKeysign yes

注意 : 通过 hostbased 方式验证要保证登录的客户端的用户 UID 与服务端的 UID 一致

我们建议关闭 hostbased 和 rhostsrsa 验证方式

HostbasedAuthentication no IgnoreUserKnownHosts yes IgnoreRhosts yes

SSH的协议 v1/v2

我们现在一般都使用 SSH-v2,只有在比较老的系统上会看到仅支持 ssh-v1,或一些网络设备

可以调整SSH服务,支持 ssh-v1 : Protocol 1

下面两个选项是只在 ssh-v1 下有用 : RSAAuthentication RhostsRSAAuthentication

建议仅使用 ssh-v2,同时关闭 RSAAuthentication/RhostsRSAAuthentication : Protocol 2 RhostsRSAAuthentication no RSAAuthentication no

认证时限,未认证连接与认证次数

我们可以通过 MaxStartups 选项对未认证连接的个数进行调整 一个 ssh 的登录,在没有成功验证前,也是一个未认证连接

MaxStartups 10 表示可以有 10 个 ssh 的半连接状态,这个选项一定要配合 LoginGraceTime 选项一起使用。

LoginGraceTime 表示认证的时限,我们可以调整认证的时间限制,例如 : LoginGraceTime 20 即在 20 秒之内不能完成认证,则断开。 注意在这里如果密码输入错误,则重新计时,如果我们输错了密码,计时将重新开始,幸运的是我们有 MaxAuthTries,来解决认证次数的问题。MaxAuthTries 1 : 这里表示只允许输错一回密码。

我们要注意的是除了 SSH 自身的选项控制认证次数外,它还通过 pam 进行验证,所以如果我们设置 MaxAuthTries 10,则允许输错密码的次数可能还是 3,如果 MaxAuthTries 2,则以 MaxAuthTries 为准。

DNS反向解析

UseDNS 选项来决定是否对远程主机名进行反向解析,以检查此主机名是否与其 IP 地址真实对应,默认值为 yes。

用 strace 对 sshd 登录服务时进行系统调用跟踪,我们发现如果采用 UseDNS yes,客户端登录时,SSH 服务端将会打开 /etc/hosts,找对映的 ip/hostname 的解析记录,如果没有找到,这时将会用利用 /lib/libnss_dns.so.2 动态链接库去 /etc/resolv.conf 中找 DNS 服务器做反向解析查询。这是根据 /etc/host.conf 中配置的解析顺序(hosts/bind)来的,如果 /etc/hosts 中有解析记录,则不会通过 /etc/resolv.conf 中的 DNS 进行反向解析。 如果我们关闭反向解析查询,即 UseDNS = no,此时则不会用 /etc/host.conf 等文件进行 hosts/bind 反向解析查询。

我们建议使用 UseDNS no,因为这样效率更高。

macs 消息摘要算法

指定允许在 SSH-2 中使用哪些消息摘要算法来进行数据校验。

可以使用逗号分隔的列表来指定允许使用多个算法,默认值(包含所有可以使用的算法)是:hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96

Hash 信息验证码 HMAC(Hash message authentication codes) 验证接收消息和发送消息的完全一致性(完整性)。这在数据交换中非常关键,尤其当传输媒介如公共网络中不提供安全保证时更显其重要性。 HMAC 结合 hash 算法和共享密钥提供完整性。 Hash 散列通常也被当成是数字签名,但这种说法不够准确,两者的区别在于 : Hash 散列使用共享密钥,而数字签名基于公钥技术。

hash 算法也称为消息摘要

  • 双方必须在通信的两个原头处各自执行 Hash 函数计算
  • 使用 Hash 函数很容易从消息计算出消息摘要,但其逆向反演过程以目前计算机的运算能力几乎不可实现

有两种最常用的 hash 函数 :

  • HMAC-MD5 : MD5 (消息摘要5) 基于 RFC1321。MD5 对 MD4 做了改进,计算速度比 MD4 稍慢,但安全性能得到了进一步改善。MD5 在计算中使用了 64 个 32 位常数,最终生成一个 128 位的完整性检查和。
  • HMAC-SHA : 安全 Hash 算法定义在 NIST FIPS 180-1,其算法以 MD5 为原型。SHA 在计算中使用了 79 个 32 位常数,最终产生一个 160 位完整性检查和。SHA 检查和长度比 MD5 更长,因此安全性也更高。

说到底 MACs 就是用于确保双方数据传输的完整性。

SSH 服务端提供可以使用的消息摘要算法,由客户端指定要使用哪种消息摘要。

建议使用 hmac-md5

authorized_keys 的权限检查

StrictModes 指定是否要求在接受连接请求前对用户主目录和相关的配置文件进行宿主和权限检查。

我们首先采用公/私钥的方式进行验证,同时打开 strictmodes 选项 : strictmodes yes

此时 SSH 服务端的 authorized_keys 文件的权限是 400。 我们将 SSH 服务端的 authorized_keys文件的权限改为 777,此时不能再通过公/私钥的方式进行验证。

强烈建议使用默认值 yes 来预防可能出现的低级错误。

阻止 root(uid=0) 用户使用 ssh 远程登录

PermitRootLogin 选项改为 no,即可阻止 root 用户远程登录,默认是 : PermitRootLogin yes 如果调整为 : PermitRootLogin without-password,则可以用 root 用户访问 ssh 服务端,但前提是使用公/私钥的方式访问,而不能是 password 的认证方式。

不允许 root(uid=0) 空口令登录系统

PermitEmptyPasswords 选项改为 no,即可阻止 root 用户以空口令的方式登录,默认为 no。

挑战应答验证

ChallengeResponseAuthentication 改为 no 则关闭挑战应答验证。

建议将挑战应答验证方式关闭 : ChallengeResponseAuthentication no

分离特权

UsePrivilegeSeparation 改为 yes 即客户端连接 ssh 服务端时,SSH 服务端通过创建非特权子进程处理接入请求的方法来进行权限分离,默认值是 “yes”。 这样做的目的是为了防止通过有缺陷的子进程提升权限,从而使系统更加安全。

使用 PAM

在 SSH 服务端使用 UsePAM yes,则 ssh 服务端会加载 /etc/pam.d/sshd

开启压缩选项

我们可以打开 Compression 选项 : Compression yes

SSH 监听端口

可以指定 ssh 监听的端口,使用 Port 选项,也可以多次使用 Port,来指定多个端口 : Port 22 Port 56000

建议使用一个 1024 端口以上的 SSH 绑定端口,如 54321 等。

SSH 的网络接口

以指定要绑定的网络接口,使用 ListenAddress

默认是监听所有接口,我们给它绑定到 eth1(192.168.27.142) : ListenAddress 192.168.27.142

建议绑定到内网通讯的网卡地址,而不是公网地址。

SSH 的协议族

我们可以指定 SSH 的协议族,使用的是 AddressFamily,默认是使用所有协议族 any,我们还可以指定 inet(ipv4),inet6(ipv6)。

外部子系统

我们可以配置一个外部的子系统,仅用于 SSH-V2 协议,一般这里使用 sftp : Subsystem sftp /usr/libexec/openssh/sftp-server,如关闭该选项,将无法使用 sftp。

设定主机的私钥文件

在 ssh 中可以用 HostKey 指定主机的私钥文件,如不指定则无法启用 ssh 服务,默认的是如下的配置:

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key

我们看到这里支持两个非对称加密算法,分别是 rsa 和 dsa。 事实上在进入身份验证之前,客户端要与服务端确认服务端的公/私钥是否改变过, 即客户端会用服务端主机公钥对一段消息进行加密,而服务端会用自己的主机密钥进行解密。 从而校验数据,达到主机身份确认的效果。

如果主机被重装过,或重新生成了新的 RSA/DSA 密钥,则登录该主机时会重新在客户端生成公钥并写入到 ~/.ssh/known_hosts

Kerberos 的身份验证

Kerberos 是针对分布式环境而设计的,如果不需要可以关闭这种身份验证方式。

建议如下的配置 : kerberosauthentication no kerberosorlocalpasswd no kerberosticketcleanup yes

SSH 客户端的配置项

  • ConnectTimeout : ConnectTimeout 3 等待 3s 客户端发现 SSH 服务端 timeout 后, 可以在指定的秒数后断开连接, 避免不必要的等待

  • Compression : 有关于客户端的 SSH 压缩设定, 在客户端如果设定 Compression yes, 则表示支持压缩, 压缩会提高网络吐吞量, 但会增加CPU的消耗。 如果客户大量使用 gzip 对数据压缩后再通过 scp 传输, 则 ssh 的 compression 并不会有任何效果, 反而会降纸网络吐吞量,同时 SSH V2 中也不支持压缩级别。

  • 使用身份验证方式的优先顺序 : PreferredAuthentications, 如果我们优先使用 password, 那么可以设定如下的配置 : PreferredAuthentications password,publickey,keyboard-interactive

  • CheckHostIP yes : 我们可以设定 CheckHostIP 选项防止 DNS 欺骗

  • 处理 known_hosts 的三种方式

当用 ssh 连接对方的主机时,如果 known_hosts 中没有对方主机的公钥,则会看到一个加入主机公钥确认身份的提示信息,这是因为客户端配置了 StrictHostKeyChecking ask 造成的。

我们可以调整 StrictHostKeyChecking 选项为 no,这样会把对方的公钥直接加入到 known_hosts 文件中。 如果调整 StrictHostKeyChecking 选项为 yes,这样直接拒绝加入对方的公钥,需要手工来填加。

  • known_hosts 的两种文件格式 : 一种是主机名(IP)明文存放的格式, 一种是主机名(IP)被哈希过的格式

我们可以通过 HashKnownHosts 这个选项来调整 : HashKnownHosts yes。明文存放的格式可以看到里面包括了主机名及非对称加密的算法,如果是哈希过的格式,看不到主机名,但可以看到使用的非对称加密算法。

建议的配置

我们对整篇文章做了整理, 建议用如下的配置, 首先是 SSH 服务端的配置

####################################
#仅使有Protocol 2
#绑定到56000端口
#绑定到内网IP
####################################
Protocol 2
Port 56000
ListenAddress 192.168.27.141


####################################
#以下两项配置仅用于Protocol 1
####################################
RhostsRSAAuthentication no
RSAAuthentication no

####################################
#关闭Kerberos身份验证
####################################
kerberosauthentication no
kerberosorlocalpasswd no
kerberosticketcleanup yes

####################################
#关闭挑战/响应身份验证(s/key)
####################################
ChallengeResponseAuthentication no

####################################
#关闭GSSAPI身份验证
####################################
GSSAPIAuthentication no
GSSAPICleanupCredentials yes

####################################
#关闭公/私钥身份验证
####################################
PubkeyAuthentication no
AuthorizedKeysFile      .ssh/authorized_keys

####################################
#关闭基于主机的身份验证
####################################
HostbasedAuthentication no
IgnoreUserKnownHosts yes
IgnoreRhosts yes

####################################
#开启unix/password身份验证
####################################
PasswordAuthentication yes


####################################
#关闭X11转发
#关闭除loopback外的其它网络接口转发
#关闭tcp端口转发
####################################
X11Forwarding no
GatewayPorts no
AllowTcpForwarding no


####################################
#日志级别调整为VERBOSE,默认为INFO
#日志Facility为AUTH
####################################
LogLevel VERBOSE
SyslogFacility AUTH


####################################
#关闭SSH客户端与服务端的变量转递
####################################
AcceptEnv none

####################################
#拒绝系统用户通过SSH登录
####################################
AllowUsers *
DenyUsers daemon bin sys sync games man lp mail news uucp proxy www-data backup list irc gnats nobody Debian-exim statd identd sshd libuuid snmp

####################################
#登录警告信息
#登录欢迎信息
#关闭SSH的补丁版本号
#关闭显示最后一次登录的信息
####################################
Banner /etc/issue
PrintMotd yes
ShowPatchLevel no
PrintLastLog no

####################################
#指定支持的数据对称加密算法
#指定支持的消息摘要算法
####################################
ciphers aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr,3des-cbc,arcfour128,arcfour256,arcfour,blowfish-cbc,cast128-cbc
macs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96

####################################
#每300秒向客户端发送一次alive消息,判断是否存活,如两次均检测失败,则断开与客户端的连接
#关闭tcpkeepalive
####################################
clientaliveinterval 300
clientalivecountmax 2
tcpkeepalive no

####################################
#允许有1000次验证连接请求,如20秒不能完成校验,则断开验证连接请求
#有三次密码验证机会
####################################
MaxStartups 1000
LoginGraceTime 20
MaxAuthTries 3

####################################
#支持压缩选项,从而提高数据通讯速度
#关闭DNS反向解析,从而提高验证速度
#支持PAM,从而支持可插入的安全模块,加载安全配置,如limit.conf等
####################################
Compression yes
UseDNS no
UsePAM yes

####################################
#如其它用户有读取authorized.keys的权限,则拒绝连接
#拒绝root用户登录
#拒绝空口令的身份验证
#用户验证时进程分离,ssh启用setuid切换到sshd用户启动验证进程
#拒绝在SSH验证结束后使用/bin/login程序
####################################
strictmodes yes
PermitRootLogin no
PermitEmptyPasswords no
UsePrivilegeSeparation yes
UseLogin no

####################################
#支持sftp子系统
####################################
Subsystem sftp /usr/lib/openssh/sftp-server

####################################
#SSH的pid文件存放位置/var/run/
####################################
PidFile /var/run/sshd.pid

####################################
#主机的私钥存放位置
####################################
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key


下面是客户端的配置,如下:
#######################################
#针对所有主机的配置
#######################################
Host *

#######################################
#支持所有协议族
#支持SSHv2/v1,优先使用SSHv2
#ssh连接目标主机的22端口
#######################################
AddressFamily any
Protocol 2,1
Port 22


#######################################
#日志级别为VERBOSE
#关闭批处理登录方式
#防止DNS欺骗
#不检查known_hosts中主机公钥的正确性
#允许连接1024以下的端口
#允许三次尝试密码登录
#######################################
LogLevel VERBOSE
BatchMode no
HashKnownHosts yes
CheckHostIP yes
StrictHostKeyChecking no
NumberOfPasswordPrompts 3

#######################################
#仅使用hmac-md5做为消息摘要算法
#仅使用arcfour(rc4)做为数据加密算法
#######################################
MACs hmac-md5
Ciphers arcfour

#######################################
#仅在protocol 1使用
#######################################
RhostsRSAAuthentication no
RSAAuthentication no


#######################################
#关闭挑战响应身份验证(s/key)
#######################################
ChallengeResponseAuthentication no

#######################################
#关闭基于主机的身份验证
#######################################
HostbasedAuthentication no
EnableSSHKeysign no
NoHostAuthenticationForLocalhost no

#######################################
#关闭GSSAPI身份验证
#######################################
GSSAPIAuthentication no
GSSAPIDelegateCredentials no
GSSAPIKeyExchange no
GSSAPITrustDNS no

#######################################
#关闭公/私钥身份验证
#######################################
PubkeyAuthentication no

#######################################
#开启unix/password身份验证
#######################################
PasswordAuthentication yes

#######################################
#优先使用password身份验证
#######################################
PreferredAuthentications password


#######################################
#连接SSH服务端,发现timeout,3秒后强制断开连接
#每300秒向SSH服务端发送1次alive消息
#如果两次alive消息都没有到达目的主机则断开连接
#因为使用serveraliveinterval,所以关闭tcpkiipalive
#######################################
ConnectTimeout 3
serveraliveinterval 300
serveralivecountmax 2
tcpkeepalive no

#######################################
#关闭对X11的端口转发
#关闭除loopback外的其它网络接口转发
#关闭转发代理
#关闭ssh tunnel
#######################################
ForwardX11 no
ForwardX11Trusted no
GatewayPorts no
ForwardAgent no
tunnel no


#######################################
#开启压缩选项,级别为6
#######################################
Compression yes

#######################################
#以下选项仅在protocol 1支持
#######################################
CompressionLevel 1
ConnectionAttempts 1