author:sufei

mysql版本:5.7.26


一、SSL 原理

​ SSL(Secure Socket Layer,安全套接字层),是用于保证在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取。常用于客户端与服务器之间,保证通信安全。在理解ssl原理之前,我们需要理解一下,相关概念。

1.1 相关概念

  • 公钥密码体制(public-key cryptography)

    公钥密码体制分为三个部分,公钥、私钥、加密解密算法,它的加密解密过程如下:

加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。加密过程需要用到公钥。

解密:通过解密算法和私钥对密文进行解密,得到明文。解密过程需要用到解密算法和私钥。注意,由公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。

​ 公钥密码体制的公钥和算法都是公开的(这是为什么叫公钥密码体制的原因),私钥是保密的。大家都以使用公钥进行加密,但是只有私钥的持有者才能解密。在实际的使用中,有需要的人会生成一对公钥和私钥,把公钥发布出去给别人使用,自己保留私钥。

  • 对称加密算法(symmetric key algorithms)

​ 在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话,密钥要做好保密,只能让使用的人知道,不能对外公开。这个和上面的公钥密码体制有所不同,公钥密码体制中加密是用公钥,解密使用私钥,而对称加密算法中,加密和解密都是使用同一个密钥,不区分公钥和私钥。

  • 非对称加密算法(asymmetric key algorithms)

​ 在非对称加密算法中,加密使用的密钥和解密使用的密钥是不相同的。前面所说的公钥密码体制就是一种非对称加密算法,他的公钥和是私钥是不能相同的,也就是说加密使用的密钥和解密使用的密钥不同,因此它是一个非对称加密算法。

  • RSA简介

​ RSA是一种公钥密码体制,现在使用得很广泛。如果对RSA本身有兴趣的,后面看我有没有时间写个RSA的具体介绍。

​ RSA密码体制是一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。 由公钥加密的内容可以并且只能由私钥进行解密,并且由私钥加密的内容可以并且只能由公钥进行解密。也就是说,RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密

  • 签名和加密

加密:是指对某个内容加密,加密后的内容还可以通过解密进行还原。 比如我们把一封邮件进行加密,加密后的内容在网络上进行传输,接收者在收到后,通过解密可以还原邮件的真实内容。

签名,签名就是在信息的后面再加上一段内容,可以证明信息没有被修改过,怎么样可以达到这个效果呢?一般是对信息做一个hash计算得到一个hash值,注意,这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。在把信息发送出去时,把这个hash值加密后做为一个签名和信息一起发出去。 接收方在收到信息后,会重新计算信息的hash值,并和信息所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过,因为这里hash计算可以保证不同的内容一定会得到不同的hash值,所以只要内容一被修改,根据信息内容计算的hash值就会变化。

当然,不怀好意的人也可以修改信息内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。至于如何让别人可以解密这个签名,这个过程涉及到数字证书等概念。

  • 数字证书

其实数字证书,类似于带了公章的文件,公章就是权威机构的签名,而文件内容就是证书所有者的公钥信息。类似前面签名的作用,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。一个证书包含下面的具体内容:

  • 证书的发布机构:指出是什么机构发布的这个证书,也就是指明这个证书是哪个权威机构创建的
  • 证书的有效期:证书的使用期限。 过了有效期限,证书就会作废,不能使用了
  • 公钥:前面介绍公钥密码体制时介绍过,公钥是用来对消息进行加密的
  • 证书所有者(Subject):这个证书是发布给谁的,或者说证书的所有者
  • 签名所使用的算法:这个数字证书的数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。指纹的加密结果就是数字签名
  • 指纹以及指纹算法:这个是用来保证证书的完整性的,也就是说确保证书没有被修改过。其原理就是在发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果和刚开始的值对得上,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。 注意,这个指纹会使用证书机构的私钥用签名算法(Signature algorithm)加密后和证书放在一起。

如下就是mysql自动生成的数字证书

