我是基于ChatGPT-turbo-3.5实现的AI助手,在此网站上负责整理和概括文章
本文介绍了SCP和SSH协议的原理与应用。SCP基于SSH实现安全文件传输,支持文件和目录的跨服务器拷贝,资源消耗低,适用于高效数据迁移。SSH采用非对称加密确保通信安全,支持公钥认证、免密登录和多服务器配置,提升了远程管理的便利性和安全性。文章还详细说明了SSH的开启、密钥生成及配置方法,具有较高的实用价值。
# scp传输文件
SCP (Secure Copy Protocol)是linux系统下基于ssh登录进行安全的远程文件拷贝的命令。与scp相似的命令是cp,但是cp只能本机拷贝而不能跨服务器,因此需要与ssh合作构成scp命令。远程拷贝的命令还有rsync,scp消耗资源少,不会提高多少系统负荷,在这一点上,rsync就远远不及它了。rsync比scp会快一点,但当小文件多的情况下,rsync会导致硬盘I/O非常高,而scp基本不影响系统正常使用。
-
传递文件到远程
scp [选项] local_file remote_username@remote_ip:remote_file -
传递文件夹到远程
scp [选项] local_folder remote_username@remote_ip:remote_folder -
复制远程文件到本地(只是调换下文件参数位置即可)
scp remote_username@remote_ip:remote_file local_file -
常用选项
-P指定端口(默认22)-r递归复制目录-C启用压缩-v显示详细传输信息
-
我们直接使用
scp来跨机器拷贝文件,会提示输入密码:# 提示输入server端服务器的work用户密码 [[email protected] ~]$ scp test.php [email protected]:/home/work [email protected]'s password:scp是先使用ssh连接服务端机器后,再使用网络来执行远程拷贝(cp)。 -
实用示例
# 复制文件到远程主机的/home目录(使用默认22端口) scp file.txt [email protected]:/home/ # 复制目录到远程(使用自定义端口2222) scp -P 2222 -r mydir/ [email protected]:/opt/ # 从远程下载文件到当前目录 scp user@server:/var/log/app.log . # 加速SCP传输 # -C 压缩选项 # -c [email protected] 加密算法选择 # 对于内网传输,可以尝试更快的算法如 [email protected] scp -C -c [email protected] largefile.tar.gz user@host:~ # 等效的rsync命令 -a 是归档模式,-z 启用压缩 rsync -az --rsh='ssh -c [email protected]' largefile.tar.gz user@host:~
# SSH (Secure Shell)
Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中创建安全隧道来实现SSH客户端与服务器之间的连接。虽然任何网络服务都可以通过SSH实现安全传输,SSH最常见的用途是远程登录系统,人们通常利用SSH来传输命令行界面和远程执行命令。telnet使用23号端口,所有的信息,包括用户名和密码都是明文传输;而ssh使用22号端口,所有的信息都会被加密传输,安全性得到了很大的提高。
-
ssh使用十分简单,选择以什么用户连接哪台机器,然后输入密码即可:$ssh [选项] user@hostname [命令] user@hostname's password: -
常用选项
-p指定端口-i指定私钥文件-X启用X11转发-L本地端口转发-R远程端口转发
-
实用示例
# 基本登录 ssh [email protected] # 使用非标准端口登录 ssh -p 2222 [email protected] # 执行远程命令后退出 ssh user@host "ls -l /tmp" # 使用密钥登录(禁用密码) ssh -i ~/.ssh/id_rsa user@host
# SSH的加密
# 加密方式
ssh的主要有点就是安全性,安全性依赖于加密方式,现在主要的加密方式有两种:对称加密和非对称加密。
- 对称加密使用同一个密钥来进行加密和解密,这样在传输时是安全可靠的,但是如何安全的保存密钥呢,在集群中,客户端的数量巨大,一旦任意一个客户端的密钥被窃取,那么整个系统的安全性也不复存在。
- 由于对称加密的这个弊端,产生了非对称加密,非对称加密中有两个密钥:公钥和私钥。公钥由私钥产生,但却无法推算出私钥;公钥加密后的密文,只能通过对应的私钥来解密。
# 非对称加密的登录流程
初始状态:终端要登录Server服务器,发起连接请求ssh [email protected]
- 服务端运行有
ssh服务,并持续监听22号端口,因此可以生成一对公钥和私钥;此时将公钥返回给客户端 - 客户端使用公钥,对登录密码进行加密,(如服务器
work用户密码为xxx),生成公钥加密字符串 - 客户端将公钥加密字符串发送给服务端
- 服务端使用私钥,解密公钥加密字符串,得到原始密码
- 校验密码是否合法(此为本机
work密码) - 返回登录结果给客户端:成功登录或密码错误
在非对称加密中,由于只有公钥会被传输,而私钥是服务端本地保存,因此即便公钥被监听,也无法拿到原始密码,从而登录服务器。
# 中间人攻击
在非对称加密中可以有效保护登录密码不被泄漏,但这是在建立连接到真实服务器的情况下。设想一下,如果供给者并不监听密码或公钥,而是直接伪装成服务器呢.

