Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tls #50

Open
Genluo opened this issue Sep 6, 2019 · 0 comments
Open

tls #50

Genluo opened this issue Sep 6, 2019 · 0 comments
Labels
Node Node相关

Comments

@Genluo
Copy link
Owner

Genluo commented Sep 6, 2019

TLS部分

tls是对**安全传输层(TLS)安全套接字(SSL)**协议的实现,建立在openSSL基础上

文档部分

1、tls.Server: 继承net.Server,接受使用tls/ssl的加密连接

  • 事件
    • newSession
    • OCSPRequest
    • resumeSession
    • SecureConnection
    • tlsClientError
  • 方法
    • addContext
    • address()
    • close()
    • getTicketKey()
    • listen()
    • setTicketKey()
  • 属性
    • connections

2、tls.TLSSocket

  • 事件
    • OCSRequest
    • secureConnect
  • 方法
    • address()
    • disableRenegotiation()
    • getCipher()
    • getEphemeralKeyInfo()
    • getFinished()
    • getPeerCertificate()
    • getPeerFinished()
    • getProtocol()
    • getSession()
    • getTLSTicket()
    • localAddress
    • localPort
    • remoteAddress
    • remoteFamily
    • remotePort
    • renegotiate()
    • setMaxSendFragment()
  • 属性
    • authorizationError
    • authorized
    • encrypted

3、tls上的方法

  • checkServerIdentity
  • connect
  • createSecureContext
  • createServer
  • getCiphers

理解部分

1、TLS和SSl理解

TLS/SSL是public/private key infrastructure (PKI).大部分情况下,每个服务器和客户端都应该有一个私钥

私钥能有多种生成方式,下面举一个例子。 用OpenSSL的命令行来生成一个2048位的RSA私钥:

openssl genrsa -out ryans-key.pem 2048

通过TLS/SSL,所有的服务器(和一些客户端)必须要一个证书。 证书是相似于私钥的公钥,它由CA或者私钥拥有者数字签名,特别地,私钥拥有者所签名的被称为自签名。 获取证书的第一步是生成一个*证书申请文件(CSR)**用OpenSSL能生成一个私钥的CSR文件:

openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem

CSR文件被生成以后,它既能被CA签名也能被用户自签名。 用OpenSSL生成一个自签名证书的命令如下:

openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem

证书被生成以后,它又能用来生成一个.pfx或者.p12文件:

openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem \
      -certfile ca-cert.pem -out ryans.pfx

命令行参数:

  • in: 被签名的证书
  • inkey: 有关的私钥
  • certfile: 签入文件的证书串,比如: cat ca1-cert.pem ca2-cert.pem > ca-cert.pem

2、客户端重协商

TLS协议允许客户端在TLS会话中进行重协商,用于安全因素的考量. 不幸的是,会话重协商需要消耗大量的服务器端资源,这将导致服务器存在潜在的被DDoS攻击的可能.

为了减轻这个风险,node限制每十分钟只能使用三次重协商,超过这个限制将会在tls.TLSSocket实例中产生一个error事件. 这个限制是可配置的:

  • tls.CLIENT_RENEG_LIMIT (number)指定重协商请求的次数限制,默认为3.
  • tls.CLIENT_RENEG_WINDOW (number) 指定限制次数的生效时间段,默认是600(十分钟).

注意: 不应在未充分理解其含义与影响的情况下修改上述参数.

如果要测试服务端重协商限制,请使用OpenSSL命令行客户端(openssl s_client -connect address:port)连接服务器,并输入 R<CR> (即输入R字符后紧跟回车) 多次,如在默认配置下连接服务器并输入三次R加回车后,服务器断开了连接,则表示限制生效.

3、TLS(安全传输层)和SSL(安全套接层)区别及其和其它协议层的结合

