OpenSSH服务

本文最后更新于:2023年12月5日 晚上

说明:ssh 客户端(后面简称 ssh)、ssh 服务端(后面简称 sshd)

SSH 认证过程

Client 10.0.0.8 ssh 远程连接 Server 10.0.0.7:

[root@centos8 ~]$ssh 10.0.0.7
The authenticity of host '10.0.0.7 (10.0.0.7)' can't be established.
ECDSA key fingerprint is SHA256:CfDVSb/UU590ZKQ0DZhZp7/76rLHeKak/pHGp2af4kw.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.0.7' (ECDSA) to the list of known hosts.
root@10.0.0.7's password:
Last login: Wed Sep  9 19:05:15 2020 from 10.0.0.8
[root@centos7 ~]#

  1. no.6、no.8:协商版本号,可以看到 Client 的 OpenSSH 版本更高,则以 Server 为准

  2. no.10、no.11:相互交换各自支持的算法,协商各种算法,以 Client 优先

  3. no.12 - 14:使用 DH 算法交换密钥,之后的通信都使用会话密钥加密,具体参考笔记[13.2 DH.md](./13.2 DH.md),

  4. 认证:SSH 支持多种认证,最常用的是口令认证和密钥认证,这个过程已经加密了,用 Wireshark 抓包看不出任何信息

相关文件

一台主机,既可以是 ssh Client,也可以是 ssh Server

ssh Client 相关文件

文件 说明
/etc/ssh/ssh_config 客户端全局配置文件
~/.ssh/config 客户端的用户配置文件,默认不存在,权限只能是 644
~/.ssh/known_hosts 保存服务端的公钥
~/.ssh/id_rsa 客户端私钥,由 ssh-keygen 生成,权限只能是 600
~/.ssh/id_rsa.pub 客户端公钥,由 ssh-keygen 生成

/etc/ssh/ssh_config:

需要说明的是,客户端配置文件有很多配置项和服务端配置项名称相同,但它们一个是在连接时采取的配置(客户端配置文件),一个是 sshd 启动时开关性的设置(服务端配置文件)。例如,两配置文件都有 GSSAPIAuthentication 项,在客户端将其设置为 no,表示连接时将直接跳过该身份验证机制,而在服务端设置为 no 则表示 sshd 启动时不开启 GSSAPI 身份验证的机制。即使客户端使用了 GSSAPI 认证机制,只要服务端没有开启,就绝对不可能认证通过。

选项 默认值 说明
PasswordAuthentication yes 是否启用基于密码的身份认证机制
HostbasedAuthentication no 是否启用基于主机的身份认证机制
GSSAPIAuthentication no 是否启用基于 GSSAPI 的身份认证机制
BatchMode no yes:将禁止 passphrase/password 询问
StrictHostKeyChecking ask yes:拒绝连接那些未知的主机,它将强制用户手动添加 host key 到~/.ssh/known_hosts 中;
ask:询问是否保存到~/.ssh/known_hosts 文件;
no:自动添加到~/.ssh/known_hosts 文件
Port 22 当命令行中不指定端口时,默认连接的远程主机上的端口

ssh Server 相关文件

文件 说明
/etc/ssh/sshd_config 服务端全局配置文件
/etc/ssh/sshhost* sshd 启动时生成的服务端公钥和私钥文件,其中私钥文件权限只能是 600
~/.ssh/authorized_keys 保存客户端的公钥,用于 key 验证,免密登录

/etc/ssh/sshd_config:

#Port 22                # 服务端SSH端口,可以指定多条表示监听在多个端口上
#ListenAddress 0.0.0.0  # 监听的IP地址。0.0.0.0表示监听所有IP
Protocol 2              # 使用SSH 2版本

#####################################
#          私钥保存位置               #
#####################################
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key      # SSH 1保存位置/etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key  # SSH 2保存RSA位置/etc/ssh/ssh_host_rsa _key
#HostKey /etc/ssh/ssh_host_dsa_key  # SSH 2保存DSA位置/etc/ssh/ssh_host_dsa _key


###################################
#           杂项配置               #
###################################
#PidFile /var/run/sshd.pid        # 服务程序sshd的PID的文件路径
#ServerKeyBits 1024               # 服务器生成的密钥长度
#SyslogFacility AUTH              # 使用哪个syslog设施记录ssh日志。日志路径默认为/var/log/secure
#LogLevel INFO                    # 记录SSH的日志级别为INFO

###################################
#   以下项影响认证速度               #
###################################
#UseDNS yes                       # 指定是否将客户端主机名解析为IP,以检查此主机名是否与其IP地址真实           对应。默认yes。
                                  # 由此可知该项影响的是主机验证阶段。建议在未配置DNS解析时,将其设置           为no,否则主机验证阶段会很慢

###################################
#   以下是和安全有关的配置           #
###################################
#PermitRootLogin yes              # 是否允许root用户登录
#GSSAPIAuthentication no          # 是否开启GSSAPI身份认证机制,默认为yes
#PubkeyAuthentication yes         # 是否开启基于公钥认证机制
#AuthorizedKeysFile  .ssh/authorized_keys  # 基于公钥认证机制时,来自客户端的公钥的存放位置
PasswordAuthentication yes        # 是否使用密码验证,如果使用密钥对验证可以关了它
#PermitEmptyPasswords no          # 是否允许空密码,如果上面的那项是yes,这里最好设置no
#MaxSessions 10                   # 最大客户端连接数量
#LoginGraceTime 2m                # 身份验证阶段的超时时间,若在此超时期间内未完成身份验证将自动断开
#MaxAuthTries 6                   # 指定每个连接最大允许的认证次数。默认值是6。
                                  # 如果失败认证次数超过该值一半,将被强制断开,且生成额外日志消息。
MaxStartups 10                    # 最大允许保持多少个未认证的连接。默认值10。

###################################
#   以下可以自行添加到配置文件        #
###################################
DenyGroups  hellogroup testgroup  # 表示hellogroup和testgroup组中的成员不允许使用sshd服务,即拒绝                      这些用户连接
DenyUsers   hello test            # 表示用户hello和test不能使用sshd服务,即拒绝这些用户连接

###################################
#   以下一项和远程端口转发有关        #
###################################
#GatewayPorts no                  # 设置为yes表示sshd允许被远程主机所设置的本地转发端口绑定在非环回          地址上
                                  # 默认值为no,表示远程主机设置的本地转发端口只能绑定在环回地址上,见           后文"远程端口转发"

一般来说,如非有特殊需求,只需修改下监听端口和 UseDNS 为 no 以加快主机验证阶段的速度即可。

ssh 客户端工具

ssh

ssh [options] [user@]remote_host [command]

-p port      # 远程服务监听的端口,默认是22
-o option    # 临时修改配置
-i <file >   # 指定私钥文件,默认使用 ~/.ssh/id_xxx

ssh-keygen

在客户端生成密钥对,默认存放在~/.ssh 目录下

ssh-keygen -t rsa # 提示保存位置,输入密码

ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa # 不提示直接生成密钥

ssh-copy-id

使用 SSH 协议,将公钥追加到服务器的 ~/.ssh/authorized_keys 文件中

ssh-copy-id -i ~/.ssh/id_rsa.pub remote_host

scp

scp 命令用于 Linux 之间复制文件和目录,基于 SSH 协议。

scp [options] SRC... DEST/

-C    # 压缩数据流
-r    # 递归复制
-p    # 保持原文件的属性信息
-q    # 静默模式
-P    # PORT 指明remote host的监听的端口

范例:

# 从本地复制到远程:
scp local_file root@to2b.cn:remote_file
scp local_file root@lujinkai:remote_file
scp local_file root@test.to2b.cn:remote_file

# 从远程复制到本地:
scp root@to2b.cn:remote_file local_file
scp root@lujinkai.cn:remote_file local_file
scp root@test.to2b.cn:remote_file local_file

rsync

rsync 工具基于 SSH 和 RSYNC 协议实现高效率的远程系统之间复制文件,比 scp 更快,基于增量数据同步,此工具来自于 rsync 包

注意:通信双方都需要安装 rsync 软件

rsync -av /etc server1:/tmp #复制目录和目录下文件
rsync -av /etc/ server1:/tmp #只复制目录下文件

-n                    # 模拟复制过程
-v                    # 显示详细过程,-vvvv显示更详细的信息
-r                    # 递归复制目录树
-p                    # 保留权限(不包括特殊权限)
-t                    # 保留修改时间戳(mtime),强烈建议任何时候都加上"-t",否则目标文件mtime会设置为系统时间,导致下次更新
-g                    # 保留组信息
-o                    # 保留所有者信息
-l                    # 将软链接文件本身进行复制(默认)
-L                    # 将软链接文件指向的文件复制
-u                    # 如果接收者的文件比发送者的文件较新,将忽略同步
-z                    # 压缩,节约网络带宽
-D                    # "--device --specials"选项的组合,即也拷贝设备文件和特殊文件
-a                    # 存档,相当于-rlptgoD,但不保留ACL(-A)和SELinux属性(-X)
-b                    # 对目标上已存在的文件做一个备份,备份的文件名后默认使用"~"做后缀
--delete              # 源数据删除,目标数据也自动同步删除
--max-size            #
--min-size            # 限制rsync传输的最小文件大小。这可以用于禁止传输小文件或那些垃圾文件
--exclude             # 排除不需要传输的文件
--port                # 连接daemon时使用的端口号,默认为873端口
--existing            # 只更新目标端已存在的文件,注意:使用相对路径时如果上层目录不存在也不会传输
--ignore-existing     # 要求只更新目标端不存在的文件。和"--existing"结合使用有特殊功能
--remove-source-files # 要求删除源端已经成功传输的文件

范例:

[root@centos8 ~]#rsync -auv --delete /data/test 10.0.0.7:/data

sftp

交互式文件传输工具,利用 ssh 服务实现安全的文件上传和下载,使用 ls cd mkdir rmdir pwd get put 等指令,详细说明可以使用 help 查看

范例:

[lujinkai@ubuntu1804 data]$sftp root@10.0.0.7
root@10.0.0.7's password:
Connected to 10.0.0.7.
sftp> help # 查看帮助
Available commands:
bye                                Quit sftp
cd path                            Change remote directory to 'path'
chgrp grp path                     Change group of file 'path' to 'grp'
chmod mode path                    Change permissions of file 'path' to 'mode'
chown own path                     Change owner of file 'path' to 'own'
df [-hi] [path]                    Display statistics for current directory or
                                   filesystem containing 'path'
exit                               Quit sftp
get [-afPpRr] remote [local]       Download file
reget [-fPpRr] remote [local]      Resume download file
reput [-fPpRr] [local] remote      Resume upload file
help                               Display this help text
lcd path                           Change local directory to 'path'
lls [ls-options [path]]            Display local directory listing
lmkdir path                        Create local directory
ln [-s] oldpath newpath            Link remote file (-s for symlink)
lpwd                               Print local working directory
ls [-1afhlnrSt] [path]             Display remote directory listing
lumask umask                       Set local umask to 'umask'
mkdir path                         Create remote directory
progress                           Toggle display of progress meter
put [-afPpRr] local [remote]       Upload file
pwd                                Display remote working directory
quit                               Quit sftp
rename oldpath newpath             Rename remote file
rm path                            Delete remote file
rmdir path                         Remove remote directory
symlink oldpath newpath            Symlink remote file
version                            Show SFTP version
!command                           Execute 'command' in local shell
!                                  Escape to local shell
?                                  Synonym for help
sftp> pwd # 查看远程服务器目录
Remote working directory: /root
sftp> lpwd # 查看本机目录
Local working directory: /home/lujinkai/data
sftp> ls
ELS.txt  a.log
sftp> get a.log /tmp/ # get 下载文件
Fetching /root/data/a.log to /tmp/a.log
/root/data/a.log                                        100%   21     6.5KB/s   00:00
sftp> put /etc/passwd ./ # 上传文件
Uploading /etc/passwd to /root/data/./passwd
/etc/passwd                                             100% 1567   544.2KB/s   00:00

高级应用

