通过 SSH(Secure Shell)登录 Linux 服务器常见的认证方式有密码和证书两种。从安全角度考虑,大家都推荐用证书登录。第一次在服务器上配置 SSH 使用证书登录,并制作证书然后登录成功还是费了不少力气。配置证书登录 SSH 的过程还挺复杂。
记录配置 SSH 证书并从 Windows 系统中使用 PuTTY 和 FileZilla 登录的操作过程以方便下次使用。
0. 配置 SSH 证书登录的流程¶
- 配置服务器上的 SSH 为证书登录模式。
- 客户端生成证书: 私钥(private key)和公钥(pubkey)。
私钥留在客户端,需要安全保存: 一般会设置一个密码,可能还需要加密密钥文件。如果对自己电脑里存的文件的安全有信心,就不信要设置密码了。而如果设置了密码,以后每次使用此私钥登录服务器的时候都需要先输入密码解开私钥。(有时候为了避免麻烦,而又不是对这种安全性有特别高的要求就*懒得*设置密码了。)
公钥上传并添加到服务器上 SSH 配置指定的文件中,使之被信任。
提示:虽然同一对私钥/公钥可重复用于登录不同的服务器,但是基于安全考虑,一般需要针对不同服务器单独生成各自的私钥/公钥。
个人来讲,在 Windows 下使用 SSH 登录服务器主要涉及到两种特殊软件: PuTTY 和 FileZilla。
如果要使用 FileZilla 的 sftp 登录服务器,因为 FileZilla 使用 putty 连接 sftp 服务器,所以需要在 putty 的 default settings -> ssh -> Auth 中加上需要的私钥并保存就可以了。新版本已经在新建服务器那里增加了使用 key 登录的选项(文件 -> 站点管理器,新建站点时协议选 SFTP,登录类型选证书登录,然后点击右边的“浏览”选择自己的私钥即可(下文中的 id_rsa))。
如果使用 PuTTY 登录服务器,需要在 putty 的 default settings -> ssh -> Auth 中加上需要的私钥并保存,然后再登录。
1. 客户端生成私钥/公钥¶
使用私钥/公钥(密钥对,都是成对的)就需要考虑密钥本身的安全性,除了妥善保管之外,还有加密及验证环节的可靠性。根据这里的介绍(Secure Secure Shell),目前可以安全的选择 ed25519 和 rsa 两种加密系统。当然对应的 SSH 服务器也要配置使用这两种密钥交换系统。
Linux / Mac 命令行方式¶
公钥/私钥的生成是在客户端(需要用来登录服务器的用户自己的电脑),这样可以保证生成的私钥不在网络上传输。所以,在客户端,如果是 Linux 系统,运行以下两条中的任一指令(推荐第二条),
# ssh-keygen -t ed25519 -o -a 100 -C "Your comment here" # ssh-keygen -t rsa -b 4096 -o -a 100 -C "Your comment here"
以生成相应格式的证书。按提示操作即可。其中 -t 表示证书密钥类型;-C 表示给证书添加一句注释的话,一般用于标记证书所有者和用途,免得回头自己都忘了哪个证书是干什么的了。
提示的 passphrase 就是用来保护私钥的密码了,需要用一个包含特殊字符并有一定长度的密码,当然还得记住,否则就没法用它了。如果*不想设置密码短语*,就直接连续敲回车两次。
默认情况下,生成的密钥被保存在当前用户目录的 .ssh
目录下,两个文件: id_rsa
是私钥, id_rsa.pub
是公钥。建议给不同的证书单独设置不同的文件名,以方便后续的管理。这里作为例子就不改名字了,下面好叙述。
使用 Windows 下 PuTTY 生成密钥对¶
如果在 Windows 下,可以使用 PuTTY 相关的一个配套的 PuTTYgen(下载地址)来生成密钥对。最新的 PuTTY 是 0.65 版(还是 Beta 阶段)。双击 PuTTYgen 运行会打开窗口。
下面可以选择加密方式,默认是 SSH-2 RSA 即 rsa 方式; 旁边有位数可以选择,默认是 2048 位(现在大家已经开始使用 4096 位的了)。点击中间靠右侧的 Generate,然后在该窗口的上半部分空白处随意晃动鼠标,就能看到证书在根据这些随机的点产生,等进度条走完,密钥对产生,就到了下面的界面。
图中, 单击 Save public key 可以将公钥保存为文件(保存前最好将框框里面的文本文件复制出来放到一个文本文件中,后面会用到)。当然保存的公钥文件也可以使用 Windows 的记事本或 Notepad++ 之类的文本编辑器打开。上面保存的文件打开后内容是这个样子,
---- BEGIN SSH2 PUBLIC KEY ---- Comment: "rsa-key-20151019" AAAAB3NzaC1yc2EAAAABJQAAAQEAmmEZDOTuPdrARNCZjWyZfZcDRHm4oRjZN6fL WG8eNh1KhNJu1pPtFvhACaWVE0vBfPS/6UzDeClNk1DScMmYVsqgsqwrjazcS4ee NFT1A9B4MeppI2N7pa5Gsvq/iD3cQpzAmGv8IZl6Aqoujz0429+dCoeUW6L2Mu49 0+0A6MWhEh/GQWV/VpYwf/J1KxAWgGuNpeMONN9el2+BiCwJdhmKwQaXNcmdqVvZ Wdm+A//+1GWJqydDWmFgYj8yXOGIHNlS0bNtw0Mrq+GrXCGiJuPWEXNDIlVA5Pgn w+6Xd0zv1qgeGe1CpjZzV2e/bTlG9AHLumJ/uWhp7ZuMwsBq6Q== ---- END SSH2 PUBLIC KEY ----
而前面复制出来的公钥应该是这个样子(这才是实际的公钥,后面要使用的就是下面这段字符,而不是上面的),
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmmEZDOTuPdrARNCZjWyZfZcDRHm4oRjZN6fLWG8eNh1KhNJu1pPtFvhACaWVE0vBfPS/6UzDeClNk1DScMmYVsqgsqwrjazcS4eeNFT1A9B4MeppI2N7pa5Gsvq/iD3cQpzAmGv8IZl6Aqoujz0429+dCoeUW6L2Mu490+0A6MWhEh/GQWV/VpYwf/J1KxAWgGuNpeMONN9el2+BiCwJdhmKwQaXNcmdqVvZWdm+A//+1GWJqydDWmFgYj8yXOGIHNlS0bNtw0Mrq+GrXCGiJuPWEXNDIlVA5Pgnw+6Xd0zv1qgeGe1CpjZzV2e/bTlG9AHLumJ/uWhp7ZuMwsBq6Q== rsa-key-20151019
所以如果前面没有复制出来的话就要打开保存的公钥自己组合一下了。
其中,Key comment 是用来给这个公钥做个注释的,比如上面的 rsa-key-20151019 就是。这个东西不是公钥本身的一部分,可以根据需要修改,比如用自己的邮箱地址替换。
保存密钥(Save private key)前可输入或者不输入密码短语(Key passphrase)。当然安全的做法是使用。Key passphrase 和它下面的 Confirm passphrase 就是前面提到的保护私钥的密码短语了。最好是大小写字母混合数字,并加入特殊字符如 ! " £ $ % ^
等。如果不输入密码短语而直接保存私钥,会有让确认的提示。注意是“短语”,也就是可以是一串长长的话。但是使用现成的文本可能会在暴力尝试下被破解。
2. SSH 服务器配置¶
服务器上一般使用 OpenSSH 提供 SSH 登录服务。CentOS(其他 Linux 发行版可能会有不同) 上的服务器配置文件保存在下面这个文件里,
/etc/ssh/sshd_config
修改此文件,
# vim /etc/ssh/sshd_config
配置示例(这里拆成行或块来说明,按顺序往下找即可):
注:SSH 默认的配置文件里很多行都被注释掉了(即不起作用,标志是行首有个 # 号),希望让它起作用的话就要把改行行首的 # 删除。
a. 端口
端口,默认 22,建议自定义,比如 2222、1234、54321 等(一般高于 2000 而不能超过 65555),
Port 2222
特别注意:这里修改端口后*重启 sshd 服务之后*原来的 22 端口就不能连接了,所以在开启了防火墙(比如 CentOS 中的 iptables 或 FirewallD)的情况下,一定要把新端口添加了允许访问的列表里,免得将自己锁在了服务器外面!!!参考这里,在 Linux 命令行输入的指令为:
# firewall-cmd --zone=public --add-port=2222/tcp --permanent
b. 协议
下面继续修改 sshd 配置。如果没有特殊原因,不要用协议 1,所以启用下面的行,
Protocol 2
c. 登录控制
禁止 Root 账户登录,
PermitRootLogin no
不允许空密码登录,默认已经是 no,
PermitEmptyPasswords no
允许 SSH 登录的用户名/用户组。可以同时使用,也可以仅使用下面一种。
#AllowUsers user1 user2 AllowGroups ssh-users
使用用户组的好处是在更换用户、添加/删除用户的时候都需要维护此配置。所以建议用用户组来管理,有新用户产生,直接将它添加到这个附加用户组中就可以了。但是,如果这个服务器只有自己一个人用,那还是直接允许自己用的那个帐户就好了。
将用户添加到附加用户组参考这里。简单说就是,
# groupadd ssh-user # usermod -a -G ssh-user <username>
不让 sshd 去检查用户目录或某些重要档案的权限数据,这是为了防止用户将某些重要档案的权限设错。例如用户的 ~.ssh/ 权限设错时,某些特殊情况下会不许用户登录。
StrictModes no
d. 允许密钥登录
允许用户自行使用成对的密钥系统登录服务器,这里仅针对协议版本 2。用户自己生成的公钥数据就放置于相应的(服务器上该用户自己的)用户目录(例如,/home/luser1
)下的 .ssh/authorized_keys
文件里面,
RSAAuthentication yes PubkeyAuthentication yes AuthorizedKeysFile %h/.ssh/authorized_keys
e. 访问安全加固(可暂时忽略此项)
保存 protocol version 2 对应的服务器自己的 KEY,不同类型的 key 保存到不同的文件中(这里只启用前面提到的两种),
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 HostKey /etc/ssh/ssh_host_ed25519_key HostKey /etc/ssh/ssh_host_rsa_key
因为启用了 diffie-hellman-group-exchange-sha256
这个密钥交换算法,还需要修改 /etc/ssh/moduli
以增强其安全性。如果有这个文件(一般安装时都会有的),将此文件中的所有第 5 列数值小于 2000 的行删除。因为行比较多,用 awk 指令自动删除比较方便,
# awk '$5 > 2000' /etc/ssh/moduli > "${HOME}/moduli" # wc -l "${HOME}/moduli" # 确保删除之后该文件中还有内容,看此指令输出的数字大于 0 # mv "${HOME}/moduli" /etc/ssh/moduli
如果没有这个文件,就生成一个,
# ssh-keygen -G /etc/ssh/moduli.all -b 4096 # ssh-keygen -T /etc/ssh/moduli.safe -f /etc/ssh/moduli.all # mv /etc/ssh/moduli.safe /etc/ssh/moduli # rm /etc/ssh/moduli.all
生成这个可能需要的时间比较长。
f. 其它杂项
禁用密码登录方式(不禁用密码登录的时候也可以同时用证书登录;可先不禁用,以防止自己把自己关在服务器外面了),
PasswordAuthentication no ChallengeResponseAuthentication no
禁止图形界面转发及 TCP 转发,
#AllowTcpForwarding no #X11Forwarding no
要求记录详细日志,
LogLevel VERBOSE
允许使用 SFTP 子系统(FileZilla 要用这个),
Subsystem sftp /usr/local/ssh/libexec/sftp-server
3. 在服务器上加入用户公钥¶
在 1. 中生成的用户的公钥需要经由系统管理员(root)导入服务器上的 SSH 的信任证书列表里面;或者如果你已经在服务器上有了用户名可直接访问服务器,则将自己的公钥添加到自己的用户目录下的特定文件里即可。SSH 服务器会自动根据用户登录服务器使用的用户名到服务器上相应的用户目录里的 .ssh/authorized_keys
文件里寻找公钥。
注意下面的操作是服务器上的 luser1(替换成自己在服务器上的用户名) 来完成的,而不是管理员(root)。
例如,要将前面 rsa 制式的公钥(咱给他保存成 id_rsa.save
吧)(注意与 PuTTYgen 保存的 id_rsa.pub 的不同,如果错了会有 Server refused our key
的错误提示,因为 pubkey 不正确)放入用户 luser1 的证书列表中,可以,
# mkdir /home/luser1/.ssh # touch /home/luser1/.ssh/authorized_keys # touch 表示如果没有这个文件则创建它 # cat id_rsa.save >> /home/luser1/.ssh/authorized_keys # 表示将 id_rsa.save 的文件内容附加到后面那个文件的结尾
或者使用 echo 指令直接将*公钥的内容*附加到指定文件的结尾,
# echo "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAmmEZDOTuPdrARNCZjWyZfZcDRHm4oRjZN6fLWG8eNh1KhNJu1pPtFvhACaWVE0vBfPS/6UzDeClNk1DScMmYVsqgsqwrjazcS4eeNFT1A9B4MeppI2N7pa5Gsvq/iD3cQpzAmGv8IZl6Aqoujz0429+dCoeUW6L2Mu490+0A6MWhEh/GQWV/VpYwf/J1KxAWgGuNpeMONN9el2+BiCwJdhmKwQaXNcmdqVvZWdm+A//+1GWJqydDWmFgYj8yXOGIHNlS0bNtw0Mrq+GrXCGiJuPWEXNDIlVA5Pgnw+6Xd0zv1qgeGe1CpjZzV2e/bTlG9AHLumJ/uWhp7ZuMwsBq6Q== rsa-key-20151019" >> ~/.ssh/authorized_keys
注意上面的双引号(” “)也是不能少的;而 ~ 代表当前用户目录(即举例中的用户 luser1,所以这里说的是用 luser1 用户登录的情况),也可以用这个路径,
/home/luser1/.ssh/authorized_keys
修改文件访问权限(如果在 sshd_config 中配置了 StrictModes
为 yes
,那么这个就是必须的了,否则无法工作),
# chmod 700 /home/luser1/.ssh # chmod 600 /home/luser1/.ssh/authorized_keys
现在重启 SSH 服务,
# systemctl restart sshd
然后用户就可以用证书登录。
4. 用户使用证书登录¶
在 Linux 上,
ssh -i /path/to/private_key/id_rsa luser1@<ssh_server_ip> -p 2222
在 Linux 上也可以通过 ssh 的 config 文件来简化登录指令。修改 ~/.ssh/config
文件,使用类似下面的代码块来配置 Host。这个文件中可以配置多个 Host。例如,
Host myserver User luser Hostname <server_name> 或者 <server_IP> Port <server_ssh_port> ServerAliveInterval 30 IdentityFile /path/to/private_key/id_rsa Host anotherServer ... ...
这样前面的 ssh 登录语句就可以简化为,
# ssh myserver
在 Windows 上,使用 PuTTY 的话(截图可参考这里),
- 双击打开 putty;
- 右侧 Basic options for you PuTTY session 下面输入 IP,端口 Port,点选 SSH,然后输入个名字,如 ssh-to-server,保存 Save;
- 左侧 Category 下,依次点选 Connection,SSH,Auth,然后在其右侧的 Browse,选择前面产生的私钥 id_rsa,再单击下面的 Open 就会打开登录过程;
- 按提示输入要登录的用户名;
- 按提示输入私钥的保护密码短语(Key passphrase)即可登录。
使用 FileZilla 的话(参考这里):可以使用 Pagent(见putty下载页),也可以直接使用其本身提供了管理私钥的设置,比 putty 更简单。下面是使用 FileZilla 内置私钥管理器的步骤:
- 打开 FileZilla,在工具栏依次点击 Edit(编辑),Settings(设置)打开设置管理器;
- 在左侧列表中选中 SFTP,右侧显示了私钥管理界面;
- 单击 Add key file…(添加私钥文件),选择要使用的私钥,打开;
- 完成(单击左侧 OK 确定);
- 回到 FileZilla,配置相应的 SFTP 服务器:
- IP,Port(端口 )
- Protocol (协议)选 SFTP – SSH File Transfer Protocol
- Logon Type(登录方式)选 Normal
- User 后输入用户名
- Password(密码)留空
- 连接即可
- 如果单击 Connect(连接)后提示输入密码短语,那是私钥的保护密码
5. 附录¶
5.1 SSH 配置参数详解¶
来自:天堂鸟
/etc/ssh/sshd_config
文件常用参数:
# 1. 关于 SSH Server 的整体设定,包含使用的 port 啦,以及使用的密码演算方式 Port 22 # SSH 预设使用 22 这个 port,您也可以使用多的 port ! # 亦即重复使用 port 这个设定项目即可! Protocol 2,1 # 选择的 SSH 协议版本,可以是 1 也可以是 2 , # 如果要同时支持两者,就必须要使用 2,1 这个分隔了! #ListenAddress 0.0.0.0 # 监听的主机适配卡!举个例子来说,如果您有两个 IP, # 分别是 192.168.0.100 及 192.168.2.20 ,那么只想要 # 开放 192.168.0.100 时,就可以写如同下面的样式: ListenAddress 192.168.0.100 # 只监听来自 192.168.0.100 这个 IP 的SSH联机。 # 如果不使用设定的话,则预设所有接口均接受 SSH PidFile /var/run/sshd.pid # 可以放置 SSHD 这个 PID 的档案!左列为默认值 LoginGraceTime 600 # 当使用者连上 SSH server 之后,会出现输入密码的画面, # 在该画面中,在多久时间内没有成功连上 SSH server , # 就断线!时间为秒! Compression yes # 是否可以使用压缩指令?当然可以?! # 2. 说明主机的 Private Key 放置的档案,预设使用下面的档案即可! HostKey /etc/ssh/ssh_host_key # SSH version 1 使用的私钥 HostKey /etc/ssh/ssh_host_rsa_key # SSH version 2 使用的 RSA 私钥 HostKey /etc/ssh/ssh_host_dsa_key # SSH version 2 使用的 DSA 私钥 # 2.1 关于 version 1 的一些设定! KeyRegenerationInterval 3600 # 由前面联机的说明可以知道, version 1 会使用 # server 的 Public Key ,那么如果这个 Public # Key 被偷的话,岂不完蛋?所以需要每隔一段时间 # 来重新建立一次!这里的时间为秒! ServerKeyBits 768 # 没错!这个就是 Server key 的长度! # 3. 关于登录文件的讯息数据放置与 daemon 的名称! SyslogFacility AUTH # 当有人使用 SSH 登入系统的时候,SSH会记录资 # 讯,这个信息要记录在什么 daemon name 底下? # 预设是以 AUTH 来设定的,即是 /var/log/secure # 里面!什么?忘记了!回到 Linux 基础去翻一下 # 其它可用的 daemon name 为:DAEMON,USER,AUTH, # LOCAL0,LOCAL1,LOCAL2,LOCAL3,LOCAL4,LOCAL5, LogLevel INFO # 登录记录的等级!嘿嘿!任何讯息! # 同样的,忘记了就回去参考! # 4. 安全设定项目!极重要! # 4.1 登入设定部分 PermitRootLogin no # 是否允许 root 登入!预设是允许的,但是建议设定成 no! UserLogin no # 在 SSH 底下本来就不接受 login 这个程序的登入! StrictModes yes # 当使用者的 host key 改变之后,Server 就不接受联机, # 可以抵挡部分的木马程序! #RSAAuthentication yes # 是否使用纯的 RSA 认证!?仅针对 version 1 ! PubkeyAuthentication yes # 是否允许 Public Key ?当然允许啦!只有 version 2 AuthorizedKeysFile .ssh/authorized_keys # 上面这个在设定若要使用不需要密码登入的账号时,那么那个 # 账号的存放档案所在档名! # 4.2 认证部分 RhostsAuthentication no # 本机系统不止使用 .rhosts ,因为仅使用 .rhosts 太 # 不安全了,所以这里一定要设定为 no ! IgnoreRhosts yes # 是否取消使用 ~/.ssh/.rhosts 来做为认证!当然是! RhostsRSAAuthentication no # 这个选项是专门给 version 1 用的,使用 rhosts 档案在 # /etc/hosts.equiv配合 RSA 演算方式来进行认证!不要使用 HostbasedAuthentication no # 这个项目与上面的项目类似,不过是给 version 2 使用的! IgnoreUserKnownHosts no # 是否忽略家目录内的 ~/.ssh/known_hosts 这个档案所记录 # 的主机内容?当然不要忽略,所以这里就是 no 啦! PasswordAuthentication yes # 密码验证当然是需要的!所以这里写 yes ?! PermitEmptyPasswords no # 若上面那一项如果设定为 yes 的话,这一项就最好设定 # 为 no ,这个项目在是否允许以空的密码登入!当然不许! ChallengeResponseAuthentication yes # 挑战任何的密码认证!所以,任何 login.conf # 规定的认证方式,均可适用! #PAMAuthenticationViaKbdInt yes # 是否启用其它的 PAM 模块!启用这个模块将会 # 导致 PasswordAuthentication 设定失效! # 4.3 与 Kerberos 有关的参数设定!因为我们没有 Kerberos 主机,所以底下不用设定! #KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosTgtPassing no # 4.4 底下是有关在 X-Window 底下使用的相关设定! X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes # 4.5 登入后的项目: PrintMotd no # 登入后是否显示出一些信息呢?例如上次登入的时间、地点等 # 等,预设是 yes ,但是,如果为了安全,可以考虑改为 no ! PrintLastLog yes # 显示上次登入的信息!可以啊!预设也是 yes ! KeepAlive yes # 一般而言,如果设定这项目的话,那么 SSH Server 会传送 # KeepAlive 的讯息给 Client 端,以确保两者的联机正常! # 在这个情况下,任何一端死掉后, SSH 可以立刻知道!而不会 # 有僵尸程序的发生! UsePrivilegeSeparation yes # 使用者的权限设定项目!就设定为 yes 吧! MaxStartups 10 # 同时允许几个尚未登入的联机画面?当我们连上 SSH , # 但是尚未输入密码时,这个时候就是我们所谓的联机画面啦! # 在这个联机画面中,为了保护主机,所以需要设定最大值, # 预设最多十个联机画面,而已经建立联机的不计算在这十个当中 # 4.6 关于使用者抵挡的设定项目: DenyUsers * # 设定受抵挡的使用者名称,如果是全部的使用者,那就是全部 # 挡吧!若是部分使用者,可以将该账号填入!例如下列! DenyUsers test DenyGroups test # 与 DenyUsers 相同!仅抵挡几个群组而已! # 5. 关于 SFTP 服务的设定项目! Subsystem sftp /usr/lib/ssh/sftp-server
5.2 OTP¶
It is also possible to use OTP authentication to reduce the consequences of lost passwords. Google Authenticator is a nice implementation of TOTP, or Timebased One Time Password. You can also use a printed list of one time passwords or any other PAM module, really, if you enable ChallengeResponseAuthentication.
5.3 参考资料(文中已有链接的除外)¶
- CNBLOGS-ggjuchen: SSH 证书登录(实例详解)
- Reddit: Secure Secure Shell
- CentOS Wiki: Securing SSH
- DigitalOcean: Initial Server Setup with CentOS 7
本文发表于水景一页。永久链接:<https://cnzhx.net/blog/linux-server-ssh-key-auth-configuration/>。转载请保留此信息及相应链接。
引用通告: 运行 CentOS 6 的主机的磁盘因为空间占满而下线 | 水景一页