这个过程分的清除TLS是那部分、SSL是那部分,其实TLS是在SSL的基础上发展起来的,当SSL发展到3.0版本后改成TLS。所以我们将两个看为一个,都是进行加密的协议,同时我们后面将将这个协议称之为TLS/SSL,两个是一个协议两种版本的不同名称,所以不纠结两个协议的区别,统一称之为TLS/SSL协议。TLS在整个过程中主要提供下面这几种能力:

  • 加密
  • 身份验证(整数验证)
  • 消息完整性验证

但是我们知道HTTPS是依赖于TCP传输层协议,那么TLS协议在整个协议中处于什么位置,根据TLS的作用我们可以猜下:TLS的上一层是HTTP应用层协议,下面是TCP传输成协议,所以TLS是处在应用层和传输层之间的协议,建立在socket上一层协议,所以SSL被称之为安全套接层:

TLS工作流程就是 :

TLS协议是基于TCP协议之上的,图中第一个蓝色往返是TCP的握手过程,之后两次橙色的往返,我们可以叫做TLS的握手。握手过程如下:

  1. client1TLS版本号+所支持加密套件列表+希望使用的TLS选项
  2. Server1:选择一个客户端的加密套件+自己的公钥+自己的证书+希望使用的TLS选项+加密随机数+(要求客户端证书);
  3. Client2:(自己的证书)+使用服务器公钥和协商的加密套件加密一个对称秘钥(自己生成的一个随机值);
  4. Server2:使用私钥解密出对称秘钥(随机值)后,发送加密的Finish消息,表明完成握手

经过这几次握手成功后,客服端和服务端之间通信的加密算法和所需要的密钥也就确定下来了,之后双方的交互都可以使用对称加密算法加密了。

TLS中,我们需要证书来保证你所访问的服务器是真实的,可信的。 看这张图我们来讨论下证书的验证过程。

  1. 客户端获取到了站点证书,拿到了站点的公钥;
  2. 要验证站点可信后,才能使用其公钥,因此客户端找到其站点证书颁发者的信息;
  3. 站点证书的颁发者验证了服务端站点是可信的,但客户端依然不清楚该颁发者是否可信;
  4. 再往上回溯,找到了认证了中间证书商的源头证书颁发者。由于源头的证书颁发者非常少,我们浏览器之前就认识了,因此可以认为根证书颁发者是可信的;
  5. 一路倒推,证书颁发者可信,那么它所颁发的所有站点也是可信的,最终确定了我们所访问的服务端是可信的;
  6. 客户端使用证书中的公钥,继续完成TLS的握手过程。

那么,客户端是是如何验证某个证书的有效性,或者验证策略是怎样的?

证书颁发者一般提供两种方式来验证证书的有效性: CRLOCSP

CRL

CRL(Certificate Revocation List)证书撤销名单。证书颁发者会提供一份已经失效证书的名单,供浏览器验证证书使用。当然这份名单是巨长无比的,浏览器不可能每次TLS都去下载,所以常用的做法是浏览器会缓存这份名单,定期做后台更新。这样虽然后台更新存在时间间隔,证书失效不实时,但一般也OK。

OCSP

OCSP(Online Certificate StatusProtocol)在线证书状态协议。除了离线文件,证书颁发者也会提供实时的查询接口,查询某个特定证书目前是否有效。实时查询的问题在于浏览器需要等待这个查询结束才能继续TLS握手,延迟会更大。

以上是站点在证书颁发者的角度说明会提供的两种判断方式,实际情况下浏览器究竟会选择哪种方式判断,每个浏览器都会有自己的实现。下面是通过Chrome查看GitHub网站的证书信息:

4、相关证书

我们在使用TLS协议的时候,通常会听到很多证书,这些证书都是在通信中使用,主要分为两种:自签名证书CA证书,一般自签名证书不能进行网络认证,有两种方法可以解决这个问题,一种是浏览器信任此证书,另一种需要将自签名证书的公钥和私钥(生成根证书)加入浏览器的受信任列表。但这样一来就增加了server的私钥泄露风险。

(1)TLS基于CA的身份认证基本原理是

