Linux【7】-8-远程连接-2-ssh

一、安装软件包

事实上,在我们使用的 CentOS 6 当中,SSH 所需要的所有软件包默认就 已经安装好了。其中包含了 openssh(核心文件)、openssh-clients(SSH 客户端) 和 openssh-server(SSH 服务器端)。我们可以用 yum 命令进行查看来确认这 些软件包都已经被安装好了。

[root@localhost ~]# yum list installed openssh*

如果没有安装,则

[root@localhost ~]# yum install openssh

二、启动服务

openssh-server 的守护程序名为 sshd。sshd 在系统启动时由启动脚本 (/etc/init.d/sshd)自动启动。我们可以用“chkconfig –list” 命令列出系统服务 列表,找到 sshd,一般来说其状态应该如下所示:

查看sshd的状态:

service sshd status

[root@localhost ~]# chkconfig --list|grep sshd
sshd 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭
# 表示 sshd 在运行级别 2、3、4 和 5 都是开机自动启动的(运行级别的解释可参考错误!
未找到引用源。)
[root@localhost ~]#

当然,如果你的系统上 ssh 服务没有开机自动启动的,那么只要简单用如下 chkconfig 命令让其在相应运行级别开机自启动就可以了。

[root@localhost ~]# chkconfig - -level 2345 sshd on

也可以使用 service 命令或者使用/etc/init.d/sshd 脚本手动启动/停止/重启 SSH 服务等操作。

三. 开放端口

最后,我们需要确认系统防火墙(iptables)是否开放了 SSH 服务的 22 端口。第 3 行所示,那么就表示 SSH 服务的 22 端口正常开放,否则就需要用 vi 打开 iptables 的配置文件/etc/sysconfig/iptables 添加该行,然后重启防火墙服务 即可。

当然也可以直接使用 CentOS 中提供的伪图形界面防火墙设置工具 system-config-firewall 来设置。

[root@localhost ~]# cat /etc/sysconfig/iptables|grep 22
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
[root@localhost ~]#

至此,SSH 服务器就架设好了,可以接受客户端远程联机请求了。

新增端口

Linux 新增或修改端口(可以打开多个端口)

vim /etc/ssh/sshd_config

#找到#Port 22一段,这里是标识默认使用22端口,修改为如下: 
Port 22 
Port  1234

重启服务:

systemctl restart sshd.service

四. 安全配置

但此时 SSH 服务器并不安全,我们还需要进行一些额外安全配置,使得 SSH 服务器变得更加安全靠谱。

SSH 协议确实是一个安全的协议,但此“安全”指的是 SSH 协议传输 的数据是经过强度较高的加密算法加密的,因此“安全”,这并不等于 SSH 服务本身就是一个安全的服务,一个没有经过良好配置的 SSH 服务器仍是黑客下手的好对象。

安全配置可以分三步走:

  1. SSH 服务器自身安全配置;
  2. 系统防火墙 (tcp_wrappers1)配置;
  3. 通过可靠的手段向用户公布主机指纹。

首先,是通过对 SSH 服务器本身进行配置来提高其安全级别,openssh 的 主要配置文件为和/etc/ssh/sshd_config。OpenSSH 默认 从此文件读取配置信息。用 vim 打开/etc/ssh/sshd_config,我们主要将改动如下 几个配置,通过改动这些配置,我们可以拒绝特定用户联机,并且主动断开长时 间没有动作的客户端:

[root@localhost ~]# vim /etc/ssh/sshd_config

#表示不接受 root 用户远程联机
PermitRootLogin no

#表示不接受口令为空的用户远程联机
PermitEmptyPasswords no

#表示不接受主组为“not_ssh_user”用户远程联机
DenyGroups not_ssh_user

#表示不接受名为“dev”用户远程联机
DenyUsers dev

