ssh服务

7643 字
38 分钟
ssh服务

ssh服务#

[TOC]


初认知#

远程连接服务

  1. 每台Linux服务器默认开启的

    即使防火墙开启,它也是默认允许连接的

  2. 默认端口是22

    端口可以修改

  3. 不同的端口表示不同的服务 22--->SSH远程连接服务 80--->WEB服务 3306—>数据库服务

    端口号的范围是从 165535

端口修改#

Terminal window
1.查看服务是否运行
[root@backup ~]#systemctl status sshd
sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2026-01-25 09:59:57 CST; 1min 1s ago
# 如果不运行,我们就无法进行远程连接了
'服务名叫sshd,而不是ssh'
[root@backup ~]#netstat -lntup | grep 22
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 952/sshd: /usr/sbin
tcp6 0 0 :::22 :::* LISTEN 952/sshd: /usr/sbin
# 过滤22端口
2.修改SSH服务内容
#配置文件位置/etc/ssh/sshd_config
'我们需要把这个端口改掉,因为大家都知道22端口是Linux远程服务器端口'
#我们这里改为别的,改为2222(四个2),只要在1-65535,就可以随便改
[root@backup ~]#vim /etc/ssh/sshd_config
...
Port 2222
....
3.重启生效
[root@backup ~]#systemctl restart sshd
4.远程连接测试
[root@backup ~]#exit
logout
Connection closing...Socket close.
# 重新尝试再次连接22端口
[C:\~]$
Connecting to 10.0.0.41:22...
Could not connect to '10.0.0.41' (port 22): Connection failed
# 22端口连接失败
'xshell修改连接端口为2222'

image-20260125103848959
image-20260125103848959

端口改了,为什么当前连接的不断开?

  • 已经占用着呢,已经进来了,不影响

  • 但是我们断开连接后,再重新连接原来的 22 端口,就连不上上了

    必须连接我们改之后的 2222 端口

ssh VS telnet#

服务类型端口号(默认)是否加密作用
ssh22 (远程连接)✅ 加密连接Linux服务器
telnet23 (远程连接)❌ 明文连接网络设备
Terminal window
# 安装telnet测试
1.安装
[root@backup ~]#yum -y install telnet-server
# 这里安装的是服务端,注意软件包的名称
2.启动服务
[root@backup ~]#systemctl start telnet.socket
# 以socket的方式来启动运行,tab键可以补全服务名
# 我们过滤一下端口进行验证
[root@backup ~]#ss -lntup | grep 23
tcp LISTEN 0 128 *:23 *:* users:(("systemd",pid=1,fd=28))
3.客户端连接测试
[C:\~]$ telnet 10.0.0.41 23
'这里不指定端口就是23,Xshell中空格隔开端口号即可'
Connecting to 10.0.0.41:23...
Connection established
To escape to local shell, press 'Ctrl+Alt+]'.
Authorized users only. All activities may be monitored and reported.
backup login: root # 41的用户名
Password: # 41服务器root的密码 oldboy123.com
'Centos不让用root来进行登录,kylin可以用root,自己也可以创建一个用户来进行登录'
  • 因为 telnet 是明文传输,我们抓包时,很轻易就能破解传输内容

SSH命令#

远程连接#

Terminal window
语法格式:
ssh 用户名@主机
ssh # 固定命令
用户名 # 指定用户名
# 在Linux远程登录Linux中,默认以当前登录系统的用户身份远程连接,和rsync相同
'当前登录用户是root,你没指定用户,ssh远程登录的时候就是root'
@ # 固定分隔符
主机 # IP地址、域名、主机名称
# 我们也可以Windows远程登录Linux服务器
案例1.windows连接linux 默认22端口
[C:\~]$
# 这里的盘符是什么东西?
为什么是C盘而不是D盘?
因为我的Xshell安装在C盘中
[C:\~]$ ssh 10.0.0.31 # 回车后,提示框输入用户名和密码
[C:\~]$ ssh root@10.0.0.31 # 指定远程连接用户
[C:\~]$ ssh 10.0.0.41 2222 # 指定端口号
'这里是空格隔开端口号,它并没有 -p 这个选项'
案例2.Linux连接Linux 默认root用户 端口22端口
[root@backup ~]#ssh 172.16.1.31
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes # 输入yes
root@172.16.1.31's password: # 输入root的密码'
# 默认以当前登录系统的用户身份远程连接
[root@nfs ~]#exit # 成功进入到nfs
logout
Connection to 172.16.1.31 closed.
[root@backup ~]# # 退出登录到backup
[root@backup ~]# ssh root@172.16.1.31 # 指定用户
-------------------------------
[root@nfs ~]#ssh 172.16.1.41 2222
ssh: connect to host 172.16.1.41 port 22: Connection refused
# 这里用nfs连接backup服务器,明明跟端口了,为啥还是连接的22?
# 需要有-p这个选项
[root@nfs ~]#ssh -p 2222 10.0.0.41 # 指定端口连接
'scp命令使用大写的P选项来指定端口'
'这里只有Linux连接Linux的时候,必须使用 -p 指定端口'
'Windows连接Linux并没有这个 -p 的这个选项,它用空格隔开'
---------------------------------
案例3.域名连接
[root@backup ~]#ssh linuxnc.com
案例4.主机名连接
[root@backup ~]#cat /etc/hosts
'这里一定要要做域名解析'
..........
172.16.1.31 nfs
#远程连接
[root@backup ~]#ssh root@nfs
[root@nfs ~]#exit #连接到nfs服务器
logout
Connection to nfs closed.
[root@backup ~]#

远程执行命令#

