本网站相关文章:

Introduction

Secure Shell

SSH: Secure Shell, 一种加密的网络传输协议, 通过在网络中建立一个虚拟的安全隧道来实现 client 和 server 之间的安全通信, 通过压缩数据, 加密数据, 以更加安全, 更少量的流量进行数据流通.

在了解了 SSH 的基本定义之后, 让我们带着如下的问题注意了解 SSH:

  • SSH 提出的目的是为了解决哪些问题?
  • SSH 的应用场景是什么?
  • SSH 的通信原理或者交互流程是怎样的?
  • SSH 如何安装和配置?

在了解了上述的基本内容之后, 我们后续会继续讲解 SSH 的进阶应用:

  • ssh agent 是什么?应用场景是什么?如何使用?
  • ssh tunnel 是什么?应用场景是什么?如何使用?

再将知识面扩展, 由 SSH 引申出安全相关话题, 进而了解TSL安全通信, authentication认证等等内容, 这些会在以前或者后续的文章中给出, 本篇文章主要讲解Secure Shell相关知识点.

术语

在介绍 SSH 相关知识点之前, 让我们先简单的了解一下相关的术语:

  • SSH1采用 DES,3DES,Blowfish 和 RC4 等对称加密算法保护数据安全传输,而对称加密算法的密钥是通过非对称加密算法(RSA)来完成交换的,使用 CRC 来保证数据的完整性.

  • SSH2避免了 RSA 的专利问题, 并修补了 CRC 的缺陷,SSH2 用数字签名算法(DSA)和 Diffie-Hellman(DH)算法代替 RSA 来完成对称密钥的交换,用消息证实代码(HMAC)来代替 CRC.

  • OpenSSH: SSH 最初是由芬兰的一家公司开发, 目前有两个版本的 openSSH, 其中大部分人都使用免费开源版本.

应用场景

让我们回到第一节提出的问题中来, SSH是因何提出来的? SSH的具体应用场景是哪些?

SSH在一开始就是为了替代telnet, ftp这种不安全的远程连接方式, 大部分应该都使用wireshark抓取过底层 TCP 报文, charles/Fiddler, 有时候会碰到普通的HTTP认证登录方式, 或者 telnet 认证方式, 这些密码信息以非常直白的方式呈现给第三方网络嗅探器, 造成极大的网络安全问题. 于是, 在 Shell 之上建立的安全隧道Secure Shell产生, 在HTTP之上建立的安全隧道HTTPS产生.

所以, SSH产生的原始是传统的 ftp, telnet 本质上都是不安全的, 在网络上使用明文进行传输 token/data, 相关的服务程序验证方式也存在弱点, 容易受到”中间人”攻击, 密码容易被抓包工具截获, 造成密码泄露.

目前来说, SSH主要用于远程安全登录, 当然, 其还用于SCP, SFTP等安全传输中, 另外基于SSH的安全隧道在很多场景中使用.

上述即使 SSH 的基本定义, 提出来由, 应用场景, 那么SSH为何能够确保安全性呢? SSH的交互流程是怎样的呢?

加密和认证

SSH 有两种方式进行认证:

  • 基于口令的验证: 密码登录, 可能会被中间人攻击
  • 基于密钥的验证: 一对 pulic key, private key

服务器B持有某一个特定公钥的前提下, 任何一个持有该公钥匹配的私钥的任何一个人, 都能正常成功的登录该服务器, 所有私钥的保护和密码一样都是非常重要的.

ssh process

Install

Ubuntu

1
2
sudo aptitude install openssh-server
sudo aptitude install openssh

Centos

1
yum install openssh-server

关于配置文件, 可从如下途径获取配置参数:

  • 命令行选项
  • 用户目录: ~/.ssh/config
  • 系统: /etc/ssh/ssh_config

其中配置文件的格式可以分为多个配置区段, 每一个区段都使用 Host 来区分, 当然,
我们可以在命令行中输入不同的 host 来加载不同的配置段.

另外, 不同于 nginx 中的配置加载, ssh configure的每一个配置项以首次获取的参数值为准,
所以需要将通用的配置放到文件末尾, 特定的配置放在前面.

Permissions

文件的拥有者, 文件的可访问权限影响了 ssh 连接中的各类问题, 需要确保

  • authorized_keys: 权限必须为 600
  • config: 权限必须为, 安装, , 安装, 命令介绍+ private_key_filename: 600
  • public_key_filename: 644

~/.ssh目录下各个文件的含义:

  • known_hosts: ssh 默认会将你访问过的计算机的 Public key, 登录进行 OpenSSH 校验, 如果公钥不同会发出警告, 避免 DNS Hijack 攻击
  • private_key_filename: 对称加密中的私钥
  • public_key_filename.pub: 对称加密中的公钥
  • config: 各个秘钥的配置
  • authorized_keys: 作为远程主机, 保存 Client 的公钥

Generate Key

Introduction

定义:ssh 公钥认证是 SSH 认证的一种方式

执行过程:获取$HOME/.ssh 下公钥和私钥,完成加密过程

命令:

1
2
3
4
5
6
ssh-keygen        Creates key pairs.
ssh-agent Agent for providing keys to remote servers. The agent holds loaded keys in memory.
ssh-add Loads a private key into the agent.

# 日志查看(重要)
/var/log/auth.log

Generate

生成公钥:

1
2
ssh-keygen        默认生成, 建议加密密钥对
ssh-keygen -f filename -c remarks(备注信息) -t rsa 指定生成

关于 config 配置文件, 见config介绍.

问题 1: 为何要对密钥对设置密码? 怎么设置?

对密钥对本身的加密吧, 避免密钥对被获取之后, 没有任何障碍的获取你所有服务器, 所有其他私密信息.
在使用ssh-keygen建议输入一个长密码, 如果想修改密码短语: ssh-keygen -f ~/.ssh/id_rsa -p.

Save

保存:

1
2
操作:保存,并拷贝公钥和私钥到.ssh目录下面
充分条件:保证当前用户对.ssh以及父目录有执行权限

登录

1
2
公钥导入服务器SSH:cat id_rsa.pub >> authorited_keys
客户端发起登录:进行公钥和私钥之间的秘密通信

Windows Configure

将所有的.ssh 压缩文件直接解压到 C:\用户\unlessbamboo\下面,会见到一个.ssh 的目录,其他原理同 linux.

SSH Client

Login

Login with password

1
ssh -p Port user@host

Login by Key

  • generate your own public/private key
  • save your public key in authorized_keys
  • connect
1
2
3
4
# login if exist config
ssh group-name
# login using common private key
ssh user@hostname -p Port

复制公钥到远程服务器

在创建好的公钥上传到远程服务器上, 以便使用 SSH 密钥认证.

传统方法: 拷贝文件到远程服务器

1
2
3
4
5
6
7
8
9
10
11
12
# 拷贝文件(此时需要使用密码)
scp ~/.ssh/id_ecdsa.pub username@remote-server.org:/home/username/
# 进入
ssh username@remote-server.org

# 将公钥加入到authorized中
mkdir ~/.ssh
cat ~/id_ecdsa.pub >> ~/.ssh/authorized_keys
rm ~/id_ecdsa.pub
# 设置权限, 并添加immutable, 避免权限被更改
chmod 600 ~/.ssh/authorized_keys
chattr +i ~/.ssh/authorized_keys

简单方式, 不会登陆服务器, 使用 ssh-copy-id 命令

1
2
3
4
5
6
# 上传默认id_rsa.pub文件, 其中远程服务器用户名同当前用户名相同
ssh-copy-id remote-server.org
# 其他
ssh-copy-id username@remote-server.org
ssh-copy-id -i ~/.ssh/id_ecdsa.pub username@remote-server.org
ssh-copy-id -i ~/.ssh/id_ecdsa.pub -p 221 username@remote-server.org