#表示当客户端 30 秒内没有任何动作,服务器将发送一个 alive 消息给客户端,如果连发 4
#次 alive 消息,客户端仍然没有动作,服务器将断开连接.
ClientAliveInterval 30
ClientAliveCountMax 4
  • 作为管理员,可以考虑将不允许通过 SSH 远程联机的用户归到一个用户组中,然后拒绝这个组远程联机;
  • 同时为了安全起见,可以考虑不允许 root 远程联机,在需要用 root身份进行管理时,通过普通用户远程登录到主机,然后再用“su –root”命令获得 root 权限。

接着,可以用 tcp_wrappers 来指定可以访问 ssh 服务的特定 IP 地址,同时 拒绝其他 IP 地址访问 ssh 服务

首先用 vim 打开/etc/hosts.deny 文件,添加如下行,表示拒绝所有 ssh 连接:

sshd:ALL:deny

/etc/hosts.deny 文件就定义完成了。接下来,打开/etc/hosts.allow 文件,添 加如下行,表示只接受来自 192.168.71.0 网段和地址为 39.187.121.53 主机的 连接。

sshd: 39.187.121.53 192.168.71.0/255.255.255.0:allow

在这里,我们只想让拥有内网 IP(192.168.71.0)和指定的外网 IP (39.187.121.53)的远程终端通过 SSH 登录到服务器,以最大限度减少不安全 因素。

  • 在任何情况下都不能将 SSH 登录权限开放给网络上的所有主机,尤 其是 Internet 上的主机。

最后,管理员可以通过安全渠道(可靠论坛、BBS、电邮或者电话)向终端 用户公布本主机的 SSH 指纹,用户可以比对此公开指纹和登录主机的指纹来确 认主机身份的真实性,以防止遭受中间人(man-in-the-middle)攻击(在任务 2 中会涉及到主机指纹的比对)。

[root@localhost ~]# ssh-keygen -lf /etc/ssh/ssh_host_rsa_key
# 用主机私钥生成主机密钥指纹,注意只有 root 才有读写主机私钥的权限
2048 42:d6:82:81:5d:20:2e:d3:c8:9b:09:e4:91:c1:6f:f4 /etc/ssh/ssh_host_rsa_key.pub
(RSA)
# 42:d6:82:81:5d:20:2e:d3:c8:9b:09:e4:91:c1:6f:f4 就是主机密钥指纹
  • 中间人攻击(Man-in-the-Middle Attack, MITM)是一种由来已久的网 络入侵手段,并且在今天仍然非常见,如 ARP 欺骗、DNS 欺骗等都 是典型的 MITM。简而言之,所谓的 MITM 就是通过拦截通信的双方 正常的网络通信数据,并进行窃取和篡改,而通信的双方却毫不知情。
  • MITM 一般有两种模式:一是当主机 A 和 B 通信时,C 可以拦截 A 的通信数据,假冒 B 与 A 进行通信来窃取 A 的敏感信息,当下常见 的“钓鱼网站”就属于此类 MITM;二是当主机 A 和 B 通信时,被主 机 C 拦截并为其“转发”,而 A、B 之间并没有真正意思上的直接通 信,他们之间的信息传递是通过 C 作为中介来完成的,但是 A、B 没 有意识到,而以为它们之间是在直接通信。这样攻击主机在中间成为 了一个转发器,C 不仅可以窃取 A、B 的敏感信息还可以将这些信息 进行恶意篡改后再传给对方。

五、在 Linux 上用 SSH 客户端远程登录主机

ssh登录提供两种认证方式:口令(密码)认证方式和密钥认证方式。

5.1 口令(密码)

在 Linux 终端上通过 SSH 登录客户端非常简洁,使用的是 openssh-clients (SSH 客户端)这个软件包,使用的命令是 ssh。接下来我们就通过 ssh 来登录 到我们刚刚建立好 SSH 服务器的主机上去。

