SSH 便捷登录配置

2016-01-22 linux ssh

通常在一个 ssh 链接中,需要指定用户名、主机名、主机端口号、配置参数等信息,如果每次登陆一台主机都要输入,那么就会变的非常麻烦,而且一些 IP 地址通常又非常难记。

为此,我们可以通过 OpenSSH 的客户端配置文件简化我们的登陆方式,下面简单介绍下。

公私钥免密认证

通过公私钥可以做到免密码,原理也很简单,用户将公钥保存在服务器上,登录时,服务端发送一段随机字符串,用户用私钥加密后再发回来,服务端用公钥解密,成功就证明用户是可信的,直接登录 shell,不再要求密码。

简单来说,生成一个密钥对,将公钥传送到服务器端,保存在 AuthorizedKeysFile 配置项指定的文件。

实践

可以通过如下步骤执行。

1. 服务端设置

在服务器端,首先确认 /etc/ssh/sshd_config 这个文件,检查下面几行是否有效。

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

2. 生成公私钥

直接通过 ssh-keygen 生成公私钥密码对即可。

$ ssh-keygen [-t rsa/dsa]
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -C "foobar@kidding.com"
参数:
    -t:   加密类型
    -f:   指定输出文件
    -N:   通过该密码加密私钥,为空则会自动登陆
    -C:   注释,通常为邮箱名称,会保存在公钥中

密钥对默认保存在 .ssh/ 目录下,包括了 id_rsa(私钥) id_rsa.pub(公钥),其它常用的加密方式还包括了 RSA DSA ECDSA ED25519 。

3. 将公钥上传到服务器

将公钥上传到服务器,此时会保存到需要免密码登陆用户 (在此为 foobar) 的 $HOME 目录下,方法很多,可以手动复制,也可以通过 scp 或者专有的 ssh-copy-id 命令。

$ cat ~/.ssh/id_rsa.pub | ssh foobar@remote-server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
$ scp ~/.ssh/id_rsa.pub foobar@remote-server-ip:~
$ ssh-copy-id -i ~/.ssh/id_dsa.pub foobar@remote-server-ip

配置文件中通过 AuthorizedKeysFile 指定公钥保存的文件名,一般是 .ssh/authorized_keys 文件,然后直接添加到该文件中即可,需要注意如下权限。

$ chmod 700 ~/.ssh/
$ chmod 644 ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/id_rsa

4. 登陆

如果使用私钥登录多台主机,可以通过 -i 选项指定私钥文件。

$ ssh -i id_rsa user-name@remote-server-ip
$ ssh -o PreferredAuthentications=publickey remote-server-ip -p 2880 -l user-name

如果是初次登陆时,会提示是否将对应的主机添加到 known_hosts 文件中,可以通过如下命令自动添加,无需交互。

$ ssh -T -o StrictHostKeyChecking=no remote-server-ip 'date'

安全相关

在生成密钥对时,如果密码没有输入,那么可以自动登陆,不过同样会导致当有人获取了该私钥后,可以登陆你配置的所有服务器。为此,为了保证私钥安全,生成密钥对时,最好指定密码。

----- 修改密码,如果设置为空则无密码
$ ssh-keygen -p -f id_rsa

不过这也导致了每次登陆时需要输入 私钥保护密码,会产生与之前相同的问题。

客户端配置

每次通过 ssh 登陆时,通常需要按照如下方式,指定用户名、主机、端口号,如果拥有多个 ssh 账号,那么要记住每个 ssh 账号的参数会非常麻烦。

$ ssh foobar@192.168.9.123 -p 2222

常用参数:
   -p:  指定端口
   -i:  如果通过公私钥认证,则通过该参数指定私钥
   -v:  调试,用于查看认证过程
   -o:  指定参数,例如-o ServerAliveInterval=60

实际上,对于 OpenSSH 客户端,可以通过配置文件简化登陆。

OpenSSH 客户端会使用 ~/.ssh/config 用户配置文件,也可使用全局配置 /etc/ssh/ssh_config,如果没有该文件则需要手动创建,该文件中的配置项通过 Key = Value 格式进行设置。

通过如下的方式指定别名,可以支持通配符 *%,注意,配置项大小写不敏感,值大小写敏感,而且注释只支持行首的注释。

Compression yes                  # 全局配置,与下面方式相同
Host *                           # 对于所有主机通用配置项
    ServerAliveInterval 60       # 防止因为空闲链接断开,每隔60秒发送一次请求,从而保持连接
    ServerAliveCountMax 3        # 发送请求后,如果服务端连续超过3次没有响应,则自动断开
    StrictHostKeyChecking no     # 默认首次添加到known_hosts时会有提示信息,配置为自动添加
    Protocol 2                   # 使用协议版本V2