Terminal window
远程执行命令
语法结构:
ssh 172.16.1.31 "执行的命令"
案例1.远程在nfs那创建hehe.txt
[root@backup ~]#ssh root@172.16.1.31 'touch hehe.txt'
# 不需要登录过去,不指定路径,默认在家目录中创建
案例2.远程在nfs上执行停止nfs服务命令
[root@backup ~]#ssh root@172.16.1.31 'systemctl stop nfs'
案例3.使用oldboy用户远程执行命令
[root@nfs ~]#useradd oldboy
[root@nfs ~]#echo "heima123.com" | passwd --stdin oldboy
Changing password for user oldboy.
passwd: all authentication tokens updated successfully.
# 现在nfs上创建用户,并给一个密码
[root@backup ~]#ssh oldboy@172.16.1.31 "touch /etc/old.txt"
# 指定oldboy用户
touch: cannot touch '/etc/old.txt': Permission denied
# 权限拒绝
[root@backup ~]#ssh oldboy@172.16.1.31 "touch /home/oldboy/old.txt"
# 只有/home/oldboy目录才属于oldboy用户

🍔关于 scp命令 的使用,可以回去看笔记 rsync 里面有详细的补充介绍​

免密连接#

Terminal window
远程连接有两种验证方式
一种: 基于免秘钥认证
二种: 基于用户名+密码
验证方式:
当我们SSH远程连接服务器172.16.1.31
1.先检测是否有秘钥对、如果有则直接通过
2.如果没有或者不通过,则需要我们输入用户名和密码

image-20260307083516801
image-20260307083516801

  • A要远程登录服务器
    • A先生成密钥对,同时把 公钥 放进目标服务器中
    • 公钥(🔒)、私钥(🔑)
    • 因为A有🔑,可以解开自己的🔒;从而实现免密登录!
  • 目标服务器可以放很多🔒(公钥)
  • 如果将生成的公钥,拷贝到目标主机,我们所有的ssh的命令和scp都可以进行免密钥执行
    • scp命令是基于ssh服务实现的
Terminal window
第一步: 生成密钥对 、一路回车
[root@backup ~]#ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
# 第一个回车是保存私钥文件路径,支持默认路径
Enter passphrase for "/root/.ssh/id_ed25519" (empty for no passphrase):
# 第二个回车是为私钥设置密码
# 如果留空(直接回车),则私钥不设密码,后续使用时无需输入。
# 如果设置了密码,每次使用该私钥(如 ssh 登录或 scp 传输)时都需要输入这个密码
Enter same passphrase again:
# 第三个回车再次输入密码以确认
# 如果上一步留空(无密码),这一步也留空即可
.....
Your identification has been saved in /root/.ssh/id_rsa #私钥
Your public key has been saved in /root/.ssh/id_rsa.pub #公钥
The key fingerprint is:
SHA256:WfTKKYAgrN+gTYcGjx/nYqwZ3eEUWrOiSKZkes4oUH4 root@backup
.......
查看生成的密钥对
[root@backup ~]#ll .ssh/
total 12
-rw------- 1 root root 2602 Dec 1 11:36 id_rsa # 私钥
-rw-r--r-- 1 root root 565 Dec 1 11:36 id_rsa.pub # 公钥
第二步: 将公钥拷贝到目标主机31
[root@backup ~]#ssh-copy-id 172.16.1.31
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
......
Authorized users only. All activities may be monitored and reported.
root@172.16.1.31's password: '
# 输入密码
.......
#查看目标主机的公钥
[root@nfs ~]#ll .ssh/
total 8
-rw------- 1 root root 565 Dec 1 11:39 authorized_keys
-rw-r--r-- 1 root root 358 Dec 1 11:21 known_hosts
[root@nfs ~]#cat /root/.ssh/authorized_keys
ssh-rsa ...wxl8NLQdCBq4C+mKj5xi6WfP51WAsY3j4PxdWEzY2FMcsl65FUw35a63dyq8= root@backup
# root@backup,这里面是backup的公钥
[root@nfs ~]#cat /root/.ssh/known_hosts
[172.16.1.41]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDzMWMShH4Xtn5g5eglbU12VuxxrQQq6coiRREMcwhfeRzVBIMcItmecViimDqjdEH65P6RxDfFQ/QDi+9uxH00=
# known_hosts 确保你没连错服务器(防钓鱼)
# 如果清空,则你第一次连接目标主机(别的主机)需要输入yes验证
-------------
免秘钥流程
1)生成密钥对
ssh-keygen
2)拷贝公钥到目标主机
ssh-copy-id 10.0.0.7
3)远程连接
ssh 10.0.0.7
-----------------
第三步: 验证远程连接
[root@backup ~]#ssh 172.16.1.31 # 直接通过
[root@backup ~]#ssh 172.16.1.31 'touch s.txt' # 直接通过
[root@backup ~]#scp /etc/hosts 172.16.1.31:~ # 直接通过

非交互式免密#

