如何设置无密码的SSH登录?

我想能够通过SSH远程登录而无需每次输入密码。

  • 我该如何设置它?
  • 执行无密码会话需要使用不同的命令吗?

你正在使用OpenSSH吗?(如果是的话,那就很简单啦 ;) ) - Rinzwind
@Rinzwind,既然OpenSSH已经预装了,为什么我要费心去获取专有版本呢? - Oxwivi
18我尽量不做假设 ;) - Rinzwind
1@Kevin,请说明清楚。我们正在讨论的是无需密码进行ssh连接,这通常是一种好的做法。你是指ssh到root shell吗?这个问题没有涉及到。 - Oxwivi
@Oxwivi:抱歉,这应该是对Ravindra的答案的评论,其针对的是root登录。 - Kevin
提醒一下,现在不必再用引号将自定义端口号和标志括起来了。ssh-copy-id -p 1234 userId@host - shiruken
10个回答

回答

执行此命令(如果您已经拥有SSH密钥,可以跳过此步骤):

ssh-keygen

然后你需要将新的密钥复制到你的服务器上

ssh-copy-id user@host
## or if your server uses custom port no:
ssh-copy-id "user@host -p 1234"

复制密钥后,像平常一样通过ssh登录到机器上。
ssh user@host

现在您可以在执行命令的特定机器上无需输入密码登录。

示例

not-marco@rinzwind-desktop:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/not-marco/.ssh/id_rsa):
Created directory '/home/not-marco/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/not-marco/.ssh/id_rsa.
Your public key has been saved in /home/not-marco/.ssh/id_rsa.pub.
The key fingerprint is:
b1:25:04:21:1a:38:73:38:3c:e9:e4:5b:81:e9:ac:0f not-marco@rinzwind-desktop
The key's randomart image is:
+--[ RSA 2048]----+
|.o= . oo.        |
|*B.+ . .         |
|*=o .   o .      |
| = .     =       |
|. o     S        |
|E.               |
| o               |
|  .              |
|                 |
+-----------------+

not-marco@rinzwind-desktop:~$ ssh-copy-id not-marco@server
not-marco@server's password:
Now try logging into the machine, with "ssh 'not-marco@server'", and check in:

  ~/.ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

解释

这假设您已经可以通过SSH成功连接到服务器。

您需要生成一个SSH密钥对,这将允许您在不使用密码的情况下识别自己。如果您愿意,您可以选择用密码保护密钥,但是也可以将其留空以实现完全无需密码的SSH访问。

  1. 首先运行ssh-keygen来创建您的SSH密钥对,这将创建一个id_rsaid_rsa.pub文件。公钥文件(pub文件)放在服务器上,私钥(id_rsa)则留在您手中,用于身份验证。
  2. 接下来,使用ssh-copy-id user@server将公钥复制到您的服务器上,将user替换为远程用户,server替换为机器的DNS名称或IP地址。它会提示您输入SSH密码,请输入密码,如果一切顺利完成,您将能够通过ssh user@server访问该机器,而无需密码。

参考资料


