Telnet
介绍
Telnet 协议是 TCP/IP 协议族中的一员,是 Internet 远程登录服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。在终端使用者的电脑上使用 telnet 程序,用它连接到服务器。终端使用者可以在 telne t程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。可以在本地就能控制服务器。要开始一个 telnet 会话,必须输入用户名和密码来登录服务器。Telnet 是常用的远程控制 Web 服务器的方法。
注意,telnet 不支持管理员 root 用户登录。
使用
服务端
1、安装 telnet 的服务端:
$ yum install telnet-server.x86_64 -y
2、设置开机启动:
$ systemctl enable telnet.socket
3、启动服务:
$ systemctl start telnet.socket
对于 CentOS 6 来说,telnet 服务是由 xinetd 守护,所以要启动 telnet 服务只需要启动 xinetd 即可,修改
/etc/xinetd.d/telnet
就可启用 telnet 服务的监听。
在 CentOS 7 中直接启动 telnet 服务即可。
telnet 服务默认监听 23 端口;
客户端
直接使用 XShell 通过 telnet
命令连接,如下:
OpenSSH
OpenSSH 是什么
OpenSSH 是 SSH(Secure SHell)协议的免费开源实现。SSH 协议族可以用来进行远程控制,或在计算机之间传送文件。而实现此功能的传统方式,如 telnet(终端仿真协议)、rcp ftp、rlogin、rsh 都是极为不安全的,并且会使用明文传送密码。OpenSSH 提供了服务端后台程序和客户端工具,用来加密远程控制和文件传输过程中的数据,并由此来代替原来的类似服务。
OpenSSH 只是 SSH 协议的其中一个实现者,还有 dropbear 也是 SSH 协议的实现。
OpenSSH 的组成
OpenSSH 主要包括了如下几个部分:
ssh
:rlogin 与 Telnet 的替代方案;scp
、sftp
:rcp 的替代方案,将文件复制到其他电脑上;sshd
:SSH 服务器,默认监听 22 端口;ssh-keygen
:产生 RSA 或 DSA 密钥,用来认证用;ssh-agent
、ssh-add
:帮助用户不需要每次都要输入密钥密码的工具;ssh-keyscan
:扫描一群机器,并记录其公钥;
客户端组件
ssh
是 OpenSSH 的客户端组件,对应的配置文件为 /etc/ssh/ssh_config
。
使用格式如下:
ssh [user@]host [command]
-p:指定远程主机监听的端口;
不指定用户时默认是以当前系统的登录用户的身份来登录远程主机,例:
$ ssh 10.0.1.202
ssh
命令还可用来直接在指定主机上执行给定的命令,例:
$ ssh root@10.0.1.202 ifconfig
查看 /etc/ssh/ssh_config
配置文件会看到以下内容:
# 下面内容在配置文件中是注释内容,也是默认值,如果想要启用则需要修改对应值并取消注释。
Host * # 限定生效的主机,* 表示对所有主机都使用以下配置
StrictHostKeyChecking ask # 是否询问校验主机 Key
Port 22 # 默认连接使用的端口
Protocol 2 # 协议版本
...
该内容的作用是用来对指定的主机使用特定的配置,*
表示所有主机。
使用基于密钥的认证
在上述我们使用 ssh
命令连接远程主机时使用的时密码方式进行认证,除此之外我们还可以使用密钥的方式进行认证。
ssh
要想使用基于密钥的认证,需要先在客户端生成一对密钥,把公钥部分上传到要连接的远程主机对应的账户的家目录下的一个特定配置文件中,这个特定文件的位置一般是在服务器端的配置文件中指明的,这个配置文件通常是在用户家目录下的名为 .ssh
的隐藏目录,如:
$ ls ~/.ssh/
known_hosts
在上述我们使用 ssh
连接远程主机时,通常第一次连接确认认证通过后第二次连接就不需要密码验证登录了,这是因为 ssh
客户端和远程主机服务端自动完成了密钥认证,查看该文件:
$ cat known_hosts
10.0.1.200 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQwK+G3Gq5FHYsNnNv5W6LCzKIlKPrKRbnZUXkxd15aSm+1VUgRLbm6JXFZChXYbS+mSTxRTNCUsicqyS1DHC0=
这里执行 cat known_hosts
的主机是 10.0.1.202
,在上述演示客户端组件时我使用 10.0.1.200
这台主机连接了 10.0.1.202
,并确认通过了认证,然后 10.0.1.200
这台主机生成的公钥信息就被保存在 10.0.1.202
这台主机上了,所以后续连接就不需要密码了。
现在以 10.0.1.202
为 ssh 客户端生成密钥对,以密钥方式认证连接 10.0.1.200
为例,做如下步骤。
1、10.0.1.202
主机以指定加密方式生成密钥对。
$ ssh-keygen -t rsa
密钥对默认会保存在当前用户家目录下的
.ssh
目录中,id_rsa
是私钥,id_rsa.pub
是公钥。
2、将公钥传送到远程主机 10.0.1.200
对应用户的家目录。
$ ssh-copy-id -i /root/.ssh/id_rsa.pub root@10.0.1.200
传送成功后对应用户的加目录下的
.ssh
目录中会生成一个authorized_keys
文件。
3、此时使用 10.0.1.202
连接 10.0.1.200
就不需要密码了。
$ ssh root@10.0.1.200
XShell 使用密钥方式认证
上述是直接使用两台 Linux 主机来完成 ssh 密钥认证,还可以直接在 Windows 上使用 XShell 与主机完成密钥认证。
1、选择工具菜单下的”新建用户密钥生成向导“:
2、直接使用默认的”RSA“方式生成 2048 位密钥即可:
3、继续下一步:
4、密钥名称随意,如果要给私钥加密就可以输入密码,不需要就直接下一步:
5、此时公钥已生成成功,选择将其保存为文件:
6、进入要使用密钥认证的主机对应用户的家目录下的 .ssh
目录,编辑 authorized_keys
文件,上一步保存的文件中的密钥信息添加到 authorized_keys
的尾部,要注意的是 authorized_keys
的属主位必须拥有读写权限(600)。
7、再次使用 XShell 连接这个主机,身份认证时选择”Public Key“方式,在上面我没有对密钥加密,所以我不输入密码直接登录即可:
8、然后就会发现成功登录了。
注意:用户家目录下的
.ssh
目录的权限需要是700
,其下的authorized_keys
文件权限应该是600
,否则会登陆失败。
使用 scp 传送文件
scp
全称 ”secure copy“,译为”安全复制“的意思,它是一个跨主机的复制命令,可以将本机上的文件复制到远程主机,也可以将远程主机上的文件复制到本机。
scp
命令有两种模式:
- pull 模式:将远程文件拉取到本地;
- push 模式:将本地文件推送到远程主机;
pull 模式的使用格式如下:
scp [options] [user@]<host>:<from_file> <local_path>
以 user 的身份将登录远程主机 host 将 from_file 文件复制到本地的 local_path,如果复制的文件是多个,local_path 应该是一个目录。
push 模式的使用格式如下:
scp [options] <from_file> [user@]<host>:<to_path>
以 user 的身份登录远程主机复制本地 from_file 文件到远程主机 host 下的 to_path 路径下,如果复制的文件是多个,to_path 应该是一个目录。
常用选项:
-r
:递归复制,复制目录时指定;-p
:保持原文件的属性信息;-q
:静默模式;-P <port>
:指定远程主机监听端口;
看如下示例。
1、登录 10.0.1.200
,以 root
用户的身份拉取 10.0.1.202
中的 /etc/fstab
到本地家目录下。
$ scp root@10.0.1.202:/etc/fstab .
root@10.0.1.202's password:
fstab
2、登录 10.0.1.200
,以 root
用户的身份复制本地 /etc/fstab
到 10.0.1.202
的家目录下。
$ scp /etc/fstab root@10.0.1.202:/root/
root@10.0.1.202's password:
fstab
如果两台主机完成了密钥认证,那么上述两个示例过程中是不需要输入密码的。
使用 sftp 访问远程主机文件系统
OpenSSH 还支持以类似 ftp 的方式访问远程主机的文件系统,这里就要用到 sftp
命令,以 10.0.1.200
主机访问 10.0.1.202
为例:
$ sftp root@10.0.1.202
Connected to 10.0.1.202.
sftp>
由于
10.0.1.200
和10.0.1.202
这两台主机已经完成了密钥认证,所以使用sftp
是不需要密码的。
在 sftp
命令提示符下的子命令与使用 ftp
、lftp
命令没有太大区别,这里就不再多说。
服务器端组件
sshd
是 OpenSSH 的服务端组件,服务名也是 sshd
,CentOS 7 中可通过执行 systemctl status sshd
查看 sshd
服务状态,对应的配置文件为 /etc/ssh/sshd_config
。
在该配置文件中,以
#
开头的行为纯注释,只以#
开头的行表示可启用的选项。
配置文件中常用的设置字段有如下:
Port
:sshd 服务监听的端口;ListenAddress
:指明监听的地址;AddressFamily
:指定使用 IPv4 还是 IPv6 协议家族,any
表示都监听,4
对应 IPv4,6
对应 IPv6;SyslogFacility
:指明记录日志的方式,默认使用AUTHPRIV
记录日志,保存在/var/log/secure
中;LoginGraceTime
:登录宽限时间,默认为2m
,表示在登录提示符下 2 分钟之内不输入密码则超时;PermitRootLogin
:是否允许管理员用户(root)登录,默认yes
表示允许;StrictModes
:是否使用严格检查模式;MaxAuthTries
:最大认证尝试次数;MaxSessions
:指定 OpenSSH 最多允许多少个会话并行登录;RSAAuthentication
:是否支持 RSA 安全认证;PubkeyAuthentication
:是否支持公钥认证;AuthorizedKeysFile
:指定使用公钥认证时的公钥的存放位置(相对对应用户家目录),默认值为.ssh/authorized_key
;PasswordAuthentication
:是否允许密码(口令)认证;X11Forwarding
:是否允许 X11 转发(远程打开图形化窗口);Subsystem
:对 sftp 的支持,注释则表示不支持 sftp 远程连接;UseDNS
:是否使用 DNS 反解;AllowUsers
:指定可登录的用户,多个用户用空格分开;AllowGroups
:指定可登录的组的用户,多个组用空格分开;DenyUsers
:指定拒绝登录的用户,多个用户用空格分开;DenyGroup
:指定拒绝登录的组的用户,多个组用空格分开;GSSAPIAuthentication
:GSS 认证;
关于
sshd_config
更详细的描述信息可使用man sshd_config
查看。
通常情况下我们会修改如下这几项:
Port 6666 # 变更 SSH 服务远程连接端口;
PermitRootLogin no # 不允许 root 远程登录
PasswordAuthentication no # 禁止使用密码直接远程登录
UseDNS no # 禁止 SSH 进行 DNS 反向解析,影响 SSH 连接效率
GSSAPIAuthentication no # 禁止 GSS 认证,减少连接延迟
ssh 服务的最佳实践
- 不要使用默认端口;
- 禁止使用
protocol version 1
; - 使用白名单(
AllowUsers
)限制可登录用户; - 设置空闲会话超时时长;
- 利用防火墙设置 ssh 的访问策略;
- 仅监听特定的 IP 地址;
- 基于口令认证时,使用强密码策略;
- 使用基于密钥的认证;
- 禁止使用空密码;
- 禁止 root 用户直接登录;
- 限制 ssh 的访问频度和并发在线数;
- 保存好日志,经常分析;
扩展
免交互 SSH
1、expect 免交互:
# 安装
$ yum install expect -y
# 编写脚本
$ cat expect.ex
#!/usr/bin/expect
set ip 10.0.1.7
set pass 1
set timeout 30
spawn ssh root@$ip
expect {
"(yes/no)" {send "yes\r"; exp_continue}
"password:" {send "$pass\r"}
}
expect "root@*" {send "ls -l\r"}
expect "root@*" {send "exit\r"}
expect eof
# 连接
$ expect expect.ex
2、sshpass 免交互
# 安装
$ yum -y install sshpass
# 连接
$ sshpass -p<pass> ssh <host>
# 执行命令
$ sshpass -p<pass> ssh <host> <command>
跳板机脚本
#!/bin/bash
lb01=10.0.1.5
lb02=10.0.1.6
web01=10.0.1.7
web02=10.0.1.8
web03=10.0.1.9
nfs=10.0.1.31
backup=10.0.1.41
db01=10.0.1.51
db02=10.0.1.52
m01=10.0.1.61
zabbix=10.0.1.71
title="欢迎进入跳板机-$m01"
#跳板机函数
JUMP(){
OPTION=$(whiptail --title "$title" --menu "请选择你要连接的服务器:" 25 60 11 \
"1" "连接 lb01" \
"2" "连接 lb02" \
"3" "连接 web01" \
"4" "连接 web02" \
"5" "连接 web03" \
"6" "连接 nfs" \
"7" "连接 backup" \
"8" "连接 db01" \
"9" "连接 db02" \
"10" "连接 m01" \
"11" "连接 zabbix" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
case $OPTION in
1)
connect $lb01
;;
2)
connect $lb02
;;
3)
connect $web01
;;
4)
connect $web02
;;
5)
connect $web03
;;
6)
connect $nfs
;;
7)
connect $backup
;;
8)
connect $db01
;;
9)
connect $db02
;;
10)
connect $m01
;;
11)
connect $zabbix
;;
12)
connect $te
;;
13)
connect $te_web
;;
esac
fi
}
#主机函数
HOST_INFO (){
HOST=$(whiptail --title "$title" --checklist \
"请选择要发送的主机名:" 25 60 11 \
"$lb01" "发送给lb01" OFF \
"$lb02" "发送给lb01" OFF \
"$web01" "发送给web01" OFF \
"$web02" "发送给web02" OFF \
"$web03" "发送给web03" OFF \
"$nfs" "发送给nfs" OFF \
"$backup" "发送给backup" OFF \
"$db01" "发送给db01" OFF \
"$db02" "发送给db02" OFF \
"$m01" "发送给m01" OFF \
"$zabbix" "发送给zabbix" OFF 3>&1 1>&2 2>&3)
}
SER_INFO(){
SER=$(whiptail --title "$title" --checklist \
"请选择要检查的服务:" 25 60 10 \
"nginx" "检查nginx" OFF \
"mysqld" "检查mysqld" OFF \
"php" "检查php" OFF \
"tomcat" "检查tomcat" OFF \
"sshd" "检查sshd" OFF \
"httpd" "检查httpd" OFF \
"vsftpd" "检查vsftpd" OFF \
"docker" "检查docker" OFF \
"saltstack" "检查saltstack" OFF \
"rsyncd" "检查rsyncd" OFF 3>&1 1>&2 2>&3)
}
#连接函数
connect(){
whiptail --title "$title" --yesno "你确定要连接这台机器么?想好了啊!!!" 10 60
if [ $? -eq 0 ];then
{
ping -c 1 -w 1 $1 >/tmp/ping.txt 2>/dev/null
if [ $? -ne 0 ];then
for ((i = 0 ; i <= 100 ; i+=30)); do
sleep 1
echo $i
done
fi
} | whiptail --gauge "emmmm...我正在连接$1,检测网络中,等我一哈子..." 6 60 0
grep 'ttl' /tmp/ping.txt &>/dev/null
if [ $? -eq 0 ];then
ssh root@$1
else
whiptail --title "$title" --msgbox "网络检测失败,别连了,我的哥,$1机器都没开" 10 60
fi
fi
}
#推送文件函数
SCP (){
HOST_INFO
PA=$(whiptail --title "$title" --inputbox "请输入需要推送的文件本地路径:" 10 60 /etc/passwd 3>&1 1>&2 2>&3)
DEST=$(whiptail --title "$title" --inputbox "请输入需要分发到主机的哪个目录:" 10 60 /tmp 3>&1 1>&2 2>&3)
{
for H in ${HOST};do
echo "scp $PA ${H}:${DEST}"|bash &>/dev/null
for ((i = 0 ; i <= 100 ; i+=50));do
sleep 1
echo $i
done
done
} | whiptail --gauge "别着急,正在传送中..." 6 60 0
}
#检查磁盘函数
CHECK_DISK (){
HOST_INFO
for H in ${HOST};do
echo "ssh $H 'df -h' "|bash > /tmp/disk
whiptail --title "$(date +%F-%T) | $H 磁盘信息" --msgbox "$(cat /tmp/disk)" 10 60
done
}
#检查内存函数
CHECK_MEM (){
HOST_INFO
for H in ${HOST};do
echo "ssh $H 'free -m' "|bash > /tmp/meminfo
whiptail --title "$(date +%F-%T) | $H 内存信息" --msgbox "$(cat /tmp/meminfo)" 30 80
done
}
#查看服务状态
CHECK_SER (){
HOST_INFO
SER_INFO
for H in ${HOST};do
for S in ${SER};do
HO=`echo "$H"|awk -F \" '{print $2}'`
PROC=`ssh $HO "ps -ef|grep $S|wc -l"`
NUM=$( expr $PROC - 3 )
if [[ $PROC > 3 ]];then
whiptail --title "$(date +%F-%T) | $H 服务信息" --msgbox "${S} 存活 | 进程数:$NUM" 10 60
else
whiptail --title "$(date +%F-%T) | $H 服务信息" --msgbox "${S} 没有存活| 进程数:$NUM" 10 60
fi
done
done
}
#批量执行命令函数
EXEC_CMD(){
HOST_INFO
CMD=$(whiptail --title "$title" --inputbox "请输入要执行的命令:" 10 60 ifconfig 3>&1 1>&2 2>&3)
for H in ${HOST};do
HO=`echo "$H"|awk -F \" '{print $2}'`
RES=`ssh $HO "$CMD"`
whiptail --title "$(date +%F-%T) | $H 命令执行结果" --msgbox "$RES" 40 80
done
}
#退出函数
EXIT(){
pass=$(whiptail --title "$title" --passwordbox "请输入你的退出密码" 10 60 3>&1 1>&2 2>&3)
if [ $pass == '123456' ];then
exit
else
whiptail --title "$title" --msgbox "密码错误,你不是运维,小样的~~~" 10 60
continue
fi
}
whiptail --title "$title" --msgbox "lnb跳板机,给你全新不一样的feel,进去了,就不想出来" 10 60
#抓取键盘信号
trap "" HUP INT TSTP
while true;do
OPTION=$(whiptail --title "$title" --menu "请选择你的动作(轻点...)" 15 60 8 \
"1" "SSH远程连接" \
"2" "推送文件" \
"3" "查看磁盘空间" \
"4" "查看内存空间" \
"5" "查看服务状态" \
"6" "批量执行命令" \
"7" "轻松一下(game)" \
"8" "退出" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
case $OPTION in
1)
JUMP
;;
2)
SCP
;;
3)
CHECK_DISK
;;
4)
CHECK_MEM
;;
5)
CHECK_SER
;;
6)
EXEC_CMD
;;
7)
sh /root/test.sh
;;
8)
EXIT
;;
esac
fi
done
评论区