Terminal window
ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa_test -N ''
各参数说明:
-t rsa:指定密钥类型为 RSA(也可用 ed25519、ecdsa 等)
-b 4096:指定密钥长度(仅对 RSA 有效,通常用 4096)
-f /root/.ssh/id_rsa_test:指定私钥保存路径(公钥会自动命名为.pub后缀)
-N '':指定私钥的密码为空(即不设密码)
# 如果要设密码,可写成 -N 'your_passphrase'
# 上面用的rsa密钥,但我们可以换一种密钥!Ed25519 密钥
'更推荐如下这个命令!'
ssh-keygen -t ed25519 -f ~/.ssh/my_key -N ''
'它比传统的密钥更加简练!'
(1)生成的密钥更加的短
(2)被官方推荐为默认密钥类型
(3)生成速度快,性能更好一点
# 较新的操作系统,推荐使用ed25519算法代替rsa算法,可以用较短的位数实现rsa较长位数的安全级别
# 但是有些老的系统,不一定支持所有的算法,可以使用rsa算法
------------------------------
'rocky远程登录OpenEuler'
(1)密钥对生成
[root@Rocky10 ~]# ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa_test -N ''
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa_test
Your public key has been saved in /root/.ssh/id_rsa_test.pub
The key fingerprint is:
SHA256:uGL9uE/+YCU9AYyu2v3QkbsBDd5z39cwYOYDTOnYVFQ root@Rocky10
The key's randomart image is:'
+---[RSA 4096]----+
| o. .+o.E |
| . .+o |
| .. =+ + |
| ..=.oo* . |
| .+ S = o o |
| .. + B o o o.|
| oo.+ B . . o|
| .....B + . |
| o+*.. |
+----[SHA256]-----+
[root@Rocky10 ~]# ll ~/.ssh/
total 16
-rw-------. 1 root root 3381 Mar 7 11:17 id_rsa_test
-rw-r--r--. 1 root root 738 Mar 7 11:17 id_rsa_test.pub
# 一个私钥,一个公钥!
(2)公钥分发
[root@Rocky10 ~]# ssh-copy-id -i /root/.ssh/id_rsa_test.pub root@10.0.0.112
# -i: 指定公钥发送
...
Authorized users only. All activities may be monitored and reported.
root@10.0.0.112's password: '
# 因为没有配置免密连接,所以需要输入它的密码!
Number of key(s) added: 1
# 成功添加进去!
Now try logging into the machine, with: "ssh -i /root/.ssh/id_rsa_test 'root@10.0.0.112'"
# 看它的提示!你登录的时候也要-i指定私钥才行!
(3)免密测试验证
[root@Rocky10 ~]# ssh root@10.0.0.112
Authorized users only. All activities may be monitored and reported.
root@10.0.0.112's password: '
# 你发现,直接ssh登录还得输入密码!
'少选项了 -i指定私钥才行!'
[root@Rocky10 ~]# ssh -i /root/.ssh/id_rsa_test root@10.0.0.112
.....
[root@OpenEuler ~]#
# 免密登录成功!
[root@OpenEuler ~]# ll ~/.ssh/
total 4
-rw-------. 1 root root 738 Mar 7 11:24 authorized_keys
# rocky的公钥🔒存放在这里!
(4)优化
# 每次ssh远程登录都要-i指定私钥,太麻烦了!
[root@Rocky10 ~]# echo 'IdentityFile ~/.ssh/id_rsa_test' >>/etc/ssh/ssh_config
# 追加配置!默认使用我们这个私钥!
'ssh_config是客户端的配置文件'
# 用于我们ssh连接别人时候使用!!!
'后面我们改服务器的ssh配置的时候,通常修改/etc/ssh/sshd_config'
# 用于别人ssh连接我们的时候使用!!!
[root@Rocky10 ~]# grep IdentityFile /etc/ssh/ssh_config
# IdentityFile ~/.ssh/id_rsa
# IdentityFile ~/.ssh/id_dsa
# IdentityFile ~/.ssh/id_ecdsa
# IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_rsa_test
[root@Rocky10 ~]# systemctl restart sshd
# 修改配置文件后,别忘记重启服务!
(5)测试连接
[root@Rocky10 ~]# ssh 10.0.0.112
....
[root@OpenEuler ~]#
# 不用输入密码直接连接过来
'方便快捷!'

✅ 总结:

步骤交互式输入非交互式参数
1. 私钥路径回车(默认)或输入路径-f /path/to/key
2. 私钥密码回车(无密码)或输入密码-N 'password'-N ''
3. 确认密码回车(同上)自动处理,无需输入

ssh常见配置#

Terminal window
# 配置文件的修改/etc/ssh/sshd_config
'服务端配置!'
1.修改默认端口
Port 2222
# 默认是22、企业中建议修改
2.强制密钥认证
PubkeyAuthentication yes
PasswordAuthentication no
# 禁止密码验证登录
3.优化连接速度
GSSAPIAuthentication no
# 禁用GSSAPI加速连接
# 明确关闭后,跳过这一认证流程,直接进入常规认证(如 pubkey/password),加快连接
UseDNS no
# kylin默认no centos是yes
# 禁止反向DNS解析
# 不做任何DNS查询,直接接受连接,显著提升首次登录速度
4.限制认证尝试和连接
MaxAuthTries 3
# 减少暴力破解机会
MaxSessions 10
# 限制并发会话
LoginGraceTime 60
# 缩短认证超时时间
5.用户访问控制
面试题 如何只允许某个IP地址连接服务器?
或者问 什么原因导致无法连接服务器?
1)来源IP地址不正确、没有在防火墙规则中
2)SSH配置文件中没有允许来源IP地址
[root@backup ~]#vim /etc/ssh/sshd_config
AllowUsers 11.22.33.44 # 公司公网IP地址
'只允许公司的公网IP连接服务器' # 单个IP地址
AllowUsers root@10.0.0.31 root@10.0.0.1 # 允许多个IP地址访问
'多个IP地址,需要 用户名@IP 组合并用空格分隔'
DenyUsers 10.0.0.31 # 拒绝单个IP地址访问我的服务器
# 拒绝用的少!
'修改完配置文件后,别忘记重启服务'
systemctl restart sshd
# 案例
[root@backup ~]#grep "AllowUsers" /etc/ssh/sshd_config
AllowUsers 10.0.0.31
# backup服务器只允许我们10.0.0.31nfs连接,别的网络不能连接
[C:\~]$
Connecting to 10.0.0.41:22...
Authorized users only. All activities may be monitored and reported.
# 仅限授权用户使用
# Xshell登录不上,10.0.0.1登录
[root@backup ~]#grep "AllowUsers" /etc/ssh/sshd_config
AllowUsers root@10.0.0.31 root@10.0.0.1
# 这次Xshell就能登录上去了
Terminal window
'修改客户端配置!'
[root@Rocky10 ~]# vim /etc/ssh/ssh_config
# 也可以在~/.ssh/目录下自己创建config文件
'vim ~/.ssh/config'
...
HOST Open
HOSTNAME 10.0.0.112
User root
Port 22
...
# 可以试着重启一下ssh服务!
[root@Rocky10 ~]# systemctl restart sshd
[root@Rocky10 ~]# ssh Open
# 我的这台OpenEuler的服务器!
Web console: https://OpenEuler:9090/ or https://10.0.0.112:9090/
....
System load: 1.56
Memory used: 7.6%
Swap used: 0%
Usage On: 7%
IP address: 10.0.0.112
Users online: 1
[root@OpenEuler ~]#
# 也是成功进来了!