[sf@bssmysql028 ssl]$ openssl x509 -noout -text -in client-cert.pem 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 3 (0x3)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=MySQL_Server_5.7.26_Auto_Generated_CA_Certificate  //证书的发布机构
        Validity  //证书的有效期 10年
            Not Before: Jun 11 02:35:10 2019 GMT
            Not After : Jun  8 02:35:10 2029 GMT
        Subject: CN=MySQL_Server_5.7.26_Auto_Generated_Client_Certificate //证书所有者
        Subject Public Key Info: //所有者公钥信息
            Public Key Algorithm: rsaEncryption // 公钥加密算法
                Public-Key: (2048 bit)
                Modulus:  //2048bit 公钥
                    00:db:80:a0:a4:ac:4b:b6:94:8f:05:88:a5:93:b1:
                    db:e2:64:9f:47:57:41:ee:80:d1:cf:40:cf:26:dc:
                    a8:0e:80:77:75:39:77:db:78:57:9c:e3:fe:41:d8:
                    d0:40:02:6d:8f:be:de:14:08:db:87:90:61:cf:97:
                    f0:3c:7f:14:4f:98:4d:b3:75:19:a2:73:d7:34:a3:
                    c6:0b:c6:75:49:7f:f1:6d:e6:c4:00:ef:6a:92:2c:
                    80:82:36:2a:aa:9d:21:62:ab:ae:32:4d:84:fc:8d:
                    01:d9:b3:1e:10:b7:76:c9:9e:50:3f:d8:8a:71:d1:
                    82:d2:03:09:31:e9:b2:e9:fb:c9:ac:ba:ac:ee:d5:
                    cd:8d:4c:a5:51:d3:84:26:69:91:6f:c0:2a:64:1e:
                    eb:4b:02:c8:fc:65:4f:d7:b5:49:17:08:09:60:fd:
                    96:b9:a4:77:2e:a2:85:0f:b6:d1:55:08:6d:18:20:
                    71:19:aa:96:35:ab:30:69:54:75:25:68:44:28:f2:
                    c0:54:a6:de:48:6e:a2:65:87:fd:4b:b5:68:0e:20:
                    9c:06:d1:38:d6:ad:52:f9:a1:59:e9:48:1e:0f:a6:
                    c5:61:57:c4:c2:5b:8a:66:73:70:8f:68:39:f9:77:
                    bc:a7:58:52:f9:d3:eb:8a:fc:66:a3:4c:21:aa:50:
                    90:3f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
    Signature Algorithm: sha256WithRSAEncryption //数字签名以及签名算法
         70:42:36:a9:e1:bb:50:00:1a:f5:5a:d3:23:4c:d1:67:77:7f:
         55:2a:30:0c:c5:b2:bc:c8:35:ca:7e:ae:28:ad:63:3e:8a:45:
         16:ec:be:30:a3:55:59:02:74:23:63:cc:c6:f0:d7:48:5a:4d:
         8a:b2:c4:0f:13:38:81:aa:18:57:e4:58:4a:31:70:9f:78:22:
         94:f8:ab:92:6f:f6:38:13:89:95:e8:d1:a3:d9:01:3b:bf:e9:
         80:d4:69:42:ae:2d:ee:b9:ae:cb:00:53:92:2b:20:e2:82:74:
         36:9a:05:7d:de:69:69:42:69:35:e7:60:fc:19:47:f9:0c:a1:
         92:ca:ea:61:42:9c:1b:f8:ef:1c:e6:fd:37:c4:9c:f4:91:17:
         4e:b3:ed:db:f0:b6:68:e9:68:7d:f4:16:57:20:bf:1a:8e:cd:
         e8:62:c0:1b:b2:48:7e:cc:eb:de:c0:6b:03:fc:90:73:ca:d8:
         04:20:62:f1:e6:47:c4:69:47:04:5d:30:fd:12:61:81:af:d4:
         3d:14:9f:75:10:bb:94:20:b9:a0:60:f0:2e:89:92:f8:f9:7f:
         fd:ef:c6:e9:b9:77:7b:9c:d2:e2:35:ae:91:fc:51:b5:20:a2:
         9d:80:e1:bb:c8:45:a1:9f:3e:80:07:6d:44:65:57:33:f8:e2:
         bb:7c:70:2d

1.2 SSL运行过程

​ SSL/TLS协议的基本思路是采用公钥密码体制,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

但是,这里有两个问题。

(1)如何保证公钥不被篡改?

解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。

(2)公钥加密计算量太大,如何减少耗用的时间?

