构筑安全堡垒:详解OpenSSL与OpenSSH在等保三级升级中的关键作用
OpenSSL
OpenSSl是一个强大的安全套接字层密码库,Apache使用它加密HTTPS,OpenSSH使用它加密SSH,但是不能只将它作为一个库来使用,它是一个多用途。跨平台的密码工具。
基本功能
OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库,SSL协议库以及应用程序。
OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。
- OpenSSL:多用途的命令工具,每种功能都使用专用的子命令来实现
- libcrypto:加密,解密库文件
- libssl:加密模块应用库,实现了ssl及tls
密码算法库
对称加密算法
我们一般的加密使用一个密码加密文件,然后解密也用同样的密码,这个对是称加密。OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5,都支持电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种常用的分组密码加密模式。其中AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。事实上,DES算法里面不仅仅是常用的DES算法,还支持三个秘钥和两个秘钥DES算法。
非对称加密算法
有些加密用的一个密码,而解密用另外一组密码,这个叫非对称加密。OpenSSL一共实现了4中非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)。DH算法一般用户秘钥交换。RSA算法既可以用于秘钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的速度,那么也可以用于数据加密。DSA算法则一般只用于数字签名。
信息摘要算法
OpenSSL实现了5种信息摘要算法,分别是MD2、MD5、MDC2、SHA(SHA1)和RIPEMD。SHA算法事实上包括了SHA和SHA1两种信息摘要算法,此外,OpenSSL还实现了DSS标准中规定的两种信息摘要算法DSS和DSS1。
秘钥和证书管理
秘钥和证书管理是PKI的一个重要组成部分,OpenSSL为之提供了丰富的功能,支持多种标准。
首先,OpenSSL实现了ASN.1的证书和秘钥相关标准,提供了对证书、公钥、私钥、证书请求以及CRL等数据对象的DER、PEM和BASE64的编解码功能。OpenSSL提供了产生各种公开秘钥和对称秘钥的方法、函数和应用程序,同时提供了对公钥和私钥的DER编解码功能。并实现了私钥的PKCS#12和PKCS#8的编解码功能。OpenSSL在标准中提供了对私钥的加密保护功能,使得秘钥可以安全地进行存储和分发。
在此基础上,OpenSSL实现了对证书的X.509标准编解码、PKCS#12格式的编解码以及PKCS#7的编解码功能。并提供了一种文本数据库,支持证书的管理功能,包括秘钥产生、请求产生、证书签发、吊销和验证等功能。
事实上,OpenSSL提供的CA应用程序就是一个小型的证书管理中心(CA),实现了证书签发的整个流程和证书管理的大部分机制。
OpenSSL命令
查看程序版本号
openssl version
标准命令
enc crl ca dh req ……
对称加密
工具:openssl enc,gpg
算法:3des,aes,blowfish
enc命令
openssl enc -e -des3 -a -salt -in ipset.sh -out ipset
-enc:表示加密
-e:加密算法
-des3:des3加密算法
-a:基于ase64文本进行编码
-salt:加盐
-in:加密的文件
-out:输出文件
openssl enc -d -des3 -a -salt -in ipest -out ipset.sh
-d:表示解密
openssl enc -e -des3 -a -salt -in /etc/fstab -out fstab.ciphertext 加密文件 要输入密码
解密
openssl enc -d -des3 -a -salt -in fstab.ciphertext -out fstab
单向加密
获取数据的特征码
工具 MD5sum sha1sum sha224sum sha256sum…… openssl dgst
dgst命令
常用选项:
[-md5|-md4|-md2|-sha1|-sha|-mdc2|-ripemd160|-dss1] : 指定一种加密算法
-out filename:将加密的内容保存到指定文件中
Openssl dgst -md5 -hex fstab 相当于 md5sum fstab 默认16进制编码
单向加密除了openssl dgst 工具还有:md5sum,sha1sum,sha224sum,sha256sum,sha384sum,sha512sum
MAC:Message Autentication Code单向加密的一种延伸应用,用于实现网络通信中保证所传输的数据的完整性机制
CBC-MAC
HMAC:使用md5或sha1算法
生成用户密码
openssl passwd,用法如下:
openssl passwd [-crypt] [-1] [-apr1] [-salt string] [-in file] [-stdin] [-noverify] [-quiet] [-table] {password}
常用选项:
-1:使用md5加密算法
-salt string:加入随机数,最多8位随机数
-in file:对输入的文件内容进行加密
-stdin:对标准输入的内容进行加密
生成随机数(适合充当salt)
生成随机数需要用到标准命令rand,用法如下
openssl rand [-out file] [-rand file(s)] [-base64] [-hex] num
常用选项:
-out file:将生成的随机数保存至指定文件中
-base64:使用base64编码格式
-hex:使用16进制编码格式
公钥加密
加密算法:RSA ELGmal
工具:gpg,openssl rsautl man rsautl
数字签名:发送方用自己的私钥加密,接收方用发送方的公钥解密。
数字签名会加密语言数据的特征码,而不会加密语言数据本身。
算法:RSA,EIGamal,DSA(只能用来做签名,而无法用来加密)
DSA:digital signature algorithm
DSS:digital signature standard(只能私钥加密,公钥解密)
密钥交换
算法:dh
数字证书:公钥加密的另一个应用
证书格式:x509
生成密钥对
genrsa命令
openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [-f4] [-3] [-rand file(s)] [-engine id] [numbits]
常用选项:
-out filename:将生成的私钥保存至指定的文件中
-des|-des3|-idea:不同的加密算法
numbits:指定生成私钥的大小,默认2048
一般情况下密钥文件的权限一定要控制好,只能自己读写,因此可以使用umask命令设置生成的私钥权限
生成私钥
openssl genrsa -out /PATH/TO/PRIVATEKEY.FILE NUM_BITS
ras命令
openssl rsa [-inform PEM|NET|DER] [-outform PEM|NET|DER] [-in filename] [-passin arg] [-out filename] [-passout arg][-sgckey] [-des] [-des3] [-idea] [-text] [-noout] [-modulus] [-check] [-pubin] [-pubout] [-engine id]
常用选项:
-in filename:指明私钥文件
-out filename:指明将提取出的公钥保存至指定文件中
-pubout:根据私钥提取出公钥
生成公钥
私钥权限控制
# 加括号在子shell中运行,umask只在这一次有用 对私钥加密 3des (umask 077; openssl genrsa -out key.pri 2048)
随机数生成器
熵池:在操作系统上有一个叫做熵池的地方,它是用来保存硬件终端产生的随机数(每一次硬件终端都会产生一个随机数)
/dev/random:仅从熵池中返回随机数,随机数耗尽时,取随机数的进程将会被阻塞
/dev/unrandom:仅从熵池中取随机数,随机数耗尽时,就通过伪随机数生成器生成伪随机数(伪随机数不安全)
熵池中随机数的来源:硬盘IO中断时间间隔
建立私有AC
数字证书的获取:
- 向RA注册申请,即公共信任的CA
- 自己创建私有CA,内部网络使用
CA 相关文件列表
- openssl的配置文件:/etc/pki/tls/openssl.cnf
- CA的工作目录:/etc/pki/CA
- 吊销列表的存放位置:/etc/pki/CA/crl
- 刚签署的证书的存放位置:/etc/pki/CA/newcerts
- CA自身的公钥的位置:/etc/pki/CA/cacert.pem
- 发出的证书的编号位置:/etc/pki/CA/serial
- 为吊销的证书编号的位置:/etc/pki/CA/crlnumber
- CA自己的私钥位置:/etc/pki/CA/private/cakey.pem
- 随机数文件:/etc/pki/CA/private/.rand
测试在centos上创建CA
实验环境:两台centos7机器,一台作为CA主机10.0.0.54,一台作为用户主机10.0.0.53(证书请求主机,web服务)
构建私有CA CA主机10.0.0.54,在确定为CA的服务器上生成一个自签证书,并为CA提供所需要的目录及文件
# 1.生成私钥,CA自签名证书,需要一个私钥,在openssl.cnf中,默认私钥文件存放路径为 /etc/pki/CA/private/cakey.pem openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096 chmod 077 /etc/pki/CA/private/cakey.pem # 2.生成自签证书 openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 365 -new:生成新证书签署请求 -x509:生成自签格式证书,专用于创建私有CA -key:生成请求时用到的私钥文件路径 -out:生成的请求文件路径;如果自签操作将直接生成签署过的证书 -days:证书的有效时长,单位为天 # 生成有效期长一些的证书 openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650 # 示例 [root@OpenSSH01 CA]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650 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) []:LiaoNing Locality Name (eg, city) [Default City]:DL Organization Name (eg, company) [Default Company Ltd]:chensir.ink Organizational Unit Name (eg, section) []:technology Common Name (eg, your name or your server's hostname) []:chensir Email Address []:xchensir@qq.com # 3.为CA提供所需的目录及文件 mkdir -pv /etc/pki/CA/{certs,crl,newcerts} # 创建 index.txt文件 (数据库文件) touch index.txt # 指明证书的开始编号 echo 01 >serial
向CA请求签署证书 CA用户主机10.0.0.53提供web服务需要用到证书进行安全通信的服务器,需要向CA请求签署证书
# 以httpd为例 # 在需要使用证书的主机上生成私钥,私钥位置随意 mkdir -p /etc/httpd/ssl openssl genrsa -out /etc/httpd/ssl/httpd.key 2048 chmod 077 /etc/httpd/ssl/httpd.key # 生成证书签署请求 openssl req -new -key /etc/httpd/ssl/httpd.key -out /etc/httpd/ssl/httpd.csr -days 365 # 将生成的httpd.csr请求文件通过可靠的方式发给CA主机 scp /etc/httpd/ssl/httpd.csr root@10.0.0.54:/tmp/
在CA主机上签署证书
# 在CA主机上查看请求主机发送的证书请求 cat /tmp/httpd.csr # 签署证书 openssl ca -in /tmp/httpd.csr -out /etc/pki/CA/certs/httpd.crt -days 365 # 查看证书信息 openssl x509 -in /etc/pki/CA/certs/httpd.crt -noout -serial -subject # 将签署完的证书发回请求主机 scp /etc/pki/CA/certs/httpd.crt root@10.0.0.53:/etc/httpd/ssl
吊销证书
# 客户端获取要吊销证书的Serial(在使用证书的主机执行) openssl x509 -in /etc/pki/CA/certs/httpd.crt -noout -serial -subject # CA主机吊销证书 先根据客户提交Serial和subject信息,对比其与本机数据库index.txt中存储的是否一致 # 吊销 其中的SERIAL要换成证书真正的序列号 openssl ca -revoke /etc/pki/CA/newcerts/SERIAL.PEM # 生成吊销证书的吊销编号(第一次吊销证书时执行) echo 01>/etc/pki/CA/crlnumber # 更新吊销证书列表 openssl ca -gencrl -out thisca.crl # 查看crl文件 openssl crl -in /path/from/crl_file.crl -noout -text
OpenSSH
OpenSSH和OpenSSL的关系
OpenSSH和OpenSSL并不是直系亲属,顶多算有共同志向的兄弟。
他们是由不同的团队开发,有不同目的,但都是开放源码,为安全通信提供支持。
- SSl是通讯链路的附加层,可以包含很多协议 https,ftps……
- SSH只是加密的shell,最初是用来替代telnet的,通过port forward,也可以让其他协议通过ssh的隧道 起到加密的效果
- OpenSSL:一个C语言函数库,是对SSL协议的实现
- OpenSSH:是对SSH协议的实现
- SSH利用OpenSSL提供的库。OpenSSH依赖于OpenSSL,没有OpenSSL的话OpenSSH就编译不过去,也运行不了
OpenSSH发展
ssh:secure shell,Protocol 22/tcp 安全的远程登录功能
openssh:ssh协议的开源实现
代替不安全的Telent telnet使用超级守恒进程xinet
SSH协议版本
V1 基于CRC-32做MAC(消息身份认证),不安全;man-in-middle
V2 双方主机协议选择安全的MAC方式
基于DH算法做密钥交换,基于RSA或DSA算法实现身份认证,两种方式的用户登录认证:
- 基于password认证
- 基于key
OpenSSH架构
C/S架构
C:ssh,scp,sftp
客户端组件
ssh,配置文件:/etc/ssh/ssh_config
StrictHostKeyChecking no 首次登录不显示检查提示
ssh [user@] host [COMMAND] -p 监听端口 cmd 远程执行命令 -X [user@]host 支持x11的图形转发 -Y 支持信任的x11转发 # 存放已授权基于key登录的主机的公钥 ~/.ssh/authorized_keys # 存放本机SSH连接过的主机的公钥 ~/.ssh/know_hosts
两种方式的用户登录认证
基于password
只要知道自己账号和口令就可以登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器,也就是“中间人”这种方式的攻击。
大致流程:
- 客户端发起ssh请求,服务器会把自己的公钥发送给用户
- 用户会根据服务器发来的公钥对密码进行加密
- 加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则用户登录成功
基于key
需要依靠秘钥,也就是你必须为自己创建一对密钥,并把公钥放在需要访问的服务器上。如果要连接到SSH服务器,客户端软件就会向服务器发出请求,请求你的密钥进行安全验证。服务器收到请求后,现在服务器上你的目录下找寻你的公钥,然后把它和你发送过来的公钥进行比较。如果两个密钥一致,服务器就用公钥加密质询(challenge)并把它发送给客户端软件。客户端软件收到质询之后就用你的私钥解密再把它发送给服务器。
大致流程:
- 在客户端生成一对密钥
- 并将客户端的公钥ssh-copy-id拷贝到服务器端对应用户的家目录下
- 当客户端再次发送一个连接请求,包括ip、用户名
- 服务端得到客户端的请求后,会到authorized_keys中查找,如果有相应的IP和用户,服务器就会发出质询,表现为一串随机字符,如:asfh
- 服务端将使用客户端拷贝过来的公钥对质询加密,然后发送给客户端
- 得到服务端发来质询后,客户端会使用私钥进行解密,然后将解密的字符串发送给服务端
- 服务端接收到客户端发来的字符串后,跟之前的字符串进对比,如果一致,就允许免密码登录
其他可以通过OpenSSH免密的工具
scp
常用选项:
-r:递归复制
-p:保持原文件的属性信息
-q:静默模式
-P:Port 指明远程主机监听端口
sftp
sftp root@10.0.0.53
服务端 sshd 配置文件 /etc/ssh/sshd_config /etc/ssh 密钥位置
# 常用参数: Port 22 # 不要监听在默认端口 AddressFamily any ipv4 or ipv6 ListenAddress ip # 只监听内网地址 SyslogFacility # 日志保存在 /var/log/secure PermitRootLogin yes # 允许管理员登录 MaxAuthTries 6 # 最大尝试次数 MaxSessions 10 # 最大并行会话数 AuthorizedKeyFile .ssh/authorized_key # 服务器端公钥存放位置 PasswordAuthentication yes # 允许口令登录 X11Forward yes Subsystem sftp # 支持sftp远程连接 UseDNS no # 做DNS反向解析 # 限制可登录用户的办法 AllowUsers AllowGroups # 重启sshd服务 SElinux要关掉 # CentOS6: service sshd restart # CentOS7: systemctl restart sshd.service
Centos7升级OpenSSH
制作openssh-8.9p1 rpm包
# 安装编译依赖的组件 yum install -y rpm-build gcc gcc-c++ glibc glibc-devel openssl-devel openssl prce pcre-devel zlib zlib-devel make wget krb5-devel pam-devel libX11-devel xmkmf libXt-devel initscripts libXt-devel imake gtk2-devel lrzsz # 建立编译目录 mkdir -pv /root/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} # 源码包下载到/root/rpmbuild/SOURCES cd /root/rpmbuild/SOURCES wget https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable/openssh-8.9p1.tar.gz # 解压spec编译文件 tar -xf openssh-8.9p1.tar.gz openssh-8.9p1/contrib/redhat/openssh.spec mv openssh-8.9p1 /root/rpmbuild/SPECS # 配置spec编译文件 cd /root/rpmbuild/SPECS/openssh-8.9p1/contrib/redhat sed -i -e "s/%global no_gnome_askpass 0/%global no_gnome_askpass 1/g" openssh.spec sed -i -e "s/%global no_x11_askpass 0/%global no_x11_askpass 1/g" openssh.spec # 解决openssl-devel
升级OpenSSH
安全备份
为防止升级过程中升级失败,配置telnet协议 连接Linux
yum install -y telnet-server xinetd systemctl enable xinetd telnet.socket
默认情况下,centos系统是不允许root用户通过telnet方式远程登录系统的。如果要使用root用户直接登录系统,需要添加以下配置
echo -e ‘pts/0\npts/1\npts/2\npts/3’ >>/etc/securetty
重启telnet服务
systemctl restart xinetd telnet.socket
验证结果
telnet localhost
ssh备份
mkdir /etc/sshconfig_backup cp /etc/ssh/sshd_config /etc/sshconfig_backup/ cp /etc/pam.d/sshd /etc/sshconfig_backup/pam.d_sshd cp -a /root/.ssh /etc/sshconfig_backup
升级
把准备好的rpm包上传到需要升级的服务器上
cd /root/rpmbuild/RPMS/x86_64 rpm -Uvh openssh*.rpm # 恢复之前的配置 cp /etc/sshconfig_backup/sshd_config /etc/ssh/sshd_config cp /etc/sshconfig_backup/pam.d_sshd /etc/pam.d/sshd # 允许root用户登录 sed -i "s/#PermitRootLogin yes/PermitRootLogin yes/g" /etc/ssh/sshd_config # 修改ssh_host*key的权限,因为之前openssh旧版本权限太宽松,新版本要求比较严格 chmod 600 /etc/ssh/* # sshd_config 最后添加一行KexAlgorithms echo "KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1" >> /etc/ssh/sshd_config # 重启ssh systemctl restart sshd
卸载并关闭telnet
yum remove -y telnet-server xinetd