ssh-agent#

Terminal window
ssh-agent(免密解锁密钥)
使用场景:
1)密钥有密码,想免密登录
# -N指定的有密码,后面每免密登录一次都需要输入密钥的密码,太麻烦了!
2)本地有很多对密钥对,登录必须要-i指定私钥才行
使用方法:
# Xshell远程终端需要手动启动,桌面中的终端自动启动
'这里面变量值和启动方式不同,有一点问题!下面有详细解决方法'
root@Rocky10:~# ps aux | grep ssh-agent
root 3746 0.0 0.0 8888 1824 ? Ss 16:56 0:00 ssh-agent
# 就是这个ssh-agen进程
1)查看已缓存的密钥
root@Rocky10:~# ssh-add -l
4096 SHA256:uGL9uE/+YCU9AYyu2v3QkbsBDd5z39cwYOYDTOnYVFQ root@Rocky10 (RSA)
2)添加默认密钥 ~/.ssh/id_rsa
ssh-add
3)添加指定密钥
ssh-add ~/.ssh/my-key
'输入密码短语后,密钥存入内存'
4)ssh-add -D
# 删除所有密钥
核心功能:
`ssh-agent` 的本质是一个“解密的内存管家”
1)ssh-add把解密后的私钥加入内存容器后,再次连接服务器不必重复输入密码!
2)解密后的私钥没有落盘行为,只存在与Agent的内存
3)存在多个密钥对时,自动尝试所有已加载的私钥去匹配远程服务器,无需用户手动使用 `-i` 指定特定私钥
'一次性解锁' '后续免交互'
SSH 密钥───────► ssh-agent ───────► SSH 连接
(加密状态) (内存缓存)
实践部分:
1)国产化Linux发行版:OpenEuler、kylin启动方式:
[root@web01 ~]#eval $(ssh-agent)
Agent pid 2391
[root@web01 ~]#ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-B3oVYYxzwCbb/agent.3089; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3090; export SSH_AGENT_PID;
echo Agent pid 3090;
[root@web01 ~]#ps aux | grep ssh-agent
root 2391 0.0 0.0 7128 544 ? Ss 19:30 0:00 ssh-agent
root 3082 0.0 0.0 7128 548 ? Ss 21:43 0:00 ssh-agent
root 3090 0.0 0.0 7128 548 ? Ss 21:44 0:00 ssh-agent
[root@web01 ~]#echo $SSH_AUTH_SOCK
/tmp/ssh-5WdWb1f5ehz8/agent.2390
[root@web01 ~]#ssh-add -l
The agent has no identities.
[root@web01 ~]#ll ~/.ssh/
total 16
-rw------- 1 root root 832 Mar 9 19:04 authorized_keys
-rw-r--r-- 1 root root 344 Feb 8 20:13 known_hosts
-rw------- 1 root root 399 Mar 9 16:58 myed25519
-rw-r--r-- 1 root root 92 Mar 9 16:58 myed25519.pub
[root@web01 ~]#ssh-add ~/.ssh/myed25519
Identity added: /root/.ssh/myed25519 (root@web01)
# 把私钥加入进去!
[root@web01 ~]#ssh-add -l
256 SHA256:TcNYrb4Fs/PTHsWsUstsrLiwvrGyftTBpKn8j1xsZaU root@web01 (ED25519)
# 这样就可以看到了!
2)Rocky:它是Centos10的内核
# 所以启动起来比较麻烦!!
systemctl start --user ssh-agent.service
# 以systemd用户服务(user service)启动
export SSH_AUTH_SOCK=/run/user/0/ssh-agent.socket
# 设置必要的环境变量(如 SSH_AUTH_SOCK 或 SSH_AGENT_PID)
--------------------------------
[root@Rocky10 ~]# echo $SSH_AUTH_SOCK
/run/user/0/keyring/ssh
'桌面的变量'
SSH_AUTH_SOCK=/run/user/0/ssh-agent.socket
'终端手动设置的变量!'
1)❗如果SSH_AUTH_SOCK=/run/user/0/keyring/ssh,使用图形化激活的代理
2)❗如果SSH_AUTH_SOCK=/run/user/0/ssh-agent.socket 则使用ssh-agent.service服务对应的代理
📝当登陆图形化界面时,系统会自动注入变量:SSH_AUTH_SOCK=/run/user/0/keyring/ssh
图形化的变量,对应的进程命令是:/usr/bin/ssh-agent -D -a /run/user/0/keyring/ssh
对于命令行界面,默认没有SSH_AUTH_SOCK变量,当启用了进程/usr/bin/ssh-agent -D -a /run/user/0/ssh-agent.socket
需要通过SSH_AUTH_SOCK指定对应的ssh-agent.socket文件的位置,此变量如需在所有终端生效,可以在~/.bashrc文件中写入:
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
或着是
export SSH_AUTH_SOCK="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/ssh-agent.socket"
--------------------------------
[root@Rocky10 ~]# ll ~/.ssh/
total 24
-rw-------. 1 root root 3381 Mar 9 18:44 id_rsa_test
-rw-r--r--. 1 root root 738 Mar 9 18:44 id_rsa_test.pub
'第一次默认创建的!'
# 创建后,我就进行分发了公钥了
# 测试ssh可以免密登录上去
-rw-------. 1 root root 399 Mar 9 18:45 myed25519
-rw-r--r--. 1 root root 94 Mar 9 18:45 myed25519.pub
# 这里是两对密钥!
'然后我们再一次生成了一对密钥!'
# 再次进行拷贝的时候,它会默认把上次拷贝过去的密钥再次拷贝一遍!
'我们分发公钥的时候,也可以进行-i指定公钥的'
[root@Rocky10 ~]# ssh-copy-id -i ~/.ssh/myed25519.pub 10.0.0.7
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/myed25519.pub"
# 这个就是我们新生成的密钥对!-i指定公钥拷贝过去!
[root@Rocky10 ~]# ssh 10.0.0.7
Authorized users only. All activities may be monitored and reported.
root@10.0.0.7's password: '
'我们把两个密钥都拷贝过去了,然后还是需要输入密码!'
[root@web01 ~]#cat ~/.ssh/authorized_keys
# 切换到web01中
ssh-rsa AAAAB3NzaC1yc2EAA....== root@Rocky10
# rsa老长了!
ssh-ed25519 AAAAC3NzaC1lZ....86hHRl5V root@Rocky10
# 这个简短一点!
'web01中两个公钥都有!'
[root@Rocky10 ~]# ssh -i ~/.ssh/id_rsa_test 10.0.0.7
# 指定第一次的私钥!可以免密登录上去!
[root@Rocky10 ~]# ssh -i ~/.ssh/myed25519 10.0.0.7
# 指定第二次的私钥可以可以登录上去的!
# 就是比较麻烦,所以引出了ssh-agent
[root@web01 ~]#ps aux | grep ssh-agent | grep -v grep
'Xshell的终端中,默认是没有开启ssh-agent'
# 一个进程都没有!
[root@Rocky10 ~]# systemctl start --user ssh-agent.service
[root@Rocky10 ~]# ps aux | grep ssh-agent | grep -v grep
root 3746 0.0 0.1 8888 4092 ? Ss 16:56 0:00 ssh-agent
# 手动启动!
[root@Rocky10 ~]# ssh-add -l
Could not open a connection to your authentication agent.
# 还是不能打开!
❗注:图形化环境有默认的SSH_AUTH_SOCK变量值,所有环境变量不一致,需要手动设置环境变量,以下命令临时设置
[root@Rocky10 ~]# export SSH_AUTH_SOCK=/run/user/0/ssh-agent.socket
[root@Rocky10 ~]# ssh-add -l
The agent has no identities.
'暂时没有托管的密钥'
[root@Rocky10 ~]# ssh-add ~/.ssh/id_rsa_test
Identity added: /root/.ssh/id_rsa_test (root@Rocky10)
[root@Rocky10 ~]# ssh-add ~/.ssh/myed25519
Identity added: /root/.ssh/myed25519 (root@Rocky10)
[root@Rocky10 ~]# ssh-add -l
4096 SHA256:Fryh+p6TyB/fEv3PRCCqGiS9YuL/AzQIiUnU7QVut2I root@Rocky10 (RSA)
# 这个是RSA,不推荐使用这个
256 SHA256:jyPGkYvl7jd8mSjW21fS2m8MwYj3zMm3lRXLRybjR0I root@Rocky10 (ED25519)
# 推荐使用这个!ED25519
再次远程连接测试!
[root@Rocky10 ~]# ssh 10.0.0.7
...'此时ssh-agent会选择与服务端配对的私钥进行连接:'
Last login: Mon Mar 9 19:09:47 2026 from 10.0.0.111
[root@web01 ~]#
# 这次即使没有指定密钥也是顺利登录上去了!
3)有密码的私钥!
[root@Rocky10 ~]# ssh-keygen -f ~/.ssh/key2 -t ed25519 -N '123456'
# -N给私钥设置密码!
[root@Rocky10 ~]# ssh-copy-id -i ~/.ssh/key2.pub 10.0.0.8
# 这次我们拷贝公钥给web02!
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/key2.pub"
# 它是有密码的私钥!
Now try logging into the machine, with: "ssh -i /root/.ssh/key2 '10.0.0.8'"
# 直接运行它提示的启动方式就行!
[root@Rocky10 ~]# ssh -i /root/.ssh/key2 '10.0.0.8'
# 远程连接尝试一下!
Authorized users only. All activities may be monitored and reported.
Enter passphrase for key '/root/.ssh/key2':
# 输入私钥的密码-N '123456'
...from 10.0.0.111 on ssh:notty
[root@web02 ~]#
# 也是成功登录到了web02中!
# 只是需要输入私钥的密码而已!
但还是觉得麻烦怎么办???
'ssh-agent'
[root@web02 ~]#exit
logout
Connection to 10.0.0.8 closed.
[root@Rocky10 ~]# ssh-add ~/.ssh/key2
Enter passphrase for /root/.ssh/key2:
# 输入私钥的密码
Identity added: /root/.ssh/key2 (root@Rocky10)
[root@Rocky10 ~]# ssh-add -L
# 查看被加入的私钥!
测试验证!
[root@Rocky10 ~]# ssh 10.0.0.8
[root@web02 ~]#exit
# 直接就登录进来了!无需输入私钥的密码!