[root@localhost ~]# ssh stu@192.168.71.128
# 连接到自己本机上面的 ssh 服务
The authenticity of host '192.168.71.128 (192.168.71.128)' can't be established.
# 首次连接主机时会提醒用户确认主机的身份
RSA key fingerprint is 42:d6:82:81:5d:20:2e:d3:c8:9b:09:e4:91:c1:6f:f4.
#通过主机 RSA 公钥生成的主机指纹
Are you sure you want to continue connecting (yes/no)? yes
# 填入完整的 yes(而不是 y)来同意连接主机
Warning: Permanently added '192.168.71.128' (RSA) to the list of known hosts.
#记录下主机的公钥,以便于下次连接时进行指纹比对
stu@192.168.71.128's password: #输入用户口令
Last login: Fri Feb 8 16:42:44 2013 from localhost
[stu@localhost ~]$ exit #如果离开终端,要及时登出
logout
Connection to 192.168.71.128 closed.
[root@localhost ~]#

你可能注意到了在登录过程中,在输入用户口令之前,会出现了一个奇怪的 “ The authenticity of host ‘192.168.71.128 (192.168.71.128)’ can’t be established.(主机 192.168.71.128 的真实性无法确实)”的提示,并且在后面 还给出了一个所谓的“RSA key fingerprint(RSA 密钥指纹)”,你只有输入了 “yes”确认要登录此主机后才能继续输入用户口令。

  • 事实上,这是一种中间人攻击防护措施。SSH 客户端在首次远程连 接 SSH 服务器的时候,客户端将获取服务器上的主机公钥并保存在 客户端相关文件中,并通过该主机公钥生成一个主机指纹(一串字符) 提示给用户。
  • 此时如果用户知道主机私钥生成的主机指纹(由管理员事先告知或者 自行通过本地登录主机获取),那么你就可以比对这两个指纹是否相 同,如果相同,那么这台主机的身份就是真实无误的,可以键入“yes” 放心登录。如果不相同,那么就要怀疑有其他不怀好意的主机冒充我 们要登录的主机,诱骗我们登录来窃取信息了。此时我们就需要向主 机管理员进行确认后再行登录了。

当然并非每次登录都需要进行主机指纹确认,当客户端成功连接过这台主机 一次后,如果主机指纹此后没有发生变化,那么就不会再给出确认主机指纹的提 示了。

如果你曾经登录过这台主机,但是又让你确认主机指纹,那么就 表示主机指纹发生了变化,可能由以下 3 种情况所导致的:

  • A. 主机重新安装了操作系统或者重新安装了 openssh 服务 器;
  • B. 这台主机可能有多个 IP 地址,这次登录是另外一个 IP 地 址;
  • C. 有其他不怀好意的主机冒充我们要登录的主机,诱骗我们 登录来窃取主机口令。

一般来说,我们碰到的都应该是前两个情况,输入“yes”就行 了,但如果要登录的主机确实很敏感,建议输入“no”,向主机管理员进行确认后再行登录。

5.2 密钥认证

这里介绍密钥认证方式登录到linux/unix的方法。

为了提高主机的安全级别,OpenSSH 可以禁止用户以密码身份认证方式登录, 而基于密钥身份认证的方式登录。

1. 禁止用户以密码身份认证方式登录

首先修改 SSH 的配置文件禁止用户以密码身份认证方式登录。打开 /etc/ssh/sshd_config 文件。进行修改,并保存退出

[root@localhost ~]# vim /etc/ssh/sshd_config
#PasswordAuthentication yes #找到这一行,将 yes 改为 no
PasswordAuthentication no #修改后变为此状态,不允许密码方式的登录

在修改完 SSH 的配置文件后,需要重新启动 SSH 服务才能使新的设置生效。

[root@localhost ~]# /etc/rc.d/init.d/sshd restart #重新启动 SSH 服务
Stopping sshd: [ OK ]
Starting sshd: [ OK ]

这时,在远程终端上用 SSH 客户端软件以密码验证身份的的方式就无法登 录主机了。如果用 Linux SSH 客户端登录,会给出“Permission denied”的提示。

[root@localhost ~]# ssh stu@192.168.71.128
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
[root@localhost ~]#

2. 使用密钥登录分为3步

