一、SSH介绍

    SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定;SSH 为建立在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台。SSH在正确使用时可弥补网络中的漏洞。SSH客户端适用于多种平台。几乎所有UNIX平台—包括HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其他平台,都可运行SSH。

    传统的网络服务程序,如:ftp、pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据,别有用心的人非常容易就可以截获这些口令和数据。而且,这些服务程序的安全验证方式也是有其弱点的, 就是很容易受到“中间人”(man-in-the-middle)这种方式的×××。所谓“中间人”的×××方式, 就是“中间人”冒充真正的服务器接收你传给服务器的数据,然后再冒充你把数据传给真正的服务器。服务器和你之间的数据传送被“中间人”一转手做了手脚之后,就会出现很严重的问题。通过使用SSH,你可以把所有传输的数据进行加密,这样"中间人"这种×××方式就不可能实现了,而且也能够防止DNS欺骗和IP欺骗。使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替Telnet,又可以为FTP、PoP、甚至为PPP提供一个安全的"通道"[1] 。

二、SSH客户端

客户端组件:
    ssh, 配置文件:/etc/ssh/ssh_config
        Host PATTERN
            StrictHostKeyChecking no 首次登录不显示检查提示
格式:

    ssh [user@]host [COMMAND]
    ssh [-l user] host [COMMAND]

选项:

    -p port:远程服务器监听的端口
    -b:指定连接的源IP
    -v:调试模式
    -C:压缩方式
    -X: 支持x11转发
    -Y:支持信任x11转发
        ForwardX11Trusted yes
    -t: 强制伪tty分配
        ssh -t remoteserver1 ssh remoteserver2

允许实现对远程系统经验证地加密安全访问
    当用户远程连接ssh服务器时,会复制ssh服务器/etc/ssh/ssh_host*key.pub(CentOS7默认是ssh_host_ecdsa_key.pub)文件中的公钥到客户机的~./ssh/know_hosts中。下次连接时,会自动匹配相应私钥,不能匹配,将拒绝连接。

三、SSH服务端

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

– Port 22:ssh默认端口为22
– ListenAddress ip
– LoginGraceTime 2m
– PermitRootLogin yes
– StrictModes yes:默认为yes,则使用密钥登录时,authorized_keys的权限不能给grout,other写权限,或不能给group,
                other对该用户家目录的.ssh 目录有wx权限,如果有以上权限,则不能用密钥登录。改为no时,则没有限制。
– MaxAuthTries 6
– MaxSessions 10 同一个连接最大会话
– PubkeyAuthentication yes:是否开启使用密钥登录
– PermitEmptyPasswords no
– PasswordAuthentication yes
– GatewayPorts yes:在ssh_config中写,则是在ssh -L时生效;在sshd_config中写,则是在ssh -R时生效
– ClientAliveInterval(单位:秒)
– ClientAliveCountMax  (默认3)
– UseDNS yes
– GSSAPIAuthentication yes 提高速度可改为no 
– MaxStartups 未认证连接最大值,默认值10 
– Banner /path/file

限制可登录用户的办法:

    AllowUsers user1 user2 user3
    DenyUsers
    AllowGroups
    DenG

四、ssh服务登录验证

    从客户端来看,SSH提供两种级别的安全验证。

第一种:基于用户名口令的安全验证

    只要知道服务器的SSH连接帐号和口令(当然也要知道对应服务器的 IP及开放的 SSH端口,默认为22 ),就可以通过 ssh客户端登录到这台远程主机。此时,所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器,可能会有别的服务器在冒充真正的服务器,也就是受到“中间人”这种方式的×××。

原理:

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

示例:

    只输入用户名和密码访问