排错流程#

Terminal window
# 无法使用秘钥登录排查:
[root@nfs ~]#ll -d / # 根555
dr-xr-xr-x. 20 root root 264 Nov 28 12:04 /
[root@nfs ~]#ll -d /root # root目录权限 550
dr-xr-x--- 4 root root 196 Dec 1 12:01 /root
[root@nfs ~]#ll -d .ssh # .ssh隐藏目录权限700
drwx------ 2 root root 48 Dec 1 11:58 .ssh
[root@nfs ~]#ll .ssh/ # 存放公钥的文件权限600
-rw------- 1 root root 946 Dec 1 11:58 authorized_keys
'必须严格按照这个权限格式'
Terminal window
[root@Rocky10 ~]# mkdir /test
[root@Rocky10 ~]# ssh-keygen -t ed25519 -f /test/myed25519 -N ''
Generating public/private ed25519 key pair.
Your identification has been saved in /test/myed25519
Your public key has been saved in /test/myed25519.pub
The key fingerprint is:
SHA256:9lRMTi5LqtsP9ytEku02k80Onjend+XUn6o7xbpkKkE root@Rocky10
The key's randomart image is:'
+--[ED25519 256]--+
| o |
| * |
| oo = |
| Eooo+ |
| . S+o+. .|
| + oO oo +|
| . o+oOo o+|
| + oB++ o.+|
| . oo.*OB.. |
+----[SHA256]-----+
[root@Rocky10 ~]# ll /test/
total 8
-rw-------. 1 root root 399 Mar 9 21:06 myed25519
-rw-r--r--. 1 root root 94 Mar 9 21:06 myed25519.pub
# 文件权限是对的!
[root@Rocky10 ~]# ll -d /test/
drwxr-xr-x. 2 root root 44 Mar 9 21:06 /test/
# 目录权限有点大!
[root@Rocky10 ~]# ssh-copy-id -i /test/myed25519.pub 10.0.0.9
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/test/myed25519.pub"
The authenticity of host '10.0.0.9 (10.0.0.9)' can't be established.'
ED25519 key fingerprint is SHA256:uvRHkeRP2lLpymyd4ZuJcj+J2j2I5iUdnfo3GiLcFx4.
.......
Authorized users only. All activities may be monitored and reported.
root@10.0.0.9's password: '
.......
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -i /test/myed25519 '10.0.0.9'"
# 我们试着连一下!
[root@Rocky10 ~]# ssh -i /test/myed25519 '10.0.0.9'
[root@web03 ~]#exit
# 这里目录权限虽然有点大,但是也是成功连上来了!
[root@Rocky10 ~]# chmod 777 /test/myed25519
[root@Rocky10 ~]# ll /test/
total 8
-rwxrwxrwx. 1 root root 399 Mar 9 21:06 myed25519
# 但是你把私钥权限放大,就不行了,无法免密连接!
[root@Rocky10 ~]# ssh -i /test/myed25519 '10.0.0.9'
Authorized users only. All activities may be monitored and reported.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/test/myed25519' are too open.
Load key "/test/myed25519": bad permissions
root@10.0.0.9's password: '
# 需要再次输入web03的密码才行!
[root@web03 ~]#ll ~/.ssh
total 4
-rw------- 1 root root 94 Mar 9 21:08 authorized_keys
# web03的这个文件也是,需要严格遵守这个权限!
[root@web03 ~]#chmod 777 ~/.ssh/authorized_keys
[root@web03 ~]#ll ~/.ssh
total 4
-rwxrwxrwx 1 root root 94 Mar 9 21:08 authorized_keys
# 改完之后,Rocky连不上去的!
[root@web03 ~]#chmod 700 ~/.ssh/authorized_keys