13@Oxwivi 这个答案是更正确的方法 - 但似乎更长。你只需要输入 ssh-keygen,按照屏幕上的指示操作,然后输入 ssh-copy-id user@server,将user替换为你的远程用户,server替换为远程机器即可。 - Marco Ceppi
3每次按照这个步骤尝试登录时,我都会遇到“代理人未能使用密钥进行签名”的错误。解决办法是在本地机器上运行“> ssh-add”,现在我可以按预期登录到远程机器了。 - jmbouffard
2值得一提的是,如果您需要为@server使用自定义端口,则需要使用以下命令:ssh-copy-id "not-marco@127.0.0.1 -p 1234" - s3m3n
@Rinzwind:这是否意味着如果我禁用密码认证并仅允许密钥认证,我将无法从未知的客户端/机器对我的服务器进行身份验证?是否有办法使用为已知/配置的客户端生成的私钥允许来自未知机器的登录,以便与服务器进行通信?我的意思是,这个私钥是否可移植,并且在紧急情况下可以用于从其他机器对服务器进行身份验证? - Rajat Gupta
如果我想要在不需要密码的情况下通过SSH连接到多个系统怎么办?使用这种方法会覆盖现有的密钥,我只能无密码地连接到最后添加的系统。 - Ramana Reddy
没错。但是你只需要生成一次,然后将其复制到其他机器上。例如,可以参考这个链接:http://www.cyberciti.biz/tips/linux-multiple-ssh-key-based-authentication.html 另外,@RamanaReddy,我建议你可以新开一个话题,询问如何在多台机器上实现此功能,引用这个链接作为参考。 - Rinzwind
8但是服务器还在要求输入密码... - Lerner Zhang
你提到的“完全无密码”的SSH访问有多安全? - Hashim Aziz
非常好。它是所有不同方法中最好的一个。 - Rinzwind
警告:默认情况下,ssh-copy-id会复制它能找到的所有密钥,这可能会打开您不打算让其访问的权限。为了避免这种情况,请使用-i选项。 - Brent Bradburn

输入以下命令:
  1. ssh-keygen

    按下 Enter 键直到出现提示符

  2. ssh-copy-id -i root@ip_address

    (它会要求输入主机系统的密码一次)

  3. ssh root@ip_address

现在您应该能够无需密码登录。


我通常的做法如下:
ssh-keygen -t rsa
(在提示输入密码时,留空即可)
然后执行以下命令: cat ~/.ssh/id_rsa.pub | ssh username@hostname 'cat >> .ssh/authorized_keys'
(这需要在目标主机的家目录中有一个名为.ssh的文件夹,并且其中包含authorized_keys文件)
当然,将username替换为所需的用户名,将hostname替换为所需的主机名或IP地址。
完成后,您可以像往常一样通过SSH连接到该主机。

Rinzwind的回答中关于touchchmod命令怎么样? - Oxwivi
7你需要将.ssh/authorized_keys文件的权限设置为0600,否则这个操作将无法完成。 - Marco Ceppi
这真的很有帮助,因为我无法让ssh-copy-id在我的服务器上以root用户正常工作。在backuppc(或任何其他守护进程)需要通过SSH登录到另一台机器的情况下,必须使用root用户。 - Adam

我通常用sshpass来做这个,使用sudo apt-get install sshpass安装它,然后像这样使用。
sshpass -p 'password' ssh your_username@your_server

6为什么不使用SSH密钥? - enzotib
1这不是一个“为什么不”的情况,即使没有添加密钥,它仍然完美工作,我只是说另一种方法而已。 - Bruno Pereira
谢谢你提供关于sshpass的信息,我以前从未听说过它。 - Panther
8SSH密钥是对这个问题的“正确”答案,但在无法更改远程服务器上的身份验证方法时,sshpass是一个非常有用的技巧! - Jacob Krall
10这非常危险,你会将连接到的主机的明文密码保存在bash_history或其他地方。 - kappa
如果您以root身份运行命令,它是否仍然存在危险?如果是的话,我想任何事情都有可能。 - userDepth
@kappa 在命令前加一个空格(例如 _sshpass,其中 _ 表示空格),以避免密码出现在 bash 历史记录中。 - WinEunuuchs2Unix

Disable Password Authentication

Because a lot of people with SSH servers use weak passwords, many online attackers will look for an SSH server, then start guessing passwords at random. An attacker can try thousands of passwords in an hour, and guess even the strongest password given enough time. The recommended solution is to use SSH keys instead of passwords. To be as hard to guess as a normal SSH key, a password would have to contain 634 random letters and numbers. If you'll always be able to log in to your computer with an SSH key, you should disable password authentication altogether.

If you disable password authentication, it will only be possible to connect from computers you have specifically approved. This massively improves your security, but makes it impossible for you to connect to your own computer from a friend's PC without pre-approving the PC, or from your own laptop when you accidentally delete your key.

It's recommended to disable password authentication unless you have a specific reason not to.