Options

Key

Host: 标识了一个配置项, 其中可用使用通配符, *, ?, !

HostName: 指定远程主机名, 可用使用 IP, Domain, 还可以使用 Format, 例如%h 会被命令行中的主机名替换

IdentityFile: 指定密钥认证使用的私钥文件路径, 默认为~/.ssh/id_rsa, 其中文件名称可用使用转义符,
可用指定多个秘钥文件, 认证时会依次尝试

BindAddress: 指定连接的时候使用的本地主机地址,只在系统有多个地址的时候有用

AddKeysToAgent: 是否自动将 key 加入到 ssh-agent, 可以为 no(default)/confirm/ask/yes

Port: 远程主机端口号, 默认为 22

User: 指定登录的用户名, 例如对于某一个固定 IP, 默认使用 root 登录, 则可用设置该值

GlobalKnownHostsFile: 指定一个或多个全局认证主机缓存文件,用来缓存通过认证的远程主机的密钥,多个文件用空格分隔
UserKnownHostsFile: 指定一个或多个用户认证主机缓存文件,用来缓存通过认证的远程主机的密钥.

其中转义符如下:

1
2
3
4
5
'%d' 本地用户目录
'%u' 本地用户名称
'%l' 本地主机名
'%h' 远程主机名
'%r' 远程用户名

默认缓存文件: ~/.ssh/known_hosts, /etc/ssh/ssh_known_hosts

关于通配符例子:

1
2
3
4
*                   匹配所有主机名, 一般仅在/etc/ssh/ssh_config中存在
*.example.com 匹配以example.com结尾的域名
!*.a.com,*.b.com 排除
192.168.0.? 匹配192.168.0网段的所有 IP

Format

每一个配置项的格式如下:

1
2
3
4
5
Host example                       # 关键词, 注意, example仅仅作为一个唯一的关键字
HostName example.com # 主机地址
User root # 用户名
IdentityFile ~/.ssh/id_ecdsa # 认证文件
Port 22 # 指定端口

其中关键词在方便调用方面非常重要, 例如你已经配置好一个重要的关键词, 那么仅仅需要输入如下命令
即可进行连接: ssh example, 多么的方便快捷

Disable Password

编辑/etc/ssh/ssh_config, 禁止密码登录

1
2
3
4
5
# 禁止密码登录
PasswordAuthentication no
# 禁止root登录
PermitRootLogin without-password
PermitRootLogin yes

对于链接断开, 可以尝试开启心跳机制, 根源问题是网络问题, 编辑~/.ssh/config

1
2
3
4
5
# for all hosts
ServerAliveInterval 10
# for a selection of host
Host keepsdroppingme.comalsokeepsdroppingme.com
ServerAliveInterval 10

Example

管理多组密钥对

对于不同的服务器, 配置不同的密钥对, 而不是使用-i参数来指定值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 同一平台下多账号, 会轮询调用
Host user1-github
HostName github.com
User git
IdentityFile ~/.ssh/github_user1

Host user2-github
HostName github.com
User git
IdentityFile ~/.ssh/github_user2

# 多平台
Host coding.net
user bamboo
HostName coding.net
IdentityFile ~/.ssh/coding

# 直接包含(适用于所有域名, 一般放在末尾)
IdentityFile ~/.ssh/unlessbamboo
IdentityFile ~/.ssh/xinshu

代理登录

没法直接登录到某台服务器,而需要使用一台中间服务器进行中转, 此时需要使用代理登录, 以进行交互

1
2
3
4
5
6
7
8
Host gateway
HostName proxy.example.com
User root
Host db
HostName db.internal.example.com # 目标服务器地址
User root # 用户名
# IdentityFile ~/.ssh/id_ecdsa # 认证文件
ProxyCommand ssh gateway netcat -q 600 %h %p # 代理命令

之后, 使用ssh db连接, 此时实际执行 ProxyCommand 命令, 并用到了gateway中的值

参考:

ssh 官网