image-20260126193339300
image-20260126193339300

  • 输入用户名,密码,不安全

    通常直接禁用 用户密码 登录的方式,强制使用密钥对登录

    PasswordAuthentication no

🍔如果我们A服务器想要登录B服务器,通常是把A生成的公钥放在B服务器上

  • 那么,黑客如果想要登录B的话,必须拿到A的私钥才能登录上去

    私钥比较难破解

Terminal window
1.windows生成密钥对
xshell-->工具-->新建秘钥生成向导-->下一步-->属性-->公钥
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsdJN1awpt35mAxKeBgFx9bf0KKpen7AlcdpbS9T22uOWfVpKsaWjuOs/OzsfRpHcvhZy7TjSnpIJNPzpgkaeP0PgBZlYnE3HljL1zHbmJsyywKlQccrVq5MC9omBubqR3V5cGRSpkhtMzTr4vHuDO4kehKR/JylBCsvHRxRRtKa8RYOIc65i3eqEYAEZbqwQ6nkbNDByMQoXLpTZDwG//HLFeqUoQlQi8a01k7wfM0+PN8r4yhnAlFzhEqht9jOASDO4CEnwI35mnmEIaRvn/sVCJT4QjqjsQzcAII+GofXYUAa+aqxL9H2Y5keplOZG0BPyLepDilFuF5wD1uag4Q== rsa 2048-012626
2.将windows的公钥写入到目标服务器
[root@backup ~]#ll /root/.ssh/
total 12
-rw------- 1 root root 2590 Jan 26 18:47 id_rsa
-rw-r--r-- 1 root root 565 Jan 26 18:47 id_rsa.pub
-rw-r--r-- 1 root root 338 Jan 25 16:44 known_hosts
'认证文件不存在需要手动创建,权限必须为600'
[root@backup ~]#vim /root/.ssh/authorized_keys
[root@backup ~]#chmod 600 /root/.ssh/authorized_keys
[root@backup ~]#ll /root/.ssh/authorized_keys
-rw------- 1 root root 398 Jan 26 19:46 /root/.ssh/authorized_keys
3.Windows验证登录
[C:\~]$ ssh 172.16.1.41
# ssh登不上内网,我们得登录公网才行
[C:\~]$ ssh 10.0.0.41
# 输入用户名-->选择下面Public Key-->确定
# 直接连接进来,不使用密码
4.修改SSH禁止密码登录
[root@nfs ~]#sed -n '66p' /etc/ssh/sshd_config
PasswordAuthentication no
5.重启生效
[root@nfs ~]#systemctl restart sshd
6.Windows再次验证
'用户名密码那一栏都是灰色的,点不亮'

image-20260126200731022
image-20260126200731022

关闭后面服务器的外网,只留下内网,通过一个 跳板机 实现 远程登录

先通过外网连接 跳板机 ,再通过内网管理后面的服务器

ssh跳板机实验#

image-20260314152211511
image-20260314152211511