目标:A电脑连接B服务器

  1. A电脑生成密钥(公钥与私钥);
  2. 放置A电脑的公钥(Public Key)到服务器B~/.ssh/authorized_key文件中;
  3. 配置ssh客户端使用密钥登录。

1、在Linux远程服务器生成密钥:

cd ~
ssh-keygen -t rsa -C "youremail@example.com"   # 建立公钥与私钥
 
Generating public/private rsa key pair.
 Enter file in which to save the key (/home/kaz/.ssh/id_rsa):  ← 钥匙的文件名,这里保持默认直接回车
 Created directory '/home/kaz/.ssh'
 Enter passphrase (empty for no passphrase):  ← 输入口令
 Enter same passphrase again:   ← 再次输入口令
 Your identification has been saved in /home/kaz/.ssh/id_rsa.
 Your public key has been saved in /home/kaz/.ssh/id_rsa.pub.
 The key fingerprint is:
 tf:rs:e3:7s:28:59:5s:93:fe:33:84:01:cj:65:3b:8e centosaline @localhost . centosaline .com

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。 如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

  • 作为系统管理员,为了防止别人知道主机用户的密钥,你需要定期地重新生成并分发密钥;
  • 作为系统管理员,需要确保用户授权的密钥文件(.ssh/authorized_keys) 读写权限为 400。这个地方被坑了好久,权限600就够了,但没有权限,一直走不通

2.放置公钥(Public Key)到服务器~/.ssh/authorized_key文件中

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys   # 公钥内容输出到相应文件中

服务器中的authorized_keys可以存放多个Id_rsa,我就有两台电脑连接到服务器上

3.配置ssh客户端使用密钥登录

然后,将私钥通过安全的方式转移到欲通过SSH连接到服务器的PC上。我通过xshel来链接。当然,你也可以用xshell来生成密匙和公匙,然后将公匙放到~/.ssh/authorized_keys。

ssh -p ** qqin@58.**.***.** -i id_rsa

六、在 windows 上用 SSH 客户端远程登录主机

如果使用 Windows 系统,Windows 下默认没有安装支持 SSH 协议的客户 端软件。用户需要自行下载安装。我们推荐使用 PuTTY,这是一款开源的 SSH 客户端软件,能够在多种平台上运行(当然包括 Windows 目前流行的各个版本)。 可以下载到 PuTTY:

打开这个下载页面,我们注意到列出的 PuTTY 相关下载文件总共有 7 个, 这 7 个文件均是可执行文件,分别有不同的用途,其中有 2 个文件是我们必须下 载的:

文件名 用途
PuTTY.exe 远程联机客户端,使用 Telnet 和 SSH 协议(必须)
PSCP.exe SCP 客户端, 命令行下通过 SSH 拷贝文件,类似于Unix/Linux 下的 scp 命令(可选)
PSFTP.exe SFTP 的命令行客户端,类似于 FTP 的文件传输,只不过使用的是 SSH 的 22 端口,而非 FTP 的 21 端口,类似于 Unix/Linux 下的 sftp 命令(可选)
PuTTYtel.exe 远程联机客户端,仅仅使用 Telnet 协议(可选)
Plink.exe 命令行工具,执行远程服务器上的命令(可选)
Pageant.exe PuTTY、PSCP、Plink 的 SSH 认证代理,用这个可以不用每次都输入口令
PuTTYgen.exe RSA 和 DSA 密钥生成工具(必须)
  • 在下载这这两个文件文件后,我们还需要需要要验证下载的文件的完 整性以保证这些下载的文件没有被发布者之外的第三方改动过。可以 下页面上提供的 MD5 文件来进行校验(具体校验方法 可以参考” 1 部署一个好的 Linux 系统 任务 3 获取安装镜像盘”)。
  • PuTTY 是一个准绿色软件,不需要安装。说它绿色是因为直接就能 使用,完全没有任何的安装程序。准绿色是指 PuTTY 的所有配置都 保存到了注册表2。

六、讨论

6.1 集群ssh服务和免密码登录的配置

启动服务

