SSH服务

ssh: secure shell, protocol, 22/tcp, 安全的远程登录

具体的软件实现:

OpenSSH: ssh协议的开源实现,CentOS默认安装

SSH协议版本

v1: 基于CRC-32做MAC,不安全;man-in-middle

v2:双方主机协议选择安全的MAC方式

基于DH算法做密钥交换,基于RSA或DSA实现身份认证

两种方式的用户登录认证:

基于password

基于key

ssh选项:

-A:开启认证代理连接转发功能;
-a:关闭认证代理连接转发功能;
-b:使用本机指定地址作为对应连接的源ip地址;
-C:请求压缩所有数据;
-F:指定ssh指令的配置文件;
-f:后台执行ssh指令;
-g:允许远程主机连接主机的转发端口;
-i:指定身份文件;
-l:指定连接远程服务器登录用户名;
-N:不执行远程指令;
-o:指定配置选项;
-p:指定远程服务器上的端口;
-q:静默模式;
-X:开启X11转发功能;
-x:关闭X11转发功能;
-y:开启信任X11转发功能。
示例:
ssh 192.168.34.100 -p 22 用ssh连接并指定端口号

ssh加密通讯

基于用户和口令登录验证
1 客户端发起ssh请求,服务器会把自己的公钥发送给用户
2 用户会根据服务器发来的公钥对密码进行加密
3 加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则
用户登录成功

示例:ssh 192.168.34.100  默认以root身份连接对方的主机

当我们第一次连接对方的时候,会出现是否想去连接对方的提示信息,如果选择yes,并输入对方的口令后,就会将对方的公钥文件存到自己/root/.ssh 目录下,此目录下有一个文件名叫konwn_hosts

1)提示是否想要登录对方的主机:

 

 2)/root/.ssh目录下有对方的公钥文件信息:

 ssh服务登录验证

ssh服务登录验证方式:

用户/口令

基于密钥

基于密钥的登录方式

1 首先在客户端生成一对密钥(ssh-keygen)

2 并将客户端的公钥ssh-copy-id 拷贝到服务端

3 当客户端再次发送一个连接请求,包括ip、用户名

4 服务端得到客户端的请求后,会到authorized_keys中查找,如果有响应的IP

和用户,就会随机生成一个字符串。

5 服务端将使用客户端拷贝过来的公钥进行加密,然后发送给客户端

6 得到服务端发来的消息后,客户端会使用私钥进行解密,然后将解密后的

字符串发送给服务端

7 服务端接受到客户端发来的字符串后,跟之前的字符串进行对比,如果一致,

就允许免密码登录

 

 

 

Linux 两台主机之间建立信任(ssh免密登录-即基于Key验证)

背景: 有时候我们在两个主机之间复制文件的时候,提示输入密码,很不方便,那如何免密码复制呢?,就是使用通过linux公钥和秘钥,建立双机信任关系。

在整理之前,我先说下ssh免密码的要点 : 

你想免密码登陆到哪个主机哪个用户, 就把你自己的公钥文件内容追加到远程主机对应用户下的authorized_keys文件中即可,对面如果没有,远程复制过去就会自动创建此authorized_keys文件,并将公钥信息存在里边。

第一种方法:

第一步:先在客户端 创建公私秘钥对ssh-keygen  -t  rsa  -P "" -f /root/.ssh/id_rsa。

[root@centos7~]#ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
Generating public/private rsa key pair.
/root/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:DumaRVWGuR+cJ6cOBWDqHz/2TB67MfvK56Xfwkz8FuM root@centos7.localdomain
The key's randomart image is:
+---[RSA 2048]----+
|      o. oo      |
|     o  +o       |
|    .   .+ .     |
|   .   o. * o    |
|    . = So * .   |
|     + =. o   oo |
|      + =o=  +o.o|
|     + . B.*.o+Eo|
|    o     X*+..o.|
+----[SHA256]-----+

生成的公私钥对在/root/.ssh目录下:文件名分别为id_rsa.pub(公钥)id_rsa(私钥)