Terminal window
A、B、C、D
四个机子!四个用户!
'需要提前关闭防火墙和SELINUX'
1)用户的创建的密码赋值
[root@lb02 ~]#hostname -I
10.0.0.6 172.16.1.6
[root@lb02 ~]#hostnamectl set-hostname A
useradd userA
echo redhat123.com | passwd --stdin userA
hostnamectl set-hostname B
useradd userB
echo redhat123.com | passwd --stdin userB
hostnamectl set-hostname C
useradd userC
echo redhat123.com | passwd --stdin userC
hostnamectl set-hostname D
useradd userD
echo redhat123.com | passwd --stdin userD
2)隐藏目录的创建和公钥文件的创建!
B:
mkdir /home/userB/.ssh/
touch /home/userB/.ssh/authorized_keys
chmod 700 /home/userB/.ssh/
chmod 600 /home/userB/.ssh/authorized_keys
chown -R userB:userB /home/userB/.ssh/
C:
mkdir /home/userC/.ssh/
touch /home/userC/.ssh/authorized_keys
chmod 700 /home/userC/.ssh/
chmod 600 /home/userC/.ssh/authorized_keys
chown -R userC:userC /home/userC/.ssh/
D:
mkdir /home/userD/.ssh/
touch /home/userD/.ssh/authorized_keys
chmod 700 /home/userD/.ssh/
chmod 600 /home/userD/.ssh/authorized_keys
chown -R userD:userD /home/userD/.ssh/
3)A密钥对的生成
[root@A ~]#su - userA
'需要userA执行'
[userA@A ~]$ssh-keygen -t ed25519 -f ~/.ssh/keyA -N ''
Generating public/private ed25519 key pair.
Created directory '/home/userA/.ssh'.
Your identification has been saved in /home/userA/.ssh/keyA
Your public key has been saved in /home/userA/.ssh/keyA.pub
The key fingerprint is:
SHA256:yhA68kvhwx6pRr+LRdTeD8jdZWY2rMnvE+kP/VHrwZQ userA@A
The key's randomart image is:'
+--[ED25519 256]--+
| |
| . . |
| ... O |
| ..o.+ o O . .|
|. +..+ +S= . E.|
| *.+ o .o .o. o o|
|. X. o ..o.. = |
| =o= .o. o o|
|o.ooo .o. o |
+----[SHA256]-----+
[userA@A ~]$cat ~/.ssh/keyA.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILgjjgCciYSn/vc3CsR1CcbMEweZ6538RCvH6xsYjhy6 userA@A
4)公钥的分发!
echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILgjjgCciYSn/vc3CsR1CcbMEweZ6538RCvH6xsYjhy6 userA@A > ~/.ssh/authorized_keys
[root@B ~]#su - userB
[userB@B ~]$echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILgjjgCciYSn/vc3CsR1CcbMEweZ6538RCvH6xsYjhy6 userA@A > ~/.ssh/authorized_keys
[root@C ~]#su - userC
[userC@C ~]$echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILgjjgCciYSn/vc3CsR1CcbMEweZ6538RCvH6xsYjhy6 userA@A > ~/.ssh/authorized_keys
[root@D ~]#su - userD
[userD@D ~]$echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILgjjgCciYSn/vc3CsR1CcbMEweZ6538RCvH6xsYjhy6 userA@A > ~/.ssh/authorized_keys
4)客户端配置文件的创建!
[userA@A ~]$vim ~/.ssh/config
Host B
HostName 172.16.1.9
User userB
Port 22
IdentityFile ~/.ssh/keyA
Host C
HostName 172.16.1.52
User userC
Port 22
IdentityFile ~/.ssh/keyA
ProxyJump B
Host D
HostName 172.16.1.53
User userD
Port 22
IdentityFile ~/.ssh/keyA
ProxyJump C
Terminal window
刚开始还是登录不上???
改了一下配置文件的权限!
[userA@A .ssh]$chmod 600 config
[userA@A .ssh]$ll
total 16
-rw------- 1 userA userA 297 Mar 10 19:48 config
-rw------- 1 userA userA 399 Mar 10 19:41 keyA
-rw-r--r-- 1 userA userA 89 Mar 10 19:41 keyA.pub
-rw-r--r-- 1 userA userA 518 Mar 10 20:18 known_hosts
[userA@A .ssh]ssh C
Authorized users only. All activities may be monitored and reported.
❌️ channel 0: open failed: administratively prohibited: open failed
❌️ stdio forwarding failed
❌️ kex_exchange_identification: Connection closed by remote host
!!!报错!!
.....

核心原因:

跳板机 B 上的 SSH 服务(sshd)禁止了 stdio 转发(即 -W 或 ProxyJump 所需的通道)

虽然你成功登录到了 B,但 B 不允许你通过它转发流量到其他主机(如 C)

Tip
Terminal window
[root@B ~]#sudo grep -E "AllowTcpForwarding|PermitOpen|ForceCommand" /etc/ssh/sshd_config
#AllowTcpForwarding yes
# AllowTcpForwarding no
# ForceCommand cvs server
AllowTcpForwarding no

默认把禁止转发开开了!!!AllowTcpForwarding yes

改过来之后!就行了!

Terminal window
[userA@A .ssh]$ssh D
Authorized users only. All activities may be monitored and reported.
Authorized users only. All activities may be monitored and reported.
Authorized users only. All activities may be monitored and reported.
|\ /|
___| \,,/_/
---__/ \/ \
__--/ (D) \
_ -/ (_ \
// / \_ / -\
__-------_____--___--/ / \_ O o)
/ / \__/
/ /
|| ) \_/\
|| / _ / |
| | /--______ ___\ /\ :
| / __- - _/ ------ | | \ \
| - - / | | \ )
| | - | | ) | |
| | | | | | | |
| | < | | | |_/
< | /__\ < \
/__\ /___\
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
奔腾如骏 稳如磐石
系统常青 永不死机
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Tue Mar 10 20:18:03 2026 from 172.16.1.52
[userD@D ~]$exit
logout
Connection to 172.16.1.53 closed.

两个不同 ssh 安全机制#

Important

在我自己的认知里面,一直学的 ==ssh== 免密钥登录的安全机制!

  • 为了让你 不用每次输入密码就能登录服务器 ,即所谓的 ==“免密登录”==

    我们后期搭集群和服务的时候,用的非常多!