/bin/systemctl start sshd.service

su - sam
ssh-keygen # 在该节点上生成公私

# 将其他服务器的id_dsa.pub写入到该服务器的authorized_keys 。这里需要确保authorized_keys至少为600,否则会没法免密码

## G03上运行
ssh-copy-id -i ~/.ssh/id_dsa.pub C01 # C01节点在该节点上免密登陆(仅限sam用户)
ssh-copy-id -i ~/.ssh/id_dsa.pub G02 # G02点在该节点上免密登陆(仅限sam用户)
# 这样G03就可以免密访问C01和G02了

或者通过 cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys  # 这一步没搞对,可能是authorized_keys权限的问题吧

免密的核心思想就是:

  1. 如果A服务器authorized_keys有B服务器的公钥,那么B服务器可以免密登录A服务器…
  2. 如果自己ssh免密码登陆自己,也是需要将自己的id_dsa.pub 放到自己的authorized_keys中

免密登陆不成功的原因

权限! 权限! 权限!

排查过程:

1.检查AuthorizedKeysFile配置是否启用authorized_keys

root@pts/1 $ cat /etc/ssh/sshd_config |egrep AuthorizedKeysFile
AuthorizedKeysFile    .ssh/authorized_keys

2.没有问题,继续检查.ssh (700) 和 authorized_keys(644) 权限

root@pts/1 $ getfacl /root/.ssh/
getfacl: Removing leading '/' from absolute path names
# file: root/.ssh/
# owner: root
# group: root
user::rwx
group::---
other::---

root@pts/1 $ getfacl /root/.ssh/authorized_keys
getfacl: Removing leading '/' from absolute path names
# file: root/.ssh/authorized_keys
# owner: root
# group: root
user::rw-
group::---
other::---

authorized_keys 权限不对,修改一下chmod 644 authorized_keys

再次尝试结果发现还是不行。但是该设置的权限都设置了。既然.ssh目录和其下文件的权限都OK了,那就检查下其父目录的权限,也就是这里的/root的权限

root@pts/1 $ getfacl /root/
getfacl: Removing leading '/' from absolute path names
# file: root/
# owner: ftpuser
# group: ftpuser
user::r-x
group::r-x
other::---

发现这里/root 的属主都发生了变化。为了不影响别的业务情况,保留这里的ftpuser权限,利用setfacl添加特殊ACL权限

root@pts/1 $ chown -R root:root  /root/
root@pts/1 $ setfacl -m u:ftpuser:rwx /root/

root@pts/1 $ getfacl /root/
getfacl: Removing leading '/' from absolute path names
# file: root/
# owner: root
# group: root
user::rwx
user:ftpuser:rwx        #effective:r-x
group::r-x
mask::r-x
other::r-x

我这里的案例,是/root 的权限变成了 777 ,恐怖。。。 所以就没法用ssh了。。

要点小结,做好笔记:

  • 权限问题
  • /root 700
  • /root/.ssh 700
  • /root/.ssh/authorized_keys rsa_id.pub 644
  • rsa_id权限必须为600
  • 开启文件AuthorizedKeysFile .ssh/authorized_keys

其他需要注意的:

/etc/ssh/sshd_config里面也开启了登陆认证

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys

然后:

service sshd restart

当上面所有情况都核查以后,发现root用户能正常免密登陆,普通用户无法正常免密登陆,最后发现我的普通用户文件放在了NFS上,收到setlinux的影响。

关闭 setlinux

[root@localhost ~]# getenforce     
            如果为disabled 就是已经关闭,如果enforce 就是强制的模式

(1)不重启的头闭 [root@localhost ~]# setenforce 0   #重启电脑后失效
(2)重启电脑的关闭 [root@localhost ~]# vi /etc/selinux/config
        把SELINUX=enforce   改成disabled就可以了,重启电脑,永久生效

或者:

setsebool -P use_nfs_home_dirs 1

其他debug的途径

  • 参看了安全日志/var/log/secure
  • ssh root@ip -vvv

七、报错