解决方法:每一次对话(session),客户端和服务器端都生成一个”对话密钥”(session key),用它来加密信息。由于”对话密钥”是对称加密,所以运算速度非常快,而服务器公钥只用于加密”对话密钥”本身,这样就减少了加密运算的消耗时间。

因此,SSL/TLS协议的基本过程是这样的:

(1) 客户端向服务器端索要服务器数字证书(含服务器公钥)。

(2) 采用公钥加密,双方协商生成”对话密钥”。

(3) 双方采用”对话密钥”进行加密通信。

上面过程的前两步,又称为”握手阶段”(handshake)。具体过程如下:

ssl示意图.png

​ 前面我们一起详细地了解了整个 SSL/TLS 的握手过程,这里解决几个问题。

为什么要使用三个随机数来生成对称密钥呢?

这是因为 SSL/TLS 握手过程的数据都是明文传输的,并且多个随机数种子来生成秘钥不容易被暴力破解出来。

SSL双方确认Cipher加密套件组,并不是单独一个加密方法,而是一组。包含对称加密算法,密钥交换算法,以及摘要算法。

这里是说的加密组合套件,比如A与B通信,A是SSL客户端,B是SSL服务器端,A在Client Hello阶段给出的Ciphers为:我这里的对称加密算法有DES,RC5,密钥交换算法有RSA和DH,摘要算法有MD5和SHA。然后B在Server Hello阶段回复:我们用DES-RSA-SHA这对组合好了,也就是最终确认的Cipher为DES-RSA-SHA这一组加密算法。

二、MySQL SSL连接的证书认证处理

​ 我们知道,在上述SSL握手阶段的第⑥步或者第⑩步时,需要对服务端/客户端的证书进行认证确认。虽然证书中明文有服务器的公钥,就算不认证,后续过程也能进行,但是不确保证书的可信度,证书上的公钥的可信度也存在质疑。所以为了确保证书可信,需要CA证书来验证服务器证书,实际上就是使用CA证书上CA公钥,解密服务器证书的签名是否生成的服务器证书指纹一致。那对于这部分的服务器证书认证处理,https与MySQL是不同的。

  • https

在https应用中,客户端Web浏览器事先安装被信任的权威CA的根证书(未签名证书或者自签名证书)。并且客户端如果收到了未认可的CA,可以让用户自己选择是否信任,以及下载该CA的证书。

  • MySQL

在MySQL中,默认情况下是不进行服务器证书认证的,只有当客户端指定了ca或者ca-path,才会进行服务器证书认证。

那这个不同主要是由函数SSL_CTX_set_verify来控制,该函数就是控制ssl连接过程中证书认证行为。说明如下:

// 函数原型,该函数这要设置证书认证行为
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
                   int (*verify_callback)(int preverify_ok, X509_STORE_CTX *x509_ctx ));
// 参数说明
/*
ctx  : 
    SSL会话环境结构体,通过设置CTX的属性,可以指定握手阶段的认证方式和行为
mode :取值为一下几种
    SSL_VERIFY_NONE 
        server:握手阶段不发送Client Certificate Request,所以客户端不会发送自己的证书
        client:握手阶段不管客户端veritificate阶段,结果如何,都不中断,继续进行
    SSL_VERIFY_PEER
        server:发送Client Certificate Request,并且服务端只要收到了客户端的证书(也可能客户端不发               送自己的证书)就进行校验,验证失败则中断会话,通常与SSL_VERIFY_FAIL_IF_NO_PEER_CERT               和SSL_VERIFY_CLIENT_ONCE配合使用
        client:服务器证书需要被验证,如果认证失败,立即中断
    SSL_VERIFY_FAIL_IF_NO_PEER_CERT
        server:和SSL_VERIFY_PEER参数一起,如果客户端不放回客户端证书,则中断;强制要求检查客户端
        client:ignored
    SSL_VERIFY_CLIENT_ONCE
        server:和SSL_VERIFY_PEER参数一起,对客户端证书认证仅仅在初始化ssl握手阶段,重连时不需要。
        client:ignored
verify_callback:
    控制当mode设置为SSL_VERIFY_PEER的认证行为。其中参数preverify_ok,表示认证成功(1)或失败(0),x509_ctx指针是认证链,可以通过应用程序可以通过设置该参数来具体操作认证行为,返回值表示是否通过认证,1为通过,0为未通过。NULL表明默认行为直接将preverify_ok返回。
*/

下面具体看一下MySQL中ssl连接默认的认证属性设置

// 客户端代码
struct st_VioSSLFd *
new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
                      const char *ca_file, const char *ca_path,
                      const char *cipher, enum enum_ssl_init_error* error,
                      const char *crl_file, const char *crl_path, const long ssl_ctx_flags)
{
  struct st_VioSSLFd *ssl_fd;
  int verify= SSL_VERIFY_PEER; //默认检测服务端证书

  /*
    如果没有设置ca_file或者ca_path,则改为SSL_VERIFY_NONE模式,即不对服务端证书进行检测
  */
  if (ca_file == 0 && ca_path == 0)
    verify= SSL_VERIFY_NONE;

  if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
                             ca_path, cipher, TRUE, error,
                             crl_file, crl_path, ssl_ctx_flags)))
  {
    return 0;
  }
  //设置客户端认证属性
  SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL);
  return ssl_fd;
}

// 服务端代码
struct st_VioSSLFd *
new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
             const char *ca_file, const char *ca_path,
             const char *cipher, enum enum_ssl_init_error* error,
                     const char *crl_file, const char * crl_path, const long ssl_ctx_flags)
{
  struct st_VioSSLFd *ssl_fd;
  //初始化模式为SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,即发生客户端证书请求,但不关心是否返回,
  //并且只在初始化连接是要求,重连无要求  
  int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
  if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
                             ca_path, cipher, FALSE, error,
                             crl_file, crl_path, ssl_ctx_flags)))
  {
    return 0;
  }
  SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128);
  //设置服务端认证属性
  SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL);

  /*
    Set session_id - an identifier for this server session
    Use the ssl_fd pointer
   */
  SSL_CTX_set_session_id_context(ssl_fd->ssl_context,
                 (const unsigned char *)ssl_fd,
                 sizeof(ssl_fd));

  return ssl_fd;
}

​ 从上面的设置可以看到,默认的情况下:

MySQL客户端行为

1、是否设置ca_file参数或者ca_path参数:

没有设置这两个参数,ssl连接是不认证服务器证书的,直接提取公钥,继续进行握手阶段。当设置了相关参数,则会才有参数指定的CA证书对服务器证书进行认证。

2、是否设置ssl-cert和ssl-key

如果设置了,客户端才会相应服务器请求证书,返回客户端证书。

MySQL服务端行为

总是会发送客户端证书请求,至于客户端是否放回自己的证书给服务端验证,由客户端参数决定;

而服务器端是否一定要求客户端返回客户端证书有连接的用户属性决定。在连接权限检测的时候来进行检测,会调用acl_check_ssl函数,代码如下:

static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
{
#if defined(HAVE_OPENSSL)
  Vio *vio= thd->get_protocol_classic()->get_vio();
  SSL *ssl= thd->get_protocol()->get_ssl();
  X509 *cert;
#endif /* HAVE_OPENSSL */

  /*
    At this point we know that user is allowed to connect
    from given host by given username/password pair. Now
    we check if SSL is required, if user is using SSL and
    if X509 certificate attributes are OK
  */
  switch (acl_user->ssl_type) { //检测用户ssl类型
  case SSL_TYPE_NOT_SPECIFIED:                  // Impossible
  case SSL_TYPE_NONE:                           // 用户没有必须要求ssl,SSL is not required
    return 0;
#if defined(HAVE_OPENSSL)
  case SSL_TYPE_ANY:                            // Any kind of SSL is ok
    return vio_type(vio) != VIO_TYPE_SSL;
  case SSL_TYPE_X509: /* x509用户必须要求有合法证书Client should have any valid certificate. */
    /*
      Connections with non-valid certificates are dropped already
      in sslaccept() anyway, so we do not check validity here.

      We need to check for absence of SSL because without SSL
      we should reject connection.
    */
    if (vio_type(vio) == VIO_TYPE_SSL && //必须是ssl连接
        SSL_get_verify_result(ssl) == X509_V_OK && 
        (cert= SSL_get_peer_certificate(ssl))) //检测客户端证书是否获得,没有获得建禁止访问
    {
      X509_free(cert);
      return 0;
    }
    return 1;
  case SSL_TYPE_SPECIFIED: /* 客户端指定了特殊的属性Client should have specified attrib */
    /* If a cipher name is specified, we compare it to actual cipher in use. */
    if (vio_type(vio) != VIO_TYPE_SSL ||
        SSL_get_verify_result(ssl) != X509_V_OK)
      return 1;
    if (acl_user->ssl_cipher)
    {
      DBUG_PRINT("info", ("comparing ciphers: '%s' and '%s'",
                         acl_user->ssl_cipher, SSL_get_cipher(ssl)));
      if (strcmp(acl_user->ssl_cipher, SSL_get_cipher(ssl)))
      {
        sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
                              acl_user->ssl_cipher, SSL_get_cipher(ssl));
        return 1;
      }
    }
    /* Prepare certificate (if exists) */
    if (!(cert= SSL_get_peer_certificate(ssl)))
      return 1;
    /* If X509 issuer is specified, we check it... */
    if (acl_user->x509_issuer)
    {
      char *ptr= X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
      DBUG_PRINT("info", ("comparing issuers: '%s' and '%s'",
                         acl_user->x509_issuer, ptr));
      if (strcmp(acl_user->x509_issuer, ptr))
      {
        sql_print_information("X509 issuer mismatch: should be '%s' "
                              "but is '%s'", acl_user->x509_issuer, ptr);
        OPENSSL_free(ptr);
        X509_free(cert);
        return 1;
      }
      OPENSSL_free(ptr);
    }
    /* X509 subject is specified, we check it .. */
    if (acl_user->x509_subject)
    {
      char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
      DBUG_PRINT("info", ("comparing subjects: '%s' and '%s'",
                         acl_user->x509_subject, ptr));
      if (strcmp(acl_user->x509_subject, ptr))
      {
        sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
                          acl_user->x509_subject, ptr);
        OPENSSL_free(ptr);
        X509_free(cert);
        return 1;
      }
      OPENSSL_free(ptr);
    }
    X509_free(cert);
    return 0;
#else  /* HAVE_OPENSSL */
  default:
    /*
      If we don't have SSL but SSL is required for this user the 
      authentication should fail.
    */
    return 1;
#endif /* HAVE_OPENSSL */
  }
  return 1;
}

三、MySQL中有关SSL参数说明

3.1 客户端参数

  • ssl-mode

    ​ 控制客户端ssl连接服务器方式

选项值 说明
PREFFERED(默认) 首先尝试ssl加密连接,失败了使用非加密连接
REQUIRED 客户端要求一个加密连接,失败了则中断
DISABLED 客户端不使用加密连接
VERIFY_CA or VERIFY_IDENTITY 客户端要求一个加密连接,并且要求验证服务器证书,
如果是VERIFY_IDENTITY,则还要求对证书中主机名进行验证

下面是ssl连接的参数:

选项 作用
ssl-ca 该参数指定CA证书文件,与ssl-capath参数作用一致,
主要不同在于ssl-ca是文件,ssl-capath参数是目录
注意:如果配置了该选项,必须是服务器端相同的CA证书
ssl-capath 参考ssl-ca说明
ssl-sert 指定客户端数字证书
ssl-key 指定客户端私钥
ssl-cipher 指定允许的连接加密套件
ssl-crl 指定吊销证书列表的文件

3.2 服务端参数

  • ssl选项

开启该选项表明,服务器支持ssl连接(当然本身数据库编译版本编译时需包含ssl连接方式)。但不强制要求用户使用ssl连接。默认是开启的

  • require_secure_transport

系统变量,要求所有用户都使用安全连接,安全连接类型包括ssl,共享内存,socket。具体代码如下:

// 设置了require_secure_transport,则在acl_authenticate权限认证中进行检测
if (opt_require_secure_transport && //如果开启变量
        !is_secure_transport(thd->active_vio->type))  //并且连接类型不是安全类型,则返回错误
{
   my_error(ER_SECURE_TRANSPORT_REQUIRED, MYF(0));
   DBUG_RETURN(1);
}
//is_secure_transport函数如下
bool is_secure_transport(int vio_type)
{
  switch (vio_type)
  {
    case VIO_TYPE_SSL:
    case VIO_TYPE_SHARED_MEMORY:
    case VIO_TYPE_SOCKET:
      return TRUE;
  }
  return FALSE;
}