image-20260307083154030
image-20260307083154030


Note

但是,老师昨天下午,第一个讲的并不是这个机制!而是另一种机制

  • 防止 中间人攻击,确保你连接的是真正的目标服务器,而不是一个伪装的中间人
  • 客户端首次连接时:
    • 服务器会将自己的 公钥 发送给客户端
    • 客户端会提示你是否信任该服务器(显示指纹),如果你确认,就将这个公钥存入 ~/.ssh/known_hosts
  • 后续连接时:
    • 客户端会比对服务器发来的公钥是否与 known_hosts 中记录的一致
    • 如果不一致(比如服务器重装了系统或 IP 被劫持),SSH 会发出警告,防止你被中间人欺骗
Terminal window
'我们这里用rocky登录OpenEuler'
[root@Rocky10 ~]# cd ~/.ssh/
[root@Rocky10 .ssh]# ll
total 0
# 现在什么都没有
[root@Rocky10 .ssh]# ssh root@10.0.0.112
...
ED25519 key fingerprint is SHA256:UcR7/gPV1ZOcD5GWJdHZiwPUcd89x9OQjbsvWie55Q8.
# 指纹
...
Are you sure you want to continue connecting (yes/no/[fingerprint])?
# 输入yes后,你的~./Extension12/目录就有known_hosts文件了!
Authorized users only. All activities may be monitored and reported.
root@10.0.0.112's password: '
# 因为我们没有配免密登录,所以这里需要输入OpenEuler的密码
[root@OpenEuler ~]#
# 输入密码后,我们就能够成功的进来了!
[root@OpenEuler ~]# exit
logout
Connection to 10.0.0.112 closed.
[root@Rocky10 .ssh]#
# 退出至rocky,再次查看目录下的内容!
[root@Rocky10 .ssh]# ll
total 8
-rw-------. 1 root root 656 Mar 7 09:32 known_hosts
[root@Rocky10 .ssh]# cat known_hosts
# 里边存的就是目标服务器(OpenEuler)的公钥!
--------------------------------
[root@Rocky10 ~]# su - www
Last login: Mon Mar 9 20:23:55 CST 2026 on pts/1
# 切换另一个用户!
[www@Rocky10 ~]$ ssh 10.0.0.112
The authenticity of host '10.0.0.112 (10.0.0.112)' can't be established.'
ED25519 key fingerprint is SHA256:UcR7/gPV1ZOcD5GWJdHZiwPUcd89x9OQjbsvWie55Q8.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
'我们明明已经输入过了yes但是为什么还是出来这样的提示呢??'
# 这个是www用户,它的家目录下(~./Extension12/)并没有known_hosts文件了
# 它是第一次连接OpenEuler
'此公钥和root用户的known_hosts文件中的OpenEuler公钥一致'
--------------------------------
[root@Rocky10 .ssh]# ssh root@10.0.0.112
# 下次再远程连接OpenEuler直接输入密码就行了!
# 确认就是它,没有别的中间人!
Authorized users only. All activities may be monitored and reported.
root@10.0.0.112's password: '
'这里我用别的服务器,直接修改为和OpenEuler一样的IP地址,再次ssh连接试试!'
[root@web01 ~]#hostname
web01
[root@web01 ~]#hostname -I
10.0.0.7 172.16.1.7
[root@web01 ~]#systemctl restart network
# 重启网络后,当前服务器Xshell自动退出
[root@OpenEuler ssh]#
Socket error Event: 32 Error: 10053.
Connection closing...Socket close.
# 而且我的OpenEuler的Xshell也自动退出了
'我们把OpenEuler关机,只留下web01这个中间人'
# 再次连接Xshell(OpenEuler)
'表面是OpenEuler,但实际上是web01,只不过IP相同罢了!'

image-20260307095738163
image-20260307095738163

image-20260307095755487
image-20260307095755487

  • 这个时候Xshell就已经开始提示了!

  • 主机密钥已更改!有人试图监听此连接!

    我们依旧 yes保存!

Terminal window
[root@web01 ~]#hostname -I
10.0.0.112 172.16.1.7
# 实际上是web01,但只不过把IP改为了OpenEuler的IP罢了!
'我们用rocky再次ssh登录10.0.0.112'
[root@Rocky10 .ssh]# ssh root@10.0.0.112
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
It is also possible that a host key has just been changed.
# 很可能是主机密钥发生了变更!
Please contact your system administrator.
# 请联系管理员
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
# 在 /root/.ssh/known_hosts 文件中添加正确的主机密钥,以消除此警告信息
Offending RSA key in /root/.ssh/known_hosts:2
# 冲突密钥的位置!
Host key for 10.0.0.112 has changed
Host key verification failed.
# 主机密钥已更改!验证失败!

总结#

Important

两种机制同时工作!共同保障 SSH 的安全性:

  • known_hosts 确保你没连错服务器(防钓鱼)
  • authorized_keys 让你不用输密码就能证明“我是我”

两者缺一不可,但解决的问题不同

目的谁生成密钥对?公钥放在哪里?验证方向
防中间人攻击,确认连接的是正确的服务器服务端 生成(安装 SSH 时自动生成)客户端的 ~/.ssh/known_hosts客户端 → 验证服务器身份
免密码登录,证明“我是合法用户”客户端 生成(通常用 ssh-keygen服务端目标用户的 ~/.ssh/authorized_keys服务器 → 验证客户端身份

✅ 简记口诀:

  • 防中间人服务端 → 公钥给客户端(存 known_hosts)
  • 免密登录客户端 → 公钥给服务端(存 authorized_keys)

两者配合,既防“连错服务器”,也防“冒充用户”,共同构建 SSH 的双向信任体系 🔒

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

ssh服务
https://www.kpyun.fun/posts/basics/extension/extension12/
作者
久棹
发布于
2025-10-04
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录