第二步:将公钥复制到对方的主机上,默认会在对方/root/.ssh/目录下生成authorized.keys文件。

ssh-copy-id -i /root/.ssh/id_rsa.pub   192.168.34.101   将客户端的公钥传送到服务器端(192.168.34.101为对方IP地址) 其中-i是指定自己当前的路径文件
ssh-copy-id  192.168.34.101   (centos6/7默认会将本地的公钥文件直接复制过去,也可以不需要指定当前的路径和-i)

第三步:

就进行测试客户端连接服务器端的IP地址,就不需要密码登陆:ssh 192.168.34.101

同理将对方的的公钥复制到本机上,对方连本机也不需要输入密码,只需要输入本机私钥的密码即可。

完成免密登录直接可以在对方机器做操作:

如: ssh 192.168.34.100 useradd wang  在对方机器上创建wang账号

 

重要:如果本机已对私钥加密,本地想远程多个主机每次都需要输入私钥密码。

我们可以将其进行托管至代理服务即可,两条命令可以解决,当前托管只记录本次操作的密码,退出代理之后,下次需要再连接时还需要输入私钥口令。

重新设置私钥口令:ssh-keygen  -p,将私钥加密之后再连接需要输入私钥加密口令,比较麻烦:

ssh  192.168.34.100 当前连接远程主机时,会需要输入私钥口令,我们可以进行下面的托管代理操作:

输入托管代理命令之后,就不需要再输入私钥加密口令,具体操作如下:

ssh-agent bash

ssh-add

实操结果:

[root@R1 .ssh]# ssh-agent bash
[root@R1 .ssh]# ssh-add
Enter passphrase for /root/.ssh/id_rsa: 
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
[root@R1 .ssh]# ssh 192.168.34.100
Last login: Tue Oct 22 21:47:24 2019 from 192.168.34.200
[root@centos6~]#

注意:

  • 如果远程主机的端口非22端口,需要指定-p port选项。
  • ssh-copy-id是由openssh-clients包提供,没有这个命令可以安装这个包。

第二种方法: 

1)每个客户端都生成公私钥文件:

ssh-keygen -t rsa -P '' -f /root/.ssh/id_rsa(注:有几个主机,就在每个主机上执行几次)

2)将所有远程机器的公钥都复制到当前本地客户端的文件下authorized_keys(需要新建文件):

机器一进行公钥复制:ssh-copy-id  -i /root/.ssh/id_rsa.pub  192.168.34.100(注:该ip为对方IP地址)

机器二进行公钥复制:ssh-copy-id  -i /root/.ssh/id_rsa.pub   192.168.34.100(注:该ip为对方IP地址)

最后本机将自己的公钥文件也放入到authorized_keys中

ssh-copy-id  192.168.34.100

3)然后将本地的IP地址复制到远程机器上,实现所有的机器都有对方的公钥,也可以进行登录不需要秘钥登录:

ssh-copy-id    机器一的IP地址

ssh-copy-id   机器二的IP地址

最终结果:本地机器与其他主机连接就会免密登录,远程主机与本地主机连接也会免密。

 

实现一个循环创建秘钥对并将公钥传送到对方的脚本:

其中每个机器上都有wang账号且密码都一样,然后可以执行以下命令进行批量创建用户公私钥对,且将本地的公钥都会复制到对方的/roo/.ssh/authorized_keys目录下,

然后就可以通过ssh远程连接不需要进行输入密码连接:

查看当前iplist.txt的IP地址:

[root@centos6html]#cat iplist.txt
192.168.34.100
192.168.34.101
192.168.34.200

vim  ip.sh   书写脚本文件

#!/bin/bash
user=wang
password=centos
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa

while read ip ;do
expect <<EOF
set timeout 10
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect eof
EOF
done < iplist.txt

 bash  ip.sh 脚本执行成功后,就会生成公私钥对,并传递到其他机器上。

试验一:

 

试验二:

 

SSH端口转发:

1、SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是,SSH