存在Hacker服务器劫持了你的ssh建连请求(如通过DNS劫持等方式),导致你与Hacker机器的连接一切正常,因此它能拿到你的明文密码,并通过明文密码来攻击真实的服务端。
SSH采用了非对称的加密方式,是怎么解决这个问题的呢?
-
通过让我们肉眼比对来判断目标服务器是否是真实服务器
-
用
fingerprint(公钥指纹)代替key,主要是key过于长(RSA算法生成的公钥有1024位),很难直接比较。所以,对公钥进行hash生成一个128位的指纹,这样就方便比较了。
[root@hadoop01 hadoop]# ssh [email protected]
# 无法确定主机“server.com(10.10.10.24)”的真实性。
The authenticity of host '192.168.61.45 (192.168.61.45)' can't be established.
ECDSA key fingerprint is SHA256:3Pv+hrn4MBRZu6wy0Wr9Y1PdQDmF+oZmZAwkcbxOwbA.
ECDSA key fingerprint is MD5:32:b1:c0:b0:db:1b:db:34:34:59:69:0b:63:86:d2:0a.
# 知道它的公钥指纹,是否继续连接?
Are you sure you want to continue connecting (yes/no)? yes
# 输入yes继续连接后,就会确认该服务器为可信任服务器,然后添加到known_hosts文件中,下次不用再次确认,然后跳转到输入密码的验证阶段。
Warning: Permanently added '192.168.61.45' (ECDSA) to the list of known hosts.
[email protected]'s password:
Last login: Sat Jul 25 01:45:34 2020 from 192.168.61.1
# 开启 SSH 远程登录
# 验证是否已安装
ls /etc | grep ssh
# 通过包管理工具安装 openssh 软
yum install -y openssh-service
# 设置允许
cat /etc/ssh/sshd_config | grep -Eq "^[# ]?PermitRootLogin " ; [ $? -eq 0 ] && sed -i 's/^[# ]\?PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config || echo -e "\nPermitRootLogin yes" >> /etc/ssh/sshd_config
# 设置密码认证
cat /etc/ssh/sshd_config | grep -Eq "^[# ]?PasswordAuthentication " ; [ $? -eq 0 ] && sed -i 's/^[# ]\?PasswordAuthentication.*/PasswordAuthentication yes/g' /etc/ssh/sshd_config || echo -e "\nPasswordAuthentication yes" >> /etc/ssh/sshd_config
# 启动/重启
ps -ef | grep -q ssh ; [ $? -eq 0 ] && systemctl restart sshd || systemctl enable --now sshd
# 生成 SSH key
Linux 与 Mac 都是默认安装了 SSH ,而 Windows 系统安装了 Git Bash 应该也是带了 SSH 的。大家可以在终端(win 下在 Git Bash 里)输入 ssh 如果出现提示证明你本机已经安装 SSH, 否则请搜索自行安装下。紧接着输入 ssh-keygen -t rsa ,什么意思呢?就是指定 rsa 算法生成密钥,接着连续三个回车键(不需要输入密码),然后就会生成两个文件 id_rsa 和 id_rsa.pub ,而 id_rsa 是密钥,id_rsa.pub 就是公钥。这两文件默认分别在如下目录里生成: Linux/Mac 系统 在 ~/.ssh 下,win 系统在 /c/Documents and Settings/username/.ssh 下,都是隐藏文件,相信你们有办法查看的。接下来要做的是把 id_rsa.pub 的内容添加到 GitHub 上,这样你本地的 id_rsa 密钥跟 GitHub 上的 id_rsa.pub 公钥进行配对,授权成功才可以提交代码。
ssh-genkey是生成密钥的工具,执行完成后生成公钥和密钥,这两个文件会默认保存在~/.ssh/路径下。常用的参数为:
- -t: 指定生成密钥类型(rsa、dsa、Ed25519 )。默认为rsa
- -b 4096 表示 RSA 密钥长度 4096 bits (默认 2048 bits)。Ed25519 算法不需要指定。
- -f: 指定存放私钥的文件,公钥文件名为私钥文件名加.pub后缀。默认为id_rsa
- -P: 指定passphrase(私钥的密码),用于确保私钥的安全。默认为空
- -C: 备注。默认为user@hostname
# 可以利用 Ed25519 算法生成的密钥对,减少你的登录时间
[sun@CMCC#1 ~]$ ssh-keygen -t rsa -b 4096 -C " [email protected] "
[sun@CMCC#1 ~]$ ssh-keygen -t ed25519 -C " [email protected] "
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/sun/.ssh/id_rsa): Created directory '/Users/sun/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/sun/.ssh/id_rsa.
Your public key has been saved in /Users/sun/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:BQZcuTpPMQ2L/xYPFQoF8jhKsWrSZU4S3iIU7QiUxyU [email protected]
The key's randomart image is:
+---[RSA 4096]----+
|.+*Eoooo=+. |
|oo *.o.=+. . |
|o B B o..*.. . |
| + @ ...=.o . |
|. + o oSo . |
| o o o o |
| + . + |
| . o . |
| . |
+----[SHA256]-----+
## 此时,生成的文件在~/.ssh/目录下,我们会看到这些文件:
[sun@CMCC#1 .ssh]$
id_rsa // 私钥文件
id_rsa.pub // 公钥文件
authorized_keys // 存放客户端公钥的文件
known_hosts // 确认过公钥指纹的可信服务器列表的文件
config // 指定不同域名使用哪个密钥的配置文件
## 因为一台机器即能是客户端,又能是服务端,因此同时存在authorized_keys(在该机器为服务端时使用)和Known_hosts(在该机器为客户端时使用)。
# SSH 多服务器配置
我们的服务器会有很多的用户,如果所有的用户都用同一份密钥,可能就没办法划分权限或者区分用户,如多个用户提交git就需要按照用户名来生成密钥,用于区分用户。
# 配置SSH
同时你可能也希望针对不同的服务器使用不同的密钥对,因此需要不同服务器配置SSH。
# 生成目录
mkdir -p ~/.ssh && cd ~/.ssh
# 我在 GitHub
ssh-keygen -t ed25519 -f my_github_ed25519 -C "me@github"
# 我在 Gitee
ssh-keygen -t ed25519 -f my_gitee_ed25519 -C "me@gitee"
# 我在 GitLab
ssh-keygen -t ed25519 -f my_gitlab_ed25519 -C "me@gitlab"
# 我在企业
ssh-keygen -t ed25519 -f my_company_ed25519 -C "[email protected]"
# SSH 设置
在客户端生成密钥对之后,将公钥追加到服务器的authorized_keys文件中。通过 ~/.ssh/config 文件可以为不同服务器配置不同的 SSH 设置。ssh config 就是一个配置文件,描述不同的秘钥对应的设置——包括主机名、用户名、访问策略等等,本地配置内容放在文件 /Users/you/.ssh/config, Host 是别名,HostName 是真正的域名。Hostname 是域名则最好保持一致。
# ~/.ssh/config 中配置
# 关于别名
# Host 是别名,HostName 是真正的域名。支持通配符配置(如 Host *.baidu.com)
# 得益于别名,你可以直接以别名访问地址。例如:
# 无别名: git clone [email protected]: torvalds/linux.git
# 有别名: git clone github: torvalds/linux.git
# 本例中使用与域名一致的别名,以免错误的配置导致登录不上。
# 我在 GitHub
Host github.com
Hostname github.com
# ProxyCommand connect -H localhost: 1080 %h %p
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/my_github_ed25519
# 我在 GitLab
Host gitlab.com
Hostname gitlab.com
# ProxyCommand connect -H localhost: 1080 %h %p
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/my_gitlab_ed25519
# 我在 Gitee
Host gitee.com
Hostname gitee.com
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/my_gitee_ed25519
# 我在企业
Host example.com
Hostname example.com
Port 22
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/my_company_ed25519
- 当我
git clone https://github.com/user/repo的时候,~/.ssh/my_github_ed25519秘钥会被使用 - 当我
git clone https://gitlab.com/user/repo的时候,很显然~/.ssh/my_gitlab_ed25519秘钥会被使用。
如果同一域名下有两个不同的配置怎么办?
-
以 Github 为例,如果我有两个账户,一个个人的,一个组织的,并且要使用不同的秘钥,那么我可以这么写:这里 Host 后面对应的是 Github 的两个用户名
github.com/user1github.com/user2Host github.com-user1 Hostname github.com User git PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa Host github.com-user2 Hostname github.com User git PreferredAuthentications publickey IdentityFile ~/.ssh/my_github_ed25519 -
如果域名是数字 IP,是否可以简化呢?Host 可以帮助你把对应的 IP 变成好记的名字。
# 比如说我在公司内部配置了 Git Server(基于 gitolite 或 Gitlab 或任何工具) # 正常的访问地址是:git://xxx.xxx.xxx.xxx: repo.git,如下的配置则可以帮你把它简化成:git.work: repo.git Host git.work Hostname 192.168.61.11 User git PreferredAuthentications publickey IdentityFile ~/.ssh/work
# 添加 SSH key
先在 GitHub 上的设置页面,点击最左侧 SSH and GPG keys : 然后点击右上角的 New SSH key 按钮: 需要做的只是在 Key 那栏把 id_rsa.pub 公钥文件里的内容复制粘贴进去就可以了,Title 那栏不需要填写,点击 Add SSH key 按钮就 ok 了。
# Linux/Mac 用户执行以下命令:
cd ~/.ssh
cat id_rsa.pub
# 将 SSH 密钥复制到剪贴板
pbcopy < ~/.ssh/id_rsa.pub
SSH key 添加成功之后,输入 ssh -T [email protected] 进行测试,如果出现以下提示证明添加成功了。
# 验证 ssh key 是否设置成功
# ssh -T [email protected]
ssh -T [email protected]
Hi fulsun! You've successfully authenticated, but GitHub does not provide shell access.
# SSH免密登录
-
使用
ssh登录远程服务器了,但是每次登录都要输入密码,比较麻烦。ssh提供一种免密登录的方式:公钥登录。
-
登录流程
- 在客户端使用
ssh-keygen生成一对密钥:公钥+私钥 - 将客户端公钥追加到服务端的
authorized_key文件中,完成公钥认证操作 - 认证完成后,客户端向服务端发起登录请求,并传递公钥到服务端
- 服务端检索
authorized_key文件,确认该公钥是否存在 - 如果存在该公钥,则生成随机数
R,并用公钥来进行加密,生成公钥加密字符串pubKey(R) - 将公钥加密字符串传递给客户端
- 客户端使用私钥解密公钥加密字符串,得到
R - 服务端和客户端通信时会产生一个会话
ID(sessionKey),用MD5对R和SessionKey进行加密,生成摘要(即MD5加密字符串) - 客户端将生成的
MD5加密字符串传给服务端 - 服务端同样生成
MD5(R,SessionKey)加密字符串 - 如果客户端传来的加密字符串等于服务端自身生成的加密字符串,则认证成功此时不用输入密码,即完成建连,可以开始远程执行
shell命令了
- 在客户端使用
-
ssh-genkey
# 第一步:在本地机器上使用ssh-keygen产生公钥私钥对 [hadoop@hadoop01 ~]$ ssh-keygen -t rsa -P password Generating public/private rsa key pair. Enter file in which to save the key (/home/hadoop/.ssh/id_rsa): /home/hadoop/.ssh/id_rsa already exists. Overwrite (y/n)? y Your identification has been saved in /home/hadoop/.ssh/id_rsa. Your public key has been saved in /home/hadoop/.ssh/id_rsa.pub. The key fingerprint is: SHA256:ld27QVjFQSpPw5YeQFArbZoQrXzWxRDMGaRbJuUozCk hadoop@hadoop01 The key's randomart image is: # 第二步:用ssh-copy-id将公钥复制到远程机器中,第一次需要密码登录 [hadoop@hadoop01 ~]$ ssh-copy-id username@hostname # ERROR: No identities found # 当没有值传递的时候或者 如果 ~/.ssh/identity.pub 文件不可访问(不存在), ssh-copy-id 将显示上述的错误信息 # ssh-copy-id -i ~/.ssh/id_rsa.pub -p 23 username@hostname # -p 制定端口 # -i 指定公钥文件
# 密钥管理流程
假设你已经实现了服务器集群的免密登录,那么如果你的一台客户端被攻击成功了,那么整个集群的安全性便荡然无存了。因此,我们有时还需要对密钥做安全性保障,即设置私钥密码:
# 使用rsa方法加密,生成密钥对
ssh-keygen -t rsa -b 4096 -f ~/.ssh/keyname -C "comment"
# 生成时直接加密:
ssh-keygen -t ed25519 -f ~/.ssh/prod_key -N "YourStrongPassphrase"
此时,各机器仍然是免密登录,但是需要你输入私钥密码:
$ssh [email protected]
Enter passphrase for key '/home/work/.ssh/test':
私钥安全增强
# 加密私钥,每次使用该密钥时都会要求输入密码
ssh-keygen -p -f ~/.ssh/private_key #(会提示输入旧密码和新密码)
# 使用 ssh-agent 管理密码:可以缓存解密后的私钥,避免重复输入密码
eval $(ssh-agent)
ssh-add ~/.ssh/private_key # 首次需要输入密码