7.1 Host key verification failed

[root@www ~]# ssh 205.209.161.**
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
6c:74:2a:d5:ae:2b:76:51:*:*.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending key in /root/.ssh/known_hosts:20
RSA host key for 205.209.161.** has changed and you have requested strict checking.
Host key verification failed.

解决办法:

进入此目录,删除的205.209.161.**相关rsa的信息即可. 或者删除这个文件

cd ~/.ssh/
rm known_hosts

7.2 ssh无法远程连接ubuntu系统,提示"System is booting up. See pam_nologin(8)"

使用ssh(xshell或者putty)远程连接Linux(ubuntu)系统时,提示:

"System is booting up. See pam_nologin(8)"
Connection closing... Socket close.

修改文件: /etc/pam.d/sshd

本地登录后,注释掉 pam_nologin.so 行,命令如下:

sudo sed -i -r 's/^(.*pam_nologin.so)/#\1/' /etc/pam.d/sshd

或者直接用vi打开,找到这行,前边加 # 号,如下:

pam_nologin.so

至此,可以使用ssh进行远程登录了!

7.3 Authentication failed

A节点,自己 ssh A节点,报错 Authentication failed

分析:

  1. 排除ssh文件夹及文件权限的问题

  2. 其他用户都正常

  3. 查看登陆日志 tail /var/log/secure ,定位到问题

    ssh fatal: Access denied for user by PAM account configuration [preauth]

报错原因:

/etc/passwd与/etc/shadow的账号信息不匹配

尼玛,我的这个用户居然是没有设置密码,导致/etc/shadow没有对应的账号,赶紧passwd一下。

7.4 ssh_exchange_identification: read: Connection reset by peer问题

在客户端连接服务端:

[root@foundation66 ~]# ssh root@172.25.254.166
ssh_exchange_identification: read: Connection reset by peer

## -v表示查看连接详细信息
[root@foundation66 ~]# ssh -v root@172.25.254.166

解决方案

在服务端更改配置文件

[root@localhost Desktop]# vi /etc/hosts.allow
#########################
sshd: ALL    ##允许所有ip主机均能连接本机

重启

[root@localhost Desktop]# systemctl restart sshd

测试

[root@foundation66 ~]# ssh root@172.25.254.166
Last login: Wed Jan  9 22:51:17 2019 from 172.25.254.66

7.5 Authentication refused: bad ownership or modes

无法免密登陆,且messages中提示报错信息

[root@g01 log]# tail /var/log/messages

Dec 22 11:40:01 g01 systemd: Started Session 15354 of user root.
Dec 22 11:40:01 g01 systemd: Removed slice User Slice of root.
Dec 22 11:46:18 g01 sshd[94174]: error: Could not load host key: /etc/ssh/ssh_host_dsa_key
Dec 22 11:46:19 g01 sshd[94174]: Authentication refused: bad ownership or modes for directory /mnt/nfs/data/user/dp
Dec 22 11:46:21 g01 sshd[94174]: Accepted password for dp from 192.1 port 41918 ssh2
Dec 22 11:46:22 g01 dbus[44505]: [system] Activating service name='org.freedesktop.problems' (using servicehelper)
Dec 22 11:46:22 g01 dbus[44505]: [system] Successfully activated service 'org.freedesktop.problems'
Dec 22 11:46:49 g01 sshd[94311]: error: Could not load host key: /etc/ssh/ssh_host_dsa_key
Dec 22 11:46:50 g01 sshd[94311]: Authentication refused: bad ownership or modes for directory /mnt/nfs/data/user/dp
Dec 22 11:46:51 g01 sshd[94311]: Accepted password for dp from 192.168.50.78 port 60610 ssh2

sshd为了安全,对属主的目录和文件权限有所要求。如果权限不对,则ssh的免密码登陆不生效。

用户目录权限为 755 或者 700,就是不能是77x。
.ssh目录权限一般为755或者700。
rsa_id.pub 及authorized_keys权限一般为644
rsa_id权限必须为600

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn