MySQL SSL 加密連接淺析

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連接也不行。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。