Linux Tools --- SSH
一、概要
1. 环境
(1) Rocky Linux 9.1
2. 概念
(1) SSH
SSH(Secure Shell)是用于两台计算机进行网络通信和数据传输的协议,使用SSH进行通信的两台计算机其通信内容已被加密,这意味着即便在不安全的网络环境中这也是一种可接受的通信方案。
SSH协议最著名的实现是Open SSH。SSH链接的默认端口是22。
(2) 本文概念
主机:是指我们运行SSH命令的机器;
目标主机:是指我们运行SSH命令需要连接的机器。
二、命令
1. ssh
(1) 连接目标主机
ssh <host(IP/Domain)>
(2) 使用指定用户名"userName"来连接目标主机"host":
ssh <userName>@<host(IP/Domain)>
相同的如下:
ssh -l <userName> <host(IP/Domain)>
(3) 在目标主机"host"上执行制定的命令"command"
ssh host command
比如,在example.com机器上执行"ls /tmp/doc"这条命令:
ssh example.com ls /tmp/doc
(4) 其他参数
-1:仅使用SSH v1;
-2:仅使用SSH v2;
-4:仅使用IPv4地址;
-6:仅使用IPv6地址;
-C:使用数据压缩;
-c:指定数据加密算法;
-F:指定配置文件,默认使用“~/.ssh/config”;
-p:指定要连接的远程机器端口号;
-q:静默模式;
详细可见SSH命令。
2. 不想每次SSH连接目标主机时输入密码
SSH支持公钥认证登录模式可以避免每次SSH连接时输入密码,该方案需要配置目标主机sshd;在主机上生成客户端密钥,并在目标主机上安装客户端密钥等步骤。
(1) 配置目标主机sshd
a. 编辑/etc/ssh/sshd_config
sudo vi /etc/ssh/sshd_config
b. 启用PubkeyAuthentication
PubkeyAuthentication yes
c. 使用root的key登录
需要确保配置文件中开启了以下项目:
PermitRootLogin yes
d. 重启sshd
sudo systemctl restart sshd
(2) 在主机上生成客户端密钥
使用ssh-keygen命令工具生成密钥,下面章节会讲到。
(3) 安装密钥
在目标主机上安装客户端密钥有两种方法:
一种是使用下面要讲的ssh-copy-id命令;
另一种是手动安装:
a. 读取公钥(*.pub文件,比如~/.ssh/id_rsa.pub)的内容:
cat ~/.ssh/id_rsa.pub
b. 将文件内容复制到目标主机的authorized_keys文件中
vi ~/.ssh/authorized_keys
c. 赋权
chmod 600 ~/.ssh/authorized_keys
3. ssh-keygen
SSH支持使用公钥加密技术校验请求连接的主机和用户。ssh-keygen是一个用于创建密钥对的工具。
(1) 格式
ssh-keygen [-f keyPath] [-t algorithm] [-b bits] [-q]
其他参数可以参考:ssh-keygen
(2) 最简单的方式
ssh-keygen
运行之后,系统会提示你输入密钥存储的文件路径和密钥密码,默认状态下的存储路径为:
密钥:~/.ssh/id_rsa
公钥:~/.ssh/id_rsa.pub
(3) 密钥算法
a. rsa,目前最常用的密钥算法,建议密钥长度至少2048位,最好是4096位;
b. dsa,一个古老的美国政府使用的算法,已经不再被建议使用;
c. ecdsa,美国政府使用的新一代密钥算法;
d. ed25519, 这是一个加入到OpenSSH中的新算法,并不被所有的客户端支持,所以慎用。
制定算法的格式为:
ssh-keygen -t rsa
(4) 指定密钥长度
ssh-keygen -t rsa -b 4096
(5) 赋权
chmod 700 ~/.ssh
4. ssh-copy-id
ssh-copy-id是OpenSSH的一部分,它可以将主机密钥安装在目标主机上的授权密钥库中(authorized key)。
(1) 格式
ssh-copy-id [-f] [-n] [-i identity file] [-p port] [-o ssh_option] [user@]hostname
-f: 强制添加密钥到目标主机,可能导致目标主机密钥重复;
-i: 指定需要添加到目标主机的密钥文件,强烈建议使用该参数,如果该参数缺省ssh-copy-id将会复制本地所有的密钥到目标主机,此举可能引起风险;
-n: 打印出所有需要安装的密钥,但不会真正执行安装;
-p: 指定ssh连接的端口号,默认为22;
更多参数可参考: ssh-copy-id
(2) 安装ssh密钥到目标主机
ssh-copy-id -i ~/.ssh/mykey user@host
该命令会使用"user"登录目标主机"host"(可能需要输入密码),然后复制密钥到目标主机并添加到authorized_keys文件中。
(3) 执行后的测试
ssh -i ~/.ssh/mykey user@host
ssh host
ssh user@host
在Client上运行以上命令,此时应该不再需要"user"的密码即可连接目标主机"host"。
5. scp (Secure Copy)
scp用于在不同主机之间复制文件,它使用SSH协议进行文件传输。
(1) 格式1: 本地到远程
从本地复制到目标主机:
scp file host[:path]
path: 可以是目录或者文件,或缺省;
(2) 格式2:远程到本地
scp host:source [target]
source: 可以是文件,也可以是目录;
target: 与source想对应,缺省为当前目录;
-r: 如果source是目录,则复制整个目录到target,并在target下创建新的目录;
其他参数可参考:scp
三、应用
1. 配置putty使用密钥连接远程主机
(1) 生成密钥
双击PUTTYGEN.EXE,点击"Generate"按钮,此时会出现滚动条需要鼠标不断移动,程序需要捕获鼠标轨迹形成随机数。
(2) 点击"Save private key"将私钥保存至C:/[User]/.ssh目录下;
(3) 复制公钥到目标主机的"~/.ssh/authorized_keys"文件中。
这里需要注意,如果点击"Save public key"保存公钥到本地比如rsa.pub,rsa.pub里面的内容和上图中"Public key for pasting into OpenSSH authorized_keys"中的内容格式是不同的,不能将rsa.pub的内容直接复制到目标主机的“~/.ssh/authorized_keys”文件中,否则SSH连接会失败(如下图)。
(4) 打开“PUTTY.EXE”,进入"Category->Connection->Data",设置用户名,该用户名需要与(3)中配置的Linux用户相匹配。
比如,在(3)中将公钥复制到root用户下的"~/.ssh/authorized_keys"文件中,那么这里的Auto-login username就是root.
(5) 进入"Category->Connection->SSH->Auth"页面,设置私钥地址:
(6) 进入"Category->Session",输入"Host Name",点击"Open"即可实现无需密码建立SSH连接。
2. 远程执行命令
(1) 远程执行单条命令
ssh userName@host 'Command1'
该命令将使用"userName"登录远程主机"host",并执行"Command1"。
(2) 远程执行多条命令
ssh userName@host 'Command1; Command2; Command3'
该命令将使用"userName"登录远程主机"host",并依次执行"Command1", "Command2", "Command3"。
(3) 远程执行sudo命令
ssh -t userName@host 'sudo command1 arg1 arg2'
该命令将使用"userName"登录远程主机"host",执行"Command1"。
(4) 远程执行su命令
ssh userName@host su --session-command="/path/to/command1 arg1 arg2"
该命令将使用"userName"登录远程主机"host",切换到root账户再执行"command1",注意"/path/to/command1"是指远程主机的地址。
(5) 远程执行多条本地命令
假设管理员在主机A上执行ssh命令,通过ssh连接机器B,A机器上有若干条命令需要通过该ssh链接在B机器上执行。
a. 首先在A机器将需要执行的命令存储到command.txt中:
sudo vi command.txt
初始化:
date uptime df -H
b. 远程执行
ssh userName@host < command.txt
(6) 以本地脚本方式执行远程命令
a. 创建脚本
sudo vi script.sh
b. 初始化script.sh
#!/bin/bash _remote="192.168.0.1" _user="tester" echo "Local system name: $HOSTNAME" echo "Local date and time: $(date)" echo "*** Running commands on remote host named $_remote ***" ssh -T $_remote <<'EOL' now="$(date)" name="$HOSTNAME" up="$(uptime)" echo "Server name is $name" echo "Server date and time is $now" echo "Server uptime: $up" echo "Bye" EOL
c. 赋权
chmod +x script.sh
d. 执行
./script.sh
四、参考
1. 官方
https://www.ssh.com/academy/ssh/command
https://www.ssh.com/academy/ssh/keygen
https://www.ssh.com/academy/ssh/copy-id
https://www.ssh.com/academy/ssh/scp
2. 其他
https://man7.org/linux/man-pages/man1/ssh.1.html
https://www.ucl.ac.uk/isd/what-ssh-and-how-do-i-use-it
https://www.techtarget.com/searchsecurity/tutorial/How-to-use-PuTTY-for-SSH-key-based-authentication
https://www.techotopia.com/index.php/Configuring_SSH_Key-based_Authentication_on_RHEL
https://linuxize.com/post/how-to-setup-passwordless-ssh-login/
https://www.cyberciti.biz/faq/unix-linux-execute-command-using-ssh/