Linux-使用ssh免密码登录
Table of Contents
ssh登录的认证方式
我们能用ssh登录服务器,是因为服务器中运行着一个叫sshd
的守护进程,它默认监听着22端口,该进程的配置文件在/etc/ssh/sshd_config
,在里面我们可以看到sshd
的认证方式大概有:
PubkeyAuthentication 公钥认证
RSAAuthentication RSA认证
PasswordAuthentication 密码认证
PAM authentication PAM认证
GSSAPIAuthentication GSSAPI认证
其中注释的都是默认使用注释的值,最常用的认证就是公钥认证
和密码认证
,我们平时登录时要输入密码,就是用的密码认证
,而免密码登录就是使用公钥认证
了,其他的我也不太懂(好像也是可以免密登录),以后用到再说吧。
方法一:使用公钥免密登录
生成RSA公钥/私钥对
首先你要检查一下你的~/.ssh
目录下,有没有id_rsa
和id_rsa.pub
两个文件,如果有,那就不用执行ssh-keygen了,因为你以前已经执行过了,id_rsa
就是私钥,id_rsa.pub
就是公钥。
如果没有这两个文件,那么执行下面命令,无论提示什么,你都闭着眼晴一路回车即可,最后会在~/.ssh
目录下生成id_rsa
和id_rsa.pub
两个文件。
ssh-keygen
如图所示(该命令也可以写成ssh-keygen -t rsa
,如果不写,默认就是-t rsa
,t表示type,即类型)
ssh-keygen
输出的内容翻译:
Generating public/private rsa key pair.
翻译:正在生成rsa公/私密钥对
Enter file in which to save the key (/Users/bruce/.ssh/id_rsa):
翻译:输入你要保存的密钥文件名(直接回车表示使用默认文件名`/Users/bruce/.ssh/id_rsa`)
Enter passphrase (empty for no passphrase):
翻译:输入密码(如果不输入则默认为空,公钥认证方式还可以再加一层密码,这样更安全,但是一般没必要)
Enter same passphrase again:
翻译:再次输入密码(还是直接回车表示使用空密码)
Your identification has been saved in /Users/bruce/.ssh/id_rsa.
翻译:你的私钥已经保存到`/Users/bruce/.ssh/id_rsa`文件中
Your public key has been saved in /Users/bruce/.ssh/id_rsa.pub.
翻译:你的公钥已经保存到`/Users/bruce/.ssh/id_rsa.pub`文件中(注意,公钥文件名都是在私钥文件名后面加上`.pub`,pub表示public,公共的)
The key fingerprint is:
翻译:密钥指纹是:
SHA256:IPOJPYk+xqkqn11pCX8Jn/WVHjIUqf5wjevNxLliL3Q [email protected]
自动把公钥拷贝到服务器中
我们可以使用ssh-copy-id
命令,把上一步中生成的公钥拷贝到需要免密登录的服务器中,一个公钥可以多个服务器使用,所以你需要免密登录的服务器都可以往那拷(记得把 [email protected] 换成你的服务器的账号密码哦)。
ssh-copy-id [email protected]
这一步会把你用户目录中的id_rsa.pub
拷贝到服务器中的~/.ssh/authorized_keys
文件中(这个文件默认是不存在的,会自动创建)。
这一步操作完成后,你可以去服务器的~/.ssh
目录下看,是不是多了一个authorized_keys,如果有多个用户想用公钥认证方式登录这台服务器,同样,只要把它们的公钥放到authorized_keys文件中即可,一个公钥占一行(如果你用vi/vim查看是多行,那是因为软换行,实际上还是一行,显示行号即可看出来)。
ssh-copy-id默认是拷贝你电脑上的~/.ssh/id_rsa.pub
公钥文件到服务器,那如果你的公钥不在这个路径,或者说不是这个名字呢?比如有可能是你帮新员工开账户,让它们把公钥发你,你来上传,要怎么上传呢?
其实是可以通过-i
来指定你要上传的公钥文件的,比如
ssh-copy-id -i ~/Downloads/zhangsan.pub [email protected]
这样就会把公钥文件上传到zhangsan的家目录下的/.ssh/authorized_keys
文件中。
手动把公钥拷贝到服务器
事实上,除了用前面说的ssh-copy-id
命令外,你也可以用常规的传文件的方法(如scp、sftp、rsync等)手动把公钥文件传到服务器后,自己新建~/.ssh/authorized_keys
文件,并把公钥文件中的内容复制到该文件中,也可以手动直接复制内容粘贴到~/.ssh/authorized_keys
文件中,这种方法尤其常见于只能用密钥登录而不允许密码登录的机器。
但需要注意~/.ssh/authorized_keys
文件的权限必须为600,且~/.ssh
目录的权限为700,这是Linux为了安全而规定的,如果这两个权限有一个不对,则公钥认证会失败,但由于~/.ssh
目录默认就存在,所以它的权限无需你去设置,默认就是700,而用ssh-copy-id
命令往服务器传公钥自动生成的~/.ssh/authorized_keys
的权限自动就是600,所以也无需你去修改,所以只有你自己新建的才需要修改。
在本地执行以下命令,输入密码后即可把公钥文件id_rsa.pub文件上传到123.8.12.135服务器的xiebruce用户的家目录下
scp ~/.ssh/id_rsa.pub [email protected]:~
注意: 这个本地未必是你自己的电脑,有可能是另一台服务器,比如A要免密登录到B,那么A就是我说的本地,但它实际上可能是一台服务器。
然后在服务器操作
# 在服务器123.8.12.135进入xiebruce家目录中的.ssh目录(注意此时你是以xiebruce这个用户登录的,并且没有切换到其它用户)
cd ~/.ssh/
# 把xiebruce家目录下的id_rsa.pub文件中的内容追加到authorized_keys文件中
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
# authorized_keys文件有可能之前不存在,我们先看看它的权限
ls -l ~/.ssh/authorized_keys
# 如果是权限不是600,即不是“-rw-------”,那前面说属于首次添加,这时我们要设置一下它的权限为600,如果是600我们就不用设置了
chmod 600 ~/.ssh/authorized_keys
操作完后,你就可以用xiebruce
这个用户免密登录123.8.12.135
这台服务器了(但其它用户还是不行)。
如果你们公司是你管理着这台服务器,很明显其他人(新员工)想要用公钥认证的方式登录,必须把它们的公钥发给你(让他们用ssh-keygen
生成),你来放到这台服务器里他们的账户家目录下对应authorized_keys文件中。
试试免密登录是否正常
如果正常的话,会直接进入登录用户的家目录(记得把 [email protected] 换成你自己服务器的账号密码哦)
ssh [email protected]
解决SSH连接自动断开的问题
编辑服务器的sshd
的配置文件/etc/ssh/sshd_config
,把ClientAliveInterval改成60,这样每隔60秒服务器会跟客户端通讯一次,然后客户端会回复,这样就不会断,把ClientAliveCountMax修改成3,表示如果3次(3*60=180秒)以后还是没有人操作客户端,那就自动断开(毕竟不能长时间开着,这样不安全):
ClientAliveInterval 60
ClientAliveCountMax 3
或者还可以在客户端(就是你自己的电脑上),编辑vim ~/.ssh/config
,在里面添加:
ServerAliveInterval 60
表示每60秒与服务器通信一次,这样就不会断开,这个比较厉害一点,因为我是mac,晚上睡眠了都没断开,所以如果没必要,还是别用这个了,毕竟一直开着不是太安全。
此外,客户端还可以设置当空闲时,每隔一定时间自动往服务器发送一个任意字符(默认是0),比如我用的iTerm2就可以这样设置:
奇怪的是,以前用密码登录的时候,只需要客户端这样设置即可,但换成了公钥认证免密码登录,客户端这个不灵了,所以才需要在服务器修改配置。
公钥认证免密登录原理
假设你想用自己的电脑A去登录服务器B(以下是自己网上查找并加上个人理解,如有不对恳请大佬指出!)
- 1)A向B发送一个连接请求,信息包括自己的用户名,ip等;
- 2)然后B得到A信息后,去.ssh下的authorized_keys文件中查找,如果有该用户的用户名和主机名,B会随机生成一个字符串STR;
- 3)然后B利用A的公钥对字符串STR进行加密,然后发送给A,A得到B发过来的消息用自己的私钥进行解密,然后将解密后的字符串用自己私钥签名后发送给B;
- 4)B接收到A发过来解密的字符串并用公钥验签,验签通过说明A发过来的数据中途未被篡改,然后比较STR是否跟刚才发过去的一致,如果一致就会允许免登陆(此时命令行界面将跳转到登录服务器后的界面)。
方法二:使用expect免密登录
expect自动登录原理
除了前面的上传公钥,还可以使用expect
工具,是自己写一个脚本,来样模拟用户的输入,本质上还是要密码,只不过expect
工具可以自动识别终端弹出的输入密码提示,自动帮你输入你事先给好的密码并帮你回车确定(当然其实回车也是自己写的)。
使用这种方式是因为遇到有阿里云跳板机只能用ls
命令查看服务器列表,什么也做不了,更别说上传你的公钥了。
编写expect脚本
以下命令即为自动登录脚本
#!/usr/bin/expect
set timeout 30
spawn ssh -l xiebruce 12.34.56.78
expect "password:"
send "123578\r"
interact
先把上边命令复制到你本地随便一个编辑器中,修改以下值
xiebruce
是登录用户名,请先换成你的登录用户名;12.34.56.78
是要登录的服务器ip,请先换成你要登录的服务器ip;send "123578\r"
中的123578
是登录密码,请换成你服务器的登录密码,注意不要把\r
删掉
修改好之后,在你电脑上新建autologin.sh
文件,把刚刚修改好的内容粘贴进去,保存(因为是ssh用于自动登录的,我建议直接放到~/.ssh/
目录下)。
然后给它执行权限
chmod u+x ~/.ssh/autologin.sh
在iTerm2上使用
这里我演示配置iTerm2终端使用,其它的终端应该也有类似自动执行shell脚本的功能。
打开iTerm2终端,按快捷键cmd+o
,点击右下角的Edit Profiles
然后点击左下角的+
号可以新增一个配置,如下图,填一下Name,还有在Command
里选择Custom Shell
,在右侧框填入刚刚创建的autologin.sh
的绝对路径(绝对路径就不要用~
这种符号),这样就行了,也不用点保存,直接点左上角的关闭按钮即可(自动保存)
以后要登录你那个服务器,直接在iTerm2上按cmd+o
,用上下方向键选中前面添加的那个配置,回车,即可自动登录。
注:其实我平时都是用公钥免密方式的,后来为了测试这种方式,我专门给我的一个服务器设置了用这种方式登录,后来在使用中发现,只要是用这种方式登录的,它会“记住”登录时窗口的大小。
比如,我小窗口的时候登录,你用vim打开文件,再放大窗口,vim打开的内容还是只会占用原来小窗口大小,不会像正常编辑器那样把内容铺满整个窗口,
如果我大窗口的时候登录,再用vim打开文件,文件内容能铺满窗口,但是,如果你把窗口缩小后再用vim打开文件,它内容会乱,显示不出来,放大窗口后再按上/下(即j/k键)才能让内容显示出来。
也就是说,你在大窗口的时候登录,就只能在大窗口的时候打开,如果你换成小窗口打开,它显示就会乱;同理,小窗口的时候登录,虽然在大窗口也能打开,但它显示还是在那个小窗口中显示。
方法三:使用sshpass免密登录
本质上还是要密码,只不过sshpass帮我们输入了。
brew无法安装sshpass
我们知道,macOS的包管理工具是Homerew,macOS下大多数命令都可以通过brew install xxx
来安装,但是如果你这种方法安装sshpass,它会提示
We won’t add sshpass because it makes it too easy for novice SSH users to
ruin SSH’s security.
翻译:我们不会添加sshpass,因为它会让很多SSH新手用户毁掉SSH的安全性。
提示如下图
我们知道Homebrew是一个第三方开发者编写的开源包管理工具,其代码开源在github上,可能Homebrew的开发者认为,这个命令会导致SSH新手用户滥用SSH,因为新手本身就不太懂,它也不了解什么安全性,这样会导致SSH失去它的安全性优势,所以Homebrew的开发者就没有把sshpass加入官方的核心库中。
虽然我们可以通过一些第三方库来安装,但质量也是参差不齐,我建议还是直接源码编译吧,也不难,非常简单。
源码编译安装sshpass
与大多数开源代码都放在github上不同,sshpass的源代码是放在sourceforge上的,我们直接在sourceforge里下载它的源码包就可以。
当然github上也有,只不过是从sourceforce同步过去的(是sourceforce的一个镜像),版本可能不是最新的。
以下命令编译(每行分别执行):
#解压
tar -zxf sshpass-1.08.tar
#进入解压后的源码文件夹
cd sshpass-1.08
#运行configure命令进行编译前配置
./configure
#编译并安装
make && make install
编译安装完之后它是自动安装到/usr/local/bin/
下的,然后就可以使用了。
使用sshpass登录
sshpass的使用非常简单,在原有的ssh登录命令前面,加上sshpass -p "登录密码"
即可自动登录。
例(-p
指定的密码可以不加双引号,但最好加上,因为有时候密码有些特殊字符,比如“星号”、“括号”之类的,不加双引号就会导致报错):
sshpass -p "sifs329i" ssh [email protected]
也可以把这个命令放到一个.sh
文件里(注意sshpass要写全路径),然后像前面的expect那样添加到iTerm2(或者你喜欢的终端)里,使用的时候,选择它,回车,即可快速不需要密码进入服务器
sshpass -p "sifs329i" ssh [email protected]
其它命令
#查看sshpass版本
sshpass -V
#帮助
sshpass -h