还能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的
加密及解密服务。这一过程也被叫做“隧道”(tunneling),这是因为 SSH 为
其他 TCP 链接提供了一个安全的通道来进行传输而得名。例如,Telnet,SMTP,
LDAP 这些 TCP 应用均能够从中得益,避免了用户名,密码以及隐私信息的明文
传输。而与此同时,如果工作环境中的防火墙限制了一些网络端口的使用,但是
允许 SSH 的连接,也能够通过将 TCP 端口转发来使用 SSH 进行通讯
2、SSH 端口转发能够提供两大功能:

  • 加密 SSH Client 端至 SSH Server 端之间的通讯数据
  • 突破防火墙的限制完成一些之前无法建立的 TCP 连接

本地转发:

-L localport:remotehost:remotehostport sshserver

 选项:

  • -f 后台启用
  • -N 不打开远程shell,处于等待状态
  • -g 启用网关功能

示例
ssh -L 9527:telnetsrv:23 -Nfg sshsrv
telnet 127.0.0.1 9527
当访问本机的9527的端口时,被加密后转发到sshsrv的ssh服务,再解密被转发
到telnetsrv:23
data <-->localhost:9527 <-->localhost:XXXXX <-->sshsrv:22 <-->
sshsrv:YYYYY<-->telnetsrv:23

 实验一:

安装telnet软件:进行跳板机实验(SSH端口本地转发功能)

centos6 打开telnet功能:

yum install telnet-server   安装telnet

chkconfig telnet  on 打开telnet功能

service xinetd start   打开xinetd功能

centos7:打开telnet功能

yum instlal telnet-server 

systemctl start telnet.socket

模拟情况:

C:模拟telnet服务端

B:模拟ssh服务端

A:模拟客户端

telnet服务端拒绝客户端的访问:C拒绝A访问

流程解释:
    数据一旦被telnet打开以后,数据会发送到本机9527端口,再在本机开一个随机端口,充当ssh客户端,再把数据流量发送到22端口的ssh服务端,收到数据以后,解密数据,临时开一个随机端口充当客户端,再把流量发送到23端口telnet服务端

 

 

 

1)在telnet服务端执行防火墙阻挡功能,阻挡客户端访问:C拒绝A

iptables -A  INPUT -s 192.168.34.101 -j REJECT 

2)我们要查看自己和服务端哪些端口未被占用,在A主机找一个未用的端口进行绑定,此时,9527端口未被使用:

第一种连接方式:


[root@centos7~]#ssh -L 9527:192.168.34.100:23 -Nf 192.168.34.200  在A执行此命令,打开B主机上未被占用的端口9527,然后A通过此9527端口连接B服务器最后再到telnet端。
-f 是后台执行,不加-f就会前台执行。
[root@centos7~]#telnet 127.0.0.1 9527    在A上执行telnet连接操作,并输入指定的9527端口号
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
CentOS release 6.10 (Final)
Kernel 2.6.32-754.el6.x86_64 on an x86_64
centos6.10.localdomain login: 用户名
Password: 密码
Last login: Thu Oct 24 20:56:12 from 192.168.34.200 #以显示连接到C服务器的机器是B,但实际是从A主机将9527端口转发连接到C服务器
[liu@centos6~]$

第二种连接方式:

ssh -L 9527:192.168.34.100:23 -fNg 192.168.34.200  在A机器上打开B机器的9527端口,在B机器搭上隧道。
telnet 192.168.34.101 9527 在A机器上通过端口9527,连接C机器

 在C机器上查看当前连接的信息:

[root@centos6~]#ss -nt
State Recv-Q Send-Q Local Address:Port Peer Address:Port 
ESTAB 0 52 192.168.34.100:22 192.168.34.1:49369 
ESTAB 0 0 192.168.34.100:23 192.168.34.200:53668  (其中100:23位telnet服务器端IP和23端口,200:53668为ssh服务端的IP和随机端口)

结论:当客户端打开9527端口,请求到ssh协议封装将数据报文发送给ssh服务器端,然后在ssh服务器端上解封装,开启随机端口将数据报文传给telnet服务器,telnet服务器最终得到数据,实现客户端连接telnet服务器端。

