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访问
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的访问频度和并发在线数
- 经常分析日志