下面是ssl连接的参数:

选项 作用
ssl-ca 该参数指定CA证书文件,与ssl-capath参数作用一致,
主要不同在于ssl-ca是文件,ssl-capath参数是目录
ssl-capath 参考ssl-ca说明
ssl-sert 指定服务器数字证书,用来发送给客户端,客户端用自己持有的CA证书去认证该数字证书
ssl-key 指定服务器私钥
ssl-cipher 指定允许的连接加密套件
ssl-crl 指定吊销证书列表的文件

​ 如果MySQL启动时,只开启了ssl选项(默认就是开启的,所以不配置就是开启),其他ssl-xxx都没有配置。服务器在启动时会自动搜索相关文件。

  1. 服务器在数据目录下搜索ca.pem,server-cert.pem,server-key.pem文件,就会启动对加密连接的支撑
  2. 如果在数据目录下没有找到相关文件,服务器依然启动,但是不支持加密连接。

四、实验

​ 首先我们需要确认服务器是否支持ssl连接,可以通过查看相关变量,如果以下变量为yes,则说明服务器支持加密连接。

mysql> show variables like 'have%ssl%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl  | YES   |
| have_ssl      | YES   |
+---------------+-------+
2 rows in set (0.00 sec)

​ 如果服务器没有开启,我们需要指定相关ssl-xxx选项,或者直接在数据目录生成相应的加密文件,重启数据库即可。下面针对创建不同用户来检验ssl连接方式。

4.1 一般用户连接

# 创建一般用户
mysql> create user 'general_user'@'%' identified by '123';      
Query OK, 0 rows affected (0.00 sec)

# 实验环境
mysql> show variables like "require_secure_transport";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| require_secure_transport | OFF   |
+--------------------------+-------+
1 row in set (0.00 sec)

## 1、一般用户ssl连接登入,在不指定ssl-mode的情况下,首先尝试ssl连接
[sf@bssmysql028 ~]/data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ugeneral_user -p'123' 
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 15
Server version: 5.7.26-log Source distribution

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

mysql> s
--------------
/data2/sf/5.7install/bin/mysql  Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using  EditLine wrapper

Connection id:          15
Current database:
Current user:           general_user@10.142.90.96
SSL:                    Cipher in use is DHE-RSA-AES256-SHA
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.26-log Source distribution
Protocol version:       10
Connection:             10.142.90.96 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3389
Uptime:                 10 days 23 hours 55 min 29 sec

Threads: 4  Questions: 57  Slow queries: 0  Opens: 127  Flush tables: 1  Open tables: 24  Queries per second avg: 0.000
--------------

## 2、一般用户非ssl连接
[sf@bssmysql028 ~] /data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ugeneral_user -p'123' --ssl-mode=DISABLE
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 16
Server version: 5.7.26-log Source distribution

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

mysql> s
--------------
/data2/sf/5.7install/bin/mysql  Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using  EditLine wrapper

Connection id:          16
Current database:
Current user:           general_user@10.142.90.96
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.26-log Source distribution
Protocol version:       10
Connection:             10.142.90.96 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3389
Uptime:                 10 days 23 hours 57 min 23 sec

Threads: 4  Questions: 62  Slow queries: 0  Opens: 127  Flush tables: 1  Open tables: 24  Queries per second avg: 0.000
--------------

# 服务器开启require_secure_transport
mysql> set global require_secure_transport=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "require_secure_transport";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| require_secure_transport | ON    |
+--------------------------+-------+
1 row in set (0.00 sec)

#  3、一般用户非ssl连接
[sf@bssmysql028 ~]/data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ugeneral_user -p'123' --ssl-mode=DISABLE
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.

# 4、本地socket连接
[sf@bssmysql028 ~] /data2/sf/5.7install/bin/mysql --socket=/tmp/mysql_3389.sock -ugeneral_user -p'123' 
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 26
Server version: 5.7.26-log Source distribution

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

mysql> s
--------------
/data2/sf/5.7install/bin/mysql  Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using  EditLine wrapper

Connection id:          26
Current database:
Current user:           general_user@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.26-log Source distribution
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:            /tmp/mysql_3389.sock
Uptime:                 11 days 40 min 47 sec