注意:虽然能通过跳板机连接到telnet服务器,但是外部机器连接内部机器时,一般防火墙不会打开22端口,客户端无法到达服务端,最终无法连接telnet端的服务。

 

远程转发:
-R sshserverport:remotehost:remotehostport sshserver
示例:
ssh -R 9527:telnetsrv:23 -Nf sshsrv
让sshsrv侦听9527端口的访问,如有访问,就加密后通过ssh服务转发请求到本
机ssh客户端,再由本机解密后转发到telnetsrv:23
Data<--> sshsrv:9527 <--> sshsrv:22 <--> localhost:XXXXX <-->
localhost:YYYYY<-->telnetsrv:23

一般防火墙从外部到内部会阻止访问,但从内部到外部不会阻止访问:

远程转发实验:

三台机器:C:服务器,B:跳板机(ssh服务器),A:客户端

C服务器只允许telnet连接(23端口)访问,不允许外部客户端直接访问,B跳板机是一个ssh服务器;有一个用户需要从外部连接到企业内部的C服务器。

模拟:C 不允许A访问:

当前模拟telnet服务端阻挡服务端访问:

在C执行防火墙阻挡A:

iptables -A  INPUT -s 192.168.34.101 -j REJECT 

[root@b~]#ssh -R 9527:192.168.34.100:23 -Nf 192.168.34.101  #在B机器上后台打开A主机的9527端口
root@192.168.34.101's password:  #输入本机密码验证
[root@b~]#

[root@centos7~]#telnet 127.0.0.1 9527    #在A机器上用telnet连接本地IP地址和9527端口,可以远程访问到内部C服务器
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
CentOS release 6.10 (Final)
Kernel 2.6.32-754.el6.x86_64 on an x86_64
centos6.10.localdomain login: wang
Password: 
Last login: Sun Oct 27 11:42:33 from 192.168.34.200 #此时已经连接到C主机,并显示连接C主机是从跳板机B连接的。
[wang@centos6~]$

 总结:客户端打开9527端口走ssh协议将数据报文封装,发送到跳板机,跳板机解封装报文得到数据,跳板机开启一个随机端口,发送数据报文到telnet服务端,实现外部的客户机通过内部跳板机连接到telnet服务器。

注意:防火墙只会阻挡从外部到内部的端口连接,不会阻挡从内部到外部的端口,现实生产中比较实用,省去了重新设置防火墙的时间。

 

另一种远程端口转发情况:外部有一个客户端(A)连接外部的服务端(B),然后再通过服务端连接内部的跳板机(ssh服务器C),最后到达telnet服务端(D),此处可以将外部客户端和服务端作为

一个堡垒机,内部的ssh服务器和telnet服务器可以看做是一个堡垒机,具体连接情况如下:

1)需要将外部客户端(A)的ssh配置文件打开:

vim /etc/ssh/sshd_config

修改里边的文件gateway no 改为yes,然后重启ssh服务,systemctl  restart sshd

2)ssh -R 9527:192.168.34.100:23 -fNg 192.168.34.101   ssh服务器端(C)输入当前的命令,将A客户端的9527端口打开,开启后台隧道。

3)telnet 192.168.34.101  9527   在外部客户端(A)输入自己的本地IP也可以连接到telnet服务端(D)。

 

SSH动态端口转发:(合理上国外网站)

客户端---->代理服务器----->国外网站

 模拟:

A: 本地机器

B: 代理客户端

C: 外国网络

当用firefox访问internet时,本机的9527端口做为代理服务器,firefox的访问请求被转发到sshserver上,由sshserver替之访问internet

以下为搭建A访问C的过程:

实现Linux主机通过代理进行访问国外网站:

  iptables -A  INPUT -s 192.168.34.101 -j REJECT   设置C阻挡A模拟。
  echo www.google.com > /var/www/html/index.html  在C建立google网站,访问此google网站实验
  service httpd start  启动C的httpd服务
  ssh -D 9528 192.168.34.200 -fN   在A机器搭建代理客户端的后台隧道
 curl --socks5 127.0.0.1:9528 192.168.34.100   在A上输入此命令,访问外国网站即可