To disable password authentication, look for the following line in your sshd_config file:

#PasswordAuthentication yes

replace it with a line that looks like this:

PasswordAuthentication no

Once you have saved the file and restarted your SSH server, you shouldn't even be asked for a password when you log in.

https://help.ubuntu.com/community/SSH/OpenSSH/Configuring#disable-password-authentication


2这是最基本的正确答案,对于安全来说非常好!另外禁用root登录也是一个很好的选择。 - FreeSoftwareServers
PasswordAuthentication no会影响所有用户吗?如果不是的话,我在测试时如何关闭普通用户的密码验证,同时保持root用户的密码验证不变?我真的不想搞砸了,完全被锁在外面。 - Adam
保持一个ssh会话打开,这样你就可以改回来。你想禁用密码和root用户。是的,你可以搞砸它。别这样做 ;) - Thufir
1在ssh过程中,我遇到了一个错误Permission denied (publickey),并且PasswordAuthentication no。我应该怎么办?我需要在另一台主机上更改PasswordAuthentication no吗? - ParisaN

这个解决方案专门针对使用Windows系统的用户,用于通过ssh远程登录他们的云主机,包括AWS Cloud和GCE Cloud上的云镜像。
免责声明:
最近使用了这个解决方案来远程登录在GCE上新部署的虚拟机镜像。

使用的工具:

  1. puttygen puttygen下载
  2. winscp winscp下载

执行步骤:

  1. 使用puttygen生成公钥/私钥对。
  2. 将公钥上传到云端或远程服务器。

如何操作:

1. 生成密钥对或使用现有的私钥

如果您拥有私钥:

打开puttygen,点击加载按钮,选择您的私钥(*.pem)文件。


如果您没有私钥: 打开 puttygen, 在参数部分中选择所需的密钥类型 SSH2 DSA(您也可以使用 RSA 或 DSA)。重要的是,您需要将密码字段留空。 点击生成并按照说明生成(公钥/私钥)键对。

Sample Key Generation pic

(来自来源1,下面给出链接)
2. 创建一个新的“authorized_keys”文件(使用记事本)
从PuTTY密钥生成器的“用于粘贴到OpenSSH authorized_keys文件的公钥”部分复制您的公钥数据,并将密钥数据粘贴到“authorized_keys”文件中。
确保这个文件中只有一行文本。

3. 将密钥上传到Linux服务器

  • 打开WinSCP,
  • 选择SFTP文件协议,并使用您的ssh凭据登录。
  • 成功后,您将在远程机器上看到主目录结构。

上传 authorized_keys 文件到远程机器的主目录。
4. 设置适当的权限
创建 .ssh 目录(如果不存在)
authorized_keys文件复制到.ssh目录中。
(这将替换任何已存在的authorized_keys文件,请注意此事)。
如果文件已存在,则只需将该文件的内容添加到现有文件中。

运行命令设置权限:

sudo chmod 700 .ssh && chmod 600 .ssh/authorized_keys

现在,您将能够每次都无需输入凭据就可以通过SSH远程登录到机器。
进一步阅读:
- 生成和上传Windows下的SSH密钥 - OpsenSSH密钥证书认证PEM PUB CRT

如果您创建了一个公共/私有密钥对并使用我们新创建的公共密钥登录,您将不需要输入密码。根据您的密钥环和/或ssh代理的配置,您可能需要使用密码保护您的密钥。
这里是其中一个简短的操作指南,对于您来说非常重要的是,生成的私钥保持私有!您永远不应该与任何人分享它或以任何方式访问它。
此命令在~/.ssh/中生成一个相当强大的密钥:
ssh-keygen -b 4096

~/.ssh/目录下,您会找到您的公钥文件id_rsa.pub。将其内容通过可传输媒介(例如U盘)添加到服务器的authorized_keys文件中,或者在服务器上暂时启用密码验证,然后使用ssh-copy-id ~/.ssh/id_rsa.pub username@server命令进行复制,之后再次禁用密码验证。
如果您选择为密钥设置了密码(在第一步中),您可以使用ssh-agent或Ubuntu密钥环来本地保护该密码,以免每次都需要输入。

无需提供密码的远程登录/复制

用于远程登录和远程复制的应用程序sshscp允许您在不提供密码的情况下与远程主机通信。这需要您按照下面描述的身份验证过程进行操作。在此,客户端指的是您所在的计算机,服务器指的是您想要无需提供密码登录的计算机。身份验证过程的步骤如下:

  1. 运行ssh-keygen生成私钥和公钥,除非您的计算机上已经完成了此操作。这些密钥存储在$HOME/.ssh目录中的文件中。
  2. 将公钥文件的内容追加到服务器上的$HOME/.ssh/authorized_keys$HOME/.ssh/authorized_keys2文件中。

有三种不同类型的身份验证协议。在运行ssh-keygen时,您需要指定所需的类型:

SSH协议版本1,RSA1:这是默认选择,会生成identity文件(私钥,应该使用chmod 0700命令确保该文件对其他人不可读)和identity.pub文件(公钥)。
SSH协议版本1,RSA:通过运行ssh-keygen -t rsa命令获得,会生成id_rsa文件(私钥)和id_rsa.pub文件(公钥)。
SSH协议版本1,DSA:通过运行ssh-keygen -t dsa命令获得,会生成id_dsa文件(私钥)和id_dsa.pub文件(公钥)。
在运行ssh-keygen时,您可以依赖默认答案(即不设置密码)。这使得整个设置过程简单,但也不安全。

您可以通过选项指定要使用的密钥类型给sshssh -1强制使用RSA1密钥(协议版本1),而ssh -2强制ssh仅尝试使用RSADSA密钥(协议版本2)。在下面的示例中,我们生成并安装了远程主机上的RSA1DSA密钥,以便您拥有更多的灵活性。您可以在.ssh目录中创建一个配置文件,并添加以下行:

Protocol 1,2

这使得 "ssh" 在尝试 "RSA1"(协议版本1)连接之前,先尝试 "RSA/DSA"(协议版本2)连接。
使用 RSA1 密钥
remote=user@remotehost   # fill in correct user and remotehost names
cd $HOME/.ssh
# create .ssh on remote host if it is non-existing:
ssh $remote 'if [ ! -d .ssh ]; then mkdir .ssh; fi' 
# copy RSA1 key: 
scp identity.pub ${remote}:.ssh
ssh $remote "cd .ssh; cat identity.pub >> authorized_keys"

使用DSA密钥
remote=user@remotehost   # fill in correct user and remotehost names
cd $HOME/.ssh
# create .ssh on remote host if it is non-existing:
ssh $remote 'if [ ! -d .ssh ]; then mkdir .ssh; fi' 
# copy DSA key: 
scp id_dsa.pub ${remote}:.ssh
ssh $remote "cd .ssh; cat id_dsa.pub >> authorized_keys2"

如果在生成密钥时没有使用口令,那么你只需要做这些。通过运行ssh $remote命令,测试连接并查看是否可以无需输入密码登录(你可能需要使用-1或-2作为ssh的选项)。当然,这个过程可以重复用于任何你想要登录的机器。
如果你使用了口令,你将需要运行程序ssh-agent来启动一个特殊的shell,然后运行ssh-add来注册你的密钥/口令组合与sshd。请参考这些程序的手册获取更多信息。
自动化免密码连接的脚本:ssh-no-password.sh
#!/bin/sh

# create ssh connections without giving a password