N%I]EHD[A(%84YAY4]A1WQQ.png

注:第一次客户端发起ssh请求,客户端会发起询问,再次发起,就不在询问。

第二种:基于密匙的安全验证

    需要依靠密匙,也就是你必须为自己创建一对密匙,并把公用密匙放在需要访问的服务器上。如果你要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密匙进行安全验证。服务器收到请求之后,先在该服务器上你的主目录下寻找你的公用密匙,然后把它和你发送过来的公用密匙进行比较。如果两个密匙一致,服务器就用公用密匙加密“质询”(challenge)并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私人密匙解密再把它发送给服务器。

    用这种方式,你必须知道自己密匙的口令。但是,与第一种级别相比,第二种级别不需要在网络上传送口令。第二种级别不仅加密所有传送的数据,而且“中间人”这种×××方式也是不可能的(因为他没有你的私人密匙),但是整个登录的过程可能需要10秒。

原理:

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

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

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

    4、服务端得到客户端的请求后,会到authorized_keys中查找,如果有响应的IP和用户,就会随机生成一个字符串,例如:acdf
    5、服务端将使用客户端拷贝过来的公钥进行加密,然后发送给客户端
    6、得到服务端发来的消息后,客户端会使用私钥进行解密,然后将解密后的字符串发送给服务端
    7、服务端接受到客户端发来的字符串后,跟之前的字符串进行对比,如果一致,就允许免密码登录

步骤:

    (1) 在客户端生成密钥对

ssh-keygen -t rsa [-P ''] [-f “~/.ssh/id_rsa"]

    (2) 把公钥文件传输至远程服务器对应用户的家目录

ssh-copy-id [-i [identity_file]] [user@]host

    (3) 测试
    (4) 在SecureCRT或Xshell实现基于key验证
        在SecureCRT工具—>创建公钥—>生成Identity.pub文件转化为openssh兼容格式(适合SecureCRT,Xshell不需要转化格式),并复制到需登录主机上相应文件authorized_keys中,注意权限必须为600,在需登录的ssh主机上执行:

    (5)重设私钥口令:

ssh-keygen –p

    (6)验证代理(authentication agent)保密解密后的密钥,这样口令就只需要输入一次,在GNOME中,代理被自动提供给root用户,否则运行ssh-agent bas。
    (7)钥匙通过命令添加给代理

ssh-add

示例:

    centos6和centos7相互实现免密登录

客户端:centos6                 服务端:centos7

    1、首先在centos6生成一对密钥(ssh-keygen)

A9FSKLZ1ML@H)BRFJ)R4YTP.png

注:从上图可以看出创建的公钥和私钥都保存在/root/.ssh/文件下,而且,没有设置私钥的加密密码。

     查看密钥是否生成:

E1PB)K5IPT5A_5JXX`J968W.png

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

ZBQJ8[PZ}DQ8{IX$(EK9[0H.png

    3、测试centos6是否不需要密码连接到centos7。

UNVDAC(QC3ZC94[X296YMGK.png

    4、在centos7上使用ssh-keygen命令生成一对密钥,并将centos7的公钥ssh-copy-id 拷贝到服务端,测试centos7是否不需要密码连接到centos6,因为操作过程与前三步一样,就不一一展示,直接测试结果。

M)95Y[BD)W]VU6X78XL3])S.png

    5、排错:不是自己想要的结果都称为排错,我在centos7执行完上述步骤后发现,centos7连接centos6还是需要密码,最终才发现是centos6和centos7中的ssh配置需要修改一下,因为它把打开钥匙验证的这一项禁止了。

1S~25GX5$2T9T)0Q6H4$ODK.png

    打开密码验证模式(这一项在免密模式可改可不改):

M`786AGKU(RN{3VCOYZUX7X.png

注:如果不打开这一模式,不使用免密登录,普通登录不需要输入密码。

    修改完成后需要重启ssh服务(centos6)

CJWL@6RZD67]LYQ6][{%V9U.png

    重启ssh服务(centos7)

4H)%804P_H{7C$~Y9NM5WSX.png

注:重启服务时centos6和centos7两者格式不同,命令也不同。

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

5.1 本地端口转发

     本地转发中的本地是指将本地的某个端口转发到其他主机的某个端口,这样当我们的程序连接本地的这个端口时,其实间接连上了其他主机的某个端口,当我们发数据包到这个端口时数据包就自动转发到了那个远程端口上了

格式:

    ssh -L [bind-address:]localport:remotehost:remotehostport sshserver
    bind_address表示本地主机的ip(绑定地址),这是针对系统有多块网卡,不指定默认是127.0.0.1
    localport:本地主机指定监听的端口
    remotehost:远程主机的ip
    remotehostport:指定远程主机的端口,如果远程主机是HTTP,就是80,FTP(21)。。。
    sshserver:远程主机的ip,也可以是能够访问到远程主机的另一个ip

选项:

    -f 后台启用
    -N 不打开远程shell,处于等待状态
    -g 启用网关功能
     -L 启动本地端口转发

示例:
    c7:192.168.159.159:client        

    c6:192.168.159.129:踏板机 

    c5:192.168.159.143:server
1、首先在centos5服务器上开启23端口,添加策略

    iptables -F
   iptables -A INPUT -s 192.168.159.129 -p tcp --dport 23 -j ACCEPT     开启
   iptables -A INPUT -p tcp --dport 23 -j REJECT              关闭

$~HHB89OA88WFGO3WOGR`}L.png

2、在c7客户端上启动本地端口转发,当访问本机的9527的端口时,被加密后转发到c6的ssh服务,再解密被转发到c5:23本地端口转发

    c7:ssh -L 9527:192.168.153.5:23 -Nf 192.168.153.6
        -L 启动本地端口转发
        -N 不启用shell
        -f 后台

3、在c5服务端创建一个用户,通过telnet利用9527端口与c5进行访问

   telnet 127.0.0.1 9527

    创建用户

I6X~15H~M]CM]SAO1S(8PEP.png

    测试

G@P$FORJ`{F605D689$26_4.png

5.2 远程端口转发

    远程转发和本地很相似,原理也差不多,但是不同的是,本地转发是在本地主机指定的一个端口,而远程转发是在远程的主机上指定一个端口将指向该端口的连接转发到本地端口。两者的本质一样,区别在于需要转发的端口是在远程主机上还是在本地主机上。

远程转发格式:

   ssh -R sshserverport:remotehost:remotehostport sshserver

示例:smtp转发

    c7:192.168.159.159:server       

    c6:192.168.159.129:踏板机 

    c5:192.168.159.143:client

1、在c7目标主机上配置smtp服务

[root@centos7(nanyibo) ~]# vim /etc/postfix/main.cf
    inet_interfaces=all

GHNX2SN8~HX_WA~GIS0S2(N.png

    修改完成后重新启动postfix服务

    systemctl restart postfix

2、让c5服务端侦听9527端口的访问,如有访问,就加密后通过ssh服务转发请求到本机ssh客户端,再由本机解密后转发到c7:25

c6:ssh -R 9528:192.168.159.129:25 -Nf 192.168.159.143

UOA5I@EW7JJIRMBEG_735GB.png
注:需要输入密码

3、测试,在c5服务端编写一封邮件,通过telnet利用9527端口与c7进行访问

c5:telnet 127.0.0.1 9527
mail from:hh@hh.com
rctp to:root@localhost.localdomain
data
hello world
.
quit

C1XNRDEWNT]1]OBMM`OZTJY.png

注:root@后面必须是这个终端的hostname,否则邮件发送不成功。

4、测试成功,收到邮件

4$31MNIJK4%3E(S]O3S_%]S.png

5.3 动态端口转发

    在企业内部或者网络中,基于安全策略不能随便访问互联网某些站点。当用firefox访问internet时,本机的1080端口做为代理服务器,firefox的访问请求被转发到sshserver上,由sshserver替之访internet ,在本机firefox设置代理socket proxy:127.0.0.1:1080。

格式:

    ssh -D 1080 root@sshserver
    port :代理服务器开启的代理端口
    ssherver : 远程的代理服务器地址

示例:

    c7:192.168.159.159

    c6:192.168.159.129

    c5:192.168.159.143

    动态代理,在centos7上部署http服务,在centos7上写防火墙,禁止物理机192.168.153.1访问centos7上的web服务,但centos6可以访问。目标利用ssh -D 建立通道,再利用sock5 代理访问

1、首先在centos7上部署http服务

    在c7上安装httpd:

    yum -y install httpd

2、设置浏览器访问

DUXLVZE)@H@H%F522]`U~]F.png

3、重启httpd服务,并测试是否可以访问

F[R)M5Y`5TKYBQK4%I2GTZC.png

4、在centos7上写防火墙,禁止物理机192.168.153.1访问centos7上的web服务,但centos6可以访问

    iptables -A INPUT -s 192.168.159.1 -p tcp --dport 80 -j REJECT
    iptables -A INPUT -s 192.168.159.143 -p tcp --dport 80 -j REJECT

5、利用ssh -D 建立通道

   ssh -fND 1080 root@192.168.159.129

~K2NR9AG]WQO$LC0P@$FJ@X.png

6、在centos5利用sock5 代理访问

   curl --socks5 127.0.0.1:1080 http://www.google.com

I7$NVN641G_HT7]AHW{IG$2.png

注:当本地1080端口受到外部网站请求会转发到外部服务器上面去,代理服务器通过1080端口把请求转发到站点服务器上面去此时方可正常访问外部站点