www.google.com

通过代理可以访问windows版国外网站搭建:

[root@b.ssh]#iptables  -A INPUT  -s 192.168.34.1 -j REJECT  C主机进行防火墙控制windows窗口连接
[root@centos7~]#ssh -D 9528 192.168.34.200 -fNg    -g选项自己能通过网关访问windows网站,别人也可以访问自己
[root@centos7~]#curl --socks5 127.0.0.1:9528 192.168.34.100  也可以通过输入命令访问windows国外网站
www.google.com

在windows网页上高级设置也可以在客户端上访问外国网络:

 

设置完之后就可以通过192.168.34.100访问网站。

 

服务器端:sshd, 配置文件: /etc/ssh/sshd_config
常用参数:

Port 端口号
ListenAddress ip 监听IP地址
LoginGraceTime 2m 等待时间是2分钟
PermitRootLogin yes 禁止ROOT用户模式进行ssh连接
StrictModes yes 检查.ssh/文件的所有者,权限等
MaxAuthTries 6 错误的连接最大次数,默认是3次
MaxSessions 10 同一个连接最大会话
PubkeyAuthentication yes 支持公钥验证
PermitEmptyPasswords no 禁止空口令登陆
PasswordAuthentication yes 支持口令验证
GSSAPIAuthentication yes 默认是yes,建议改为no影响连接速度。
UsePAM yes # 使用PAM模块
ClientAliveInterval 2 检查客户端是否活跃,每两秒检查一次,客户端10s时间不动就会断开
ClientAliveCountMax 3 连续检查3次客户端活跃情况。
GatewayPorts no 网关接口默认值是no 
ClientAliveInterval 单位:秒
ClientAliveCountMax 默认3
UseDNS yes   # 反向解析SSH,需要将此改为no,SSH连接与数据传输就会变快。
GSSAPIAuthentication yes 提高速度可改为no
MaxStartups 未认证连接最大值,默认值10, 连接并发连接数,当到达20,开始拒绝部分人。
Banner /path/file 登陆提示文件

限制可登录用户的办法:
AllowUsers user1 user2 user3 白名单用户
DenyUsers 黑名单用户 加入名单的用户名就无法通过ssh连接
AllowGroups
DenyGroups

 结论:白名单优先级比黑名单优先级高,如果黑白名单同时有一个IP地址被禁止ssh连接,默认可以连接。

 /etc/ssh/sshd_config配置文件部分内容详解:

服务器端修改配置文件中以下两项进行修改,可以加速ssh的连接

vim /etc/ssh/sshd_conf
UseDNS no                
GSSAPIAuthentication no
  •  在/etc/ssh/sshd_config配置中,我们默认的port(端口号)是22,可以通过此配置文件将自己的端口号改掉,以防黑客暴力破解当前的用户账号和密码,修改完之后service sshd restart。

修改完之后的端口号,我们再连接时需要指定端口号:ssh 192.168.34.100 -p 44(修改后的端口号)

  • 我们可以在指定的配置文件中输入要监听的IP地址:listenadress  192.168.34.10  直接绑定自己的IP地址和端口号,默认只能自己通过ssh连接。
  • 还可以在最后一行限制普通用户登录情况,例如:allowusers  wang  只能wang用户进行ssh登录。

ssh服务的最佳实践

  • 建议使用非默认端口
  • 禁止使用protocol version 1
  • 限制可登录用户
  • 设定空闲会话超时时长
  • 利用防火墙设置ssh访问策略
  • 仅监听特定的IP地址
  • 基于口令认证时,使用强密码策略
  • 使用基于密钥的认证
  • 禁止使用空密码
  • 禁止root用户直接登录
  • 限制ssh的访问频度和并发在线数
  • 经常分析日志

 

 

posted @ 2019-10-23 21:27  一叶知秋~~  阅读(1025)  评论(0编辑  收藏  举报