if [ $# -lt 1 ]; then
  echo Usage: $0 username@remotehost
  exit
fi
remote="$1"  # 1st command-line argument is the user@remotehost address
this=$HOST   # name of client host

# first check if we need to run ssh-keygen for generating
# $HOME/.ssh with public and private keys:
if [ ! -d $HOME/.ssh ]; then
  echo "just type RETURN for each question:" # no passphrase - unsecure!!
  # generate RSA1, RSA and DSA keys:
  echo; echo; echo
  ssh-keygen
  echo; echo; echo
  ssh-keygen -t rsa
  echo; echo; echo
  ssh-keygen -t dsa
else
  # we have $HOME/.ssh, but check that we have all types of
  # keys (RSA1, RSA, DSA):
  if [ ! -f $HOME/.ssh/identity ]; then
     # generate RSA1 keys:
     echo "just type RETURN for each question:" # no passphrase - unsecure!!
     ssh-keygen
  fi
  if [ ! -f $HOME/.ssh/id_rsa ]; then
     # generate RSA keys:
     echo "just type RETURN for each question:" # no passphrase - unsecure!!
     ssh-keygen -t rsa
  fi
  if [ ! -f $HOME/.ssh/id_rsa ]; then
     # generate DSA keys:
     echo "just type RETURN for each question:" # no passphrase - unsecure!!
     ssh-keygen -t dsa
  fi
fi


cd $HOME/.ssh

if [ ! -f config ]; then
  # make ssh try ssh -1 (RSA1 keys) first and then ssh -2 (DSA keys)
  echo "Protocol 1,2" > config
fi

# copy public keys (all three types) to the destination host:

echo; echo; echo
# create .ssh on remote host if it's not there:
ssh $remote 'if [ ! -d .ssh ]; then mkdir .ssh; fi' 
# copy RSA1 key: 
scp identity.pub ${remote}:.ssh/${this}_rsa1.pub
# copy RSA key:
#scp id_rsa.pub ${remote}:.ssh/${this}_rsa.pub
# copy DSA key:
scp id_dsa.pub ${remote}:.ssh/${this}_dsa.pub
# make authorized_keys(2) files on remote host:

echo; echo; echo
# this one copies all three keys:
#ssh $remote "cd .ssh; touch authorized_keys authorized_keys2; cat ${this}_rsa1.pub >> authorized_keys; cat ${this}_rsa.pub >> authorized_keys2; cat ${this}_dsa.pub >> authorized_keys2;"
# this one copies RSA1 and DSA keys:
ssh $remote "cd .ssh; touch authorized_keys authorized_keys2; cat ${this}_rsa1.pub >> authorized_keys; cat ${this}_dsa.pub >> authorized_keys2;"

echo; echo; echo
echo "try an ssh $remote"

复制自: http://folk.uio.no/hpl/scripting/doc/ssh-no-password.html


补充一些内容:
Mac默认情况下没有`ssh-copy-id`,您需要自己安装它: ``` curl https://raw.github.com/beautifulcode/ssh-copy-id-for-OSX/master/ssh-copy-id.sh -o /usr/local/bin/ssh-copy-id chmod +x /usr/local/bin/ssh-copy-id ```
在这里找到更多信息:https://github.com/beautifulcode/ssh-copy-id-for-OSX 如果你已经进行了端口转发,命令应该是这样的: ssh-copy-id "not-marco@127.0.0.1 -p 2222"
请注意,引号是必要的。

我想为那些可能发现即使他们已经阅读了这里的所有答案,但仍然需要输入密码的人添加一个答案,因为您将IdentitiesOnly设置为是。而且这里的答案可以节省您管理多个密钥(无论是用于git还是服务器)的时间。
在我生成了密钥并将其复制到服务器之后:
ssh-keygen  # change the file to /home/yourname/.ssh/something
ssh-copy-id -i ~/.ssh/something.pub lerner@192.168.20.160

我发现它不起作用。
然后我去检查了客户端的~/.ssh/config文件,底部看到了这个:
Host *
IdentitiesOnly yes

然后我在上面添加这个:
Host somename
HostName 192.168.20.160
User lerner
IdentityFile ~/.ssh/something

我只需要输入ssh somename就可以登录。
然后,您可以使用您喜欢的名称添加多个SSH密钥,您只需要将上述四行设置添加到配置文件中。
Host是您以后连接服务器时要输入的名称;HostName是服务器的IP地址;User是您登录服务器的用户名;identityfile是存储您生成的密钥的文件。