Host mysql                       # 登陆时简化MySQL主机的配置
    HostName 192.168.9.123       # 指定服务器的IP,如果与上述的Host参数相同,则可以忽略
    User foobar                  # 登陆用户名
    Port 2222                    # 登陆使用端口号,默认22
    IdentityFile ~/.ssh/mysql    # 如果通过公私钥认证方式,指定私钥文件地址

Host dev backup www* mail        # 可以指定多个甚至是通配符
    HostName %h.example.com      # 利用上述的Host作为参数

例如,上述的 mysql 设置,可以直接通过 ssh mysql 命令登陆,而且 scp 等,同样可以如此使用。

另外,对于上述的最后一个示例,需要简单说明下,如果是通过 ssh dev 命令登陆,那么实际登陆时对应的主机名为 dev.example.com,以此类推。

代理设置

为了安全设置,通常防火墙只允许 80/22 端口访问,假设该服务器同时部署了 MySQL 服务,那么我们就无法通过笔记本进行调试。当然可以通过 ssh 的本地代理实现,设置如下:

$ ssh -f -N -L 9906:127.0.0.1:3306 foobar@database.example.com

如上,使得本地访问 9906 端口时,会将请求转发到 database.example.com127.0.0.1:3306,也就是对应的 MySQL 服务器了。同样可以通过如下方式简化。

Host tunnel
    HostName database.example.com
    IdentityFile ~/.ssh/foobar.example.key
    LocalForward 9906 127.0.0.1:3306
    User foobar

然后通过 ssh -f -N tunnel 命令登录即可。

共享连接

当登陆一台服务器后,可以通过共享链接实现免登陆,也就是说第一次登陆之后,后面的会自动登陆。需要在添加配置文件 ~/.ssh/config(600) 中添加如下内容。

host *
    ControlMaster auto                     # 复用之前链接
    ControlPath /tmp/ssh_mux_%r@%h:%p      # 如果不使用该参数只能是最后一个免登
    ControlPersist 4h                      # 默认直接退出,该参数指定4小时后退出

此时会在 /tmp 目录下创建 ssh_mux 前缀的 sock 文件,它记录了你目前登录到的机器,这样的话,你登录同样的机器就会重用同一个链接了。

ssh-agent

为了解决上述的问题,可以使用 ssh-agent,这是一个守护进程,设计它的唯一目的就是对解密用的专用密钥进行高速缓存,包括进行私钥转发。

ssh 支持与 ssh-agent 通信,允许 ssh 建立新连接时自动获取解密的专用密钥;你所需要做的就是,使用 ssh-add 命令把密钥添加到 ssh-agent 的高速缓存中即可。

工作原理

在 CentOS 中,会默认启动 ssh-agent 服务,当然,也可以手动启动;此是会输出一些信息,包括两个重要的环境变量 SSH_AUTH_SOCK (ssh/scp用来连接的套接字) 和 SSH_AGENT_PID

可以通过 ssh-add id_rsa 将私钥添加到 agent 中,后续 ssh、ssh-add、scp 等命令就会利用上述的环境变量与 ssh-agent 进行交互,获取对应的私钥信息,如果对私钥进行了加密,那么后续请求就无需再输入密码。

代理转发

ssh agent forwarding

简单来说,在 X 机器上运行 ssh-agent 代理来管理私钥,然后通过 X 机器 ssh 登录到 Y 机器,这样就能让 Y 机器上的 ssh 客户端也能使用到所有 X 机器上的 ssh-agent 所管理的所有私钥。

----- 在X节点上配置/etc/ssh/ssh_config,增加允许Agent转发
ForwardAgent yes

----- 在Y的/etc/ssh/sshd_config配置文件添加,需要重启sshd服务端
AllowAgentForwarding yes

修改完成之后,在 Y 机器上,可以通过 ssh-add -l 命令查看到 X 上的密钥信息。

其原理是,Y 机器上的 ssh 客户端会跟 Y 机器上 sshd 服务器请求私钥,因为已经从 X 登录到 Y 上,X 的 ssh 客户端和 Y 上的 sshd 服务器建立了一条连接,通过这条连接,请求被转发给了 X 上的 ssh 客户端,最终传递给 X 上的 ssh-agent,这样请求的结果反向传递回去。

常用命令

可以通过 ssh-add 管理私钥,常用命令参数如下:

  • -L 列出所缓存的私钥信息,包含了详细信息;
  • -l 列出所缓存的 SHA256 信息;
  • -D 清空缓存中的密码,此时如果登陆则需要使用之前设置的私钥保护密码;
  • -X/x 对agent加锁,不知道具体的作用,仍然可以免密码登陆。
----- 启动并设置环境变量
$ eval $(ssh-agent)

----- 添加并查看私钥,添加时需要输入密码
$ ssh-add YourSecretFile
$ ssh-add -l