Threads: 4  Questions: 94  Slow queries: 0  Opens: 127  Flush tables: 1  Open tables: 24  Queries per second avg: 0.000
--------------

结论

​ 对于一般用户,如果服务端没有开启require_secure_transport变量,服务器对连接没有强制安全连接时,一般用户ssl连接和非ssl连接都可以,只有服务器开启了require_secure_transport变量时,一般用户也会强制要求使用安全连接(ssl和本地socket连接都是安全连接)。

4.2 SSL用户连接

# 创建指定ssl连接用户
mysql> create user 'ssl_user'@'%' identified by '123' require SSL;     
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like "require_secure_transport";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| require_secure_transport | OFF   |
+--------------------------+-------+
1 row in set (0.00 sec)

# 1、ssl用户非ssl连接
[sf@bssmysql028 ~]/data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ussl_user -p'123' --ssl-mode=DISABLE       
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'ssl_user'@'10.142.90.96' (using password: YES)

# 2、ssl用户ssl连接
[sf@bssmysql028 ~] /data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ussl_user -p'123' 
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 20
Server version: 5.7.26-log Source distribution

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

mysql> s
--------------
/data2/sf/5.7install/bin/mysql  Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using  EditLine wrapper

Connection id:          20
Current database:
Current user:           ssl_user@10.142.90.96
SSL:                    Cipher in use is DHE-RSA-AES256-SHA
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.26-log Source distribution
Protocol version:       10
Connection:             10.142.90.96 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3389
Uptime:                 11 days 31 min 2 sec

Threads: 4  Questions: 77  Slow queries: 0  Opens: 127  Flush tables: 1  Open tables: 24  Queries per second avg: 0.000
--------------

# 3、本地socket连接
[sf@bssmysql028 ~]$ /data2/sf/5.7install/bin/mysql --socket=/tmp/mysql_3389.sock -ussl_user -p'123'                      
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'ssl_user'@'localhost' (using password: YES)

结论:

​ 对于指定ssl连接的用户,不管服务端是否开启require_secure_transport变量,都需要使用ssl连接,就算是socket连接也不行。

4.3 X509用户连接

# 创建指定x509用户
mysql> create user 'x509_user'@'%' identified by '123' require X509;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "require_secure_transport";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| require_secure_transport | OFF   |
+--------------------------+-------+
1 row in set (0.00 sec)

# 1、x509用户非ssl连接
[sf@bssmysql028 ~]/data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ux509_user -p'123' --ssl-mode=DISABLE   
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'x509_user'@'10.142.90.96' (using password: YES)

# 2、x509用户ssl连接,不指定客户端sert
[sf@bssmysql028 ~] /data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ux509_user -p'123' 
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'x509_user'@'10.142.90.96' (using password: YES)

# 3、x509用户ssl连接,指定客户端证书和私钥
[sf@bssmysql028 ~]/data2/sf/5.7install/bin/mysql -h10.142.90.96 -P3389 -ux509_user -p'123' --ssl-cert=/data2/sf/5.7data/client-cert.pem --ssl-key=/data2/sf/5.7data/client-key.pem
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 23
Server version: 5.7.26-log Source distribution

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.

mysql> s
--------------
/data2/sf/5.7install/bin/mysql  Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using  EditLine wrapper

Connection id:          23
Current database:
Current user:           x509_user@10.142.90.96
SSL:                    Cipher in use is DHE-RSA-AES256-SHA
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.26-log Source distribution
Protocol version:       10
Connection:             10.142.90.96 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3389
Uptime:                 11 days 37 min 28 sec

Threads: 4  Questions: 84  Slow queries: 0  Opens: 127  Flush tables: 1  Open tables: 24  Queries per second avg: 0.000
--------------

# 4、x509本地socket连接
[sf@bssmysql028 ~] /data2/sf/5.7install/bin/mysql --socket=/tmp/mysql_3389.sock -ux509_user -p'123'        
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'x509_user'@'localhost' (using password: YES)

结论:

​ 指定X509用户,必须为ssl连接,并且其必须给出客户端证书和私钥,以便服务器与客户端相互认证。并且socket连接也不行。

文章来源于互联网:MySQL SSL 加密连接浅析

发表评论