首先验证方需要信任CA提供方自己的证书(CAcert),比如证书在操作系统的受信任证书列表中,或者用户通过“安装根证书”等方式将 CA的公钥和私钥加入受信任列表;然后CA对被验证方的原始证书进行签名(私钥加密),生成最终的证书;验证方得到最终的证书后,利用CAcert中包含的公钥进行解密,得到被验证方的原始证书。

(2)验证手段

根据RSA的加密原理,如果用CA的公钥解密成功,说明该证书的确是用CA的私钥加密的,可以认为被验证方是可信的。

(3)证书存在的问题:

  1. CA错签证书,最近比较经典的就是google被其他CA乱签了证书,这在CA界是很恐怖的一件事。谷歌是怎么发现的呢? 这就要提到chrome采用了不同的CA管理机制叫做CT Log,每个CA在签证书前都要先把证书post到谷歌CA服务器去备份,这个谷歌就能知道自己的域名是不是被乱签了。
  2. 依然有可能发生中间人攻击,比如使用真实CA签发的证书(要求证书链完整,即该软件必须有认证过的CA)替换掉要访问的网站的证书(需要拦截底层请求),模拟浏览器去验证OCSP等

5、使用openssl生成自签名证书

自签名证书主要有两种:

  • 自签名证书 - 类似于上图中根证书
  • 自建CA签名的根证书 - 类似上面整个过程,我们使用openssl进行的就是生成根证书并进行自签名,并用根证书对服务器实体证书进行签名,然后将根证书导入到浏览器中,这样chrome就会信任服务器实体证书

自签名的证书无法被吊销,CA 签名的证书可以被吊销,能不能吊销证书的区别在于如果私钥不小心被恶意获取,如果证书不能被吊销那么黑客很有可能伪装成受信任的客户端与用户进行通信。
如果你的规划需要创建多个客户端证书,那么使用自建 CA 签名证书的方法比较合适,只要给所有的客户端都安装了 CA 根证书,那么以该 CA 根证书签名过的客户端证书都是信任的,不需要重复的安装客户端证书。
请注意由于是自建 CA 证书,在使用这个临时证书的时候,会在客户端浏览器报一个错误,签名证书授权未知或不可(signing certificate authority is unknown and not trusted.),但只要配置正确,继续操作并不会影响正常通信。 自签名证书的 Issuer 和 Subject 是一样的。
下面就分别阐述不同的应用场景下,如何使用 OpenSSL 生成这两种自签名证书。

  • 自签名证书

openssl req -new -x509 -newkey rsa:4096 -keyout client.key -out client.crt

  • 自建CA签名的根证书

    • 创建CA根证书

    // 创建CA根目录

    mkdir -p ~/ssl/demoCA/{certs,newcerts,crl,private}
    cd ~/ssl/demoCA
    Touch index.txt
    echo "01" > serial

    // 修改 openssl.cnf 文件

    sudo cp /etc/ssl/openssl.cnf ~/ssl/openssl.cnf
    vi ~/ssl/openssl.cnf

    // 生成 CA 根证书及密钥

    openssl req -new -x509 -newkey rsa:4096 -keyout cakey.key -out cacert.crt -config openssl.cnf -days 365

    • 签发客户端证书

    生成 4096 bit 的客户端私钥

    openssl genrsa -out client.key 4096

    用该客户端私钥生成证书签名请求,扩展名.csr

    openssl req -new -key client.key -out client.csr -config openssl.cnf

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

    openssl ca -in client.csr -out client.crt -cert cacert.crt -keyfile cakey.key -config openssl.cnf

    把客户端证书和私钥保存为.pem 格式

    cat client.crt client.key > client.pem

    如需导出到 windows 供 P2S VPN 客户端使用, 需把客户端证书转换成.pfx 格式

    openssl pkcs12 -export -inkey client.key -in client.pem -out client.pfx

(5) CA中心的几种形式

文章推荐

@Genluo Genluo added the Node Node相关 label Sep 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Node Node相关
Projects
None yet
Development

No branches or pull requests

1 participant