SSH 端口转发能够提供两大功能:

  • 加密 SSH Client 端至 SSH Server 端之间的通讯数据
  • 突破防火墙的限制完成一些之前无法建立的 TCP 连接

SSH 本地端口转发

三台主机:

host1:家用电脑,公网中
host2:业务服务器,内网中
host3:中转服务器,内网中

host1 不能直接连接 host2,但是可以通过 host3 中转,在 host1 上执行下面命令:

ssh -fNL 1234:host2_ip:80 [host3_user@]host3_ip

-N                                   # 不打开远程shell,适用于转发端口
-f                                   # 后台启用,避免占用终端前台
-L [bind_address:]port:host:hostport # 本机端口:目标主机:目标主机端口,默认ssh只监听127.0.0.1的port,指定bind_address,则监听bind_address的port,如果bind_address设置为0.0.0.0,表示监听本机全部地址的port
host3                                # 中转服务器
# host1:CentOS6 10.0.0.6
# host2:CentOS7 10.0.0.7
# host3:CentOS 10.0.0.8

# host1 ssh监听本机的1234端口,将1234端口的请求通过10.0.0.8转发到10.0.0.7的80端口
[root@centos6 ~]# ssh -fNL 1234:10.0.0.7:80 root@10.0.0.8
[root@centos6 ~]# curl 127.0.0.1:1234
hello nginx!

# host2
[root@centos7 ~]#cat /usr/local/nginx/html/index.html
hello nginx!
[root@centos7 ~]#tail -f /usr/local/nginx/logs/access.log
10.0.0.8 - - [12/Sep/2020:14:15:53 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

绑定本地端口,指定数据传送的目标主机,们把这种情况称为”本地端口转发”(Local forwarding)。

因为 host1 和 host3 通信使用 SSH 加密,仿佛形成一个数据传输的秘密隧道,因此又被称为”SSH 隧道”。

SSH 远程端口转发

三台主机:

host1:家用电脑,公网中
host2:业务服务器,内网中
host3:中转服务器,内网中

host1 不能直接连接 host2,也不能直接连接 host3,但是 host3 既可以连接 host1,又可以连接 host2,所有使用 host3 做中转。

远程端口转发 和 本地端口转发 逻辑上刚好相反:

  • 本地端口转发是 host1 主动监听本机的 1234 端口(因为主动,所以是 ssh 监听 1234),要求 host3 帮忙转发;
  • 远程端口转发是 host3 通知 host1,让其监听自身的 1234 端口(因为被动,所以是 sshd 监听 1234),host3 主动拿帮 host1 转发。
ssh -fNR 1234:host2_ip:80 [host1_user@]host1_ip

-R [bind_address:]port:host:hostport   # 远程主机端口:目标主机:目标主机端口
# host1:CentOS6 10.0.0.6
# host2:CentOS7 10.0.0.7
# host3:CentOS 10.0.0.8

# host3
[root@centos8 ~]$ssh -fNR 1234:10.0.0.7:80 root@10.0.0.6

# host1,成功访问到host2,
[root@centos6 ~]# curl 127.0.0.1:1234
hello nginx!

SSH 动态端口转发

ssh -D 1080 root@10.0.0.8

SSH 创建 SOCKS 代理服务,去监听本地的 1080 端口。一旦有数据传向那个端口,就自动把它转移到 SSH 连接上面,发往远程主机 10.0.0.8。可以想象,如果 1080 端口原来是一个不加密端口,现在将变成一个加密端口。

目前 SOCKS4 和 SOCKS5 协议支持端口转发:

# CentOS6 配置 SOCKS代理
[root@centos6 ~]# ssh -fND 1080 root@10.0.0.8
# CentOS8替CentOS6访问http://10.0.0.7,将返回数据加密,发送回CentOS6
[root@centos6 ~]# curl --socks5 127.0.0.1:1080 http://10.0.0.7
hello nginx!

X 协议转发


OpenSSH服务
http://blog.lujinkai.cn/运维/基础/加密和安全/OpenSSH服务/
作者
像方便面一样的男子
发布于
2020年12月9日
更新于
2023年12月5日
许可协议