CentOS – HTTPS (HTTP + SSL + CA)

Loading

WordPress 的需求建議 https://wordpress.org/about/requirements/ 裡面有提到要使用 https ,所謂的 https 就是 http with SSL (Secure Sockets Layer) 或是 TLS (Transport Layer Security) 還要加上 CA (Certification Authority) .

先來了解一下什麼是 SSL ?
SSL 是由 Netscape 所提出來的資料保密協定,採用了對稱式以及非對稱式加密演算法再加上 CA 來確定身份所組合而成的.

  • Symmetric Algorithms 對稱式加密,所謂的對稱式加密就是加密以及解密都是使用同一支鑰匙.
  • Asymmetric Algorithms 非對稱式或稱公鑰密碼演算法的一種.所謂的非對偁式加密會使用兩把公與私鑰 (Public / Private Key), public key 會當成加密用, Private key 就會當解密用
  • CA 公正的第三者,主要用來驗證認證的真假.

那 TLS (Transport Layer Security) 是什麼呢!
IETF 將 SSL 標準化,並稱之為 TLS(Transport Layer Security)

TLS 提供了 One-Way Authenticated (Server Only) 與 Two-Way (Mutually) Authenticated (Client 與 Server) ,我們只會用到 One-way Authenticated Client 只需要確認 Server 的真偽.

剛剛的 SSL 是怎麼樣應用到 HTTP 協定上,變成 HTTPS 的.

使用者端有一支對稱式加密的鑰匙要給伺服器端,讓接下來的資料都經過加密的方式來傳送,但這隻鑰匙是無法直接透過網路來傳送,所以會使用非對稱式或稱公鑰的方式來傳送剛剛說的那一支對稱式加密的鑰匙.

另一個問題是使用者端也無法確定伺服器端的真假,所以會使用 CA 的方式來確認伺服器端的身份.

我們來看一下 https (SSL) 的交易方式.

  1. 伺服器端會給使用者端 公鑰(用來加密使用者端的對稱式加密鑰匙) 與 數位簽名的憑證(身份確認).
  2. 使用者端接到數位簽名的憑證,會先去 Root CA 詢問資料是否真的由該網站所核發.
  3. 使用者端產生一支對稱式加密的鑰匙,並使用伺服器端的公鑰加密並回傳給伺服器端,伺服器端使用自己的私鑰解開還原使用者端給的對稱式加密鑰匙.
  4. 等到伺服器端,使用者端都有對稱式加密的鑰匙後,就使用這對稱式加密的鑰匙來進行接下來的資料傳送與交易.

測試環境為 CentOS 7 /8 x86_64 + Apache2 (虛擬機) , 使用 Ubuntu 16.04 x86_64 + Apache2 請參考 – https://benjr.tw/96655

CentOS 6 方式也一樣,控制服務程式從 systemctl 改成 service 即可.

HTTP+PHP

先安裝 Web server 所需套件.

  1. Apache (Httpd)
    Web Server 可以自行選擇 Apache 或是 Nginx .下面使用的是 Apache

    [root@localhost ~]# yum install -y httpd
    
    [root@localhost ~]# systemctl enable httpd
    Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
    [root@localhost ~]# systemctl start httpd
    [root@localhost ~]# systemctl status httpd
    ● httpd.service - The Apache HTTP Server
       Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
       Active: active (running) since Fri 2017-07-21 12:03:23 CST; 5s ago
         Docs: man:httpd(8)
               man:apachectl(8)
     Main PID: 6418 (httpd)
       Status: "Processing requests..."
       CGroup: /system.slice/httpd.service
               ├─6418 /usr/sbin/httpd -DFOREGROUND
               ├─6419 /usr/sbin/httpd -DFOREGROUND
               ├─6420 /usr/sbin/httpd -DFOREGROUND
               ├─6421 /usr/sbin/httpd -DFOREGROUND
               ├─6422 /usr/sbin/httpd -DFOREGROUND
               └─6423 /usr/sbin/httpd -DFOREGROUND
    


    如果連不上請先確一下 Firewall 的狀態.

    [root@localhost ~]# systemctl stop firewalld
    

    CentOS 8 搭配的 Apache 沒有預設網頁,可以自行建立 index.html 來測試.

    [root@localhost ~]# echo Apache on CentOS 8 > /var/www/html/index.html
    

    PHP

    phpMyAdmin 主要透過 PHP 的程式語言架構出來的,而 PHP 是一種直譯式的程式語言,用於網頁的撰寫,不同於靜態式的 HTML 它可以依據使用者的需求來呈現不同的網頁內容.

    • CentOS 7
      [root@localhost ~]# yum install -y php php-pear php-mysql php-mbstring
      

      還需要安裝 mcrypt 擴充套件(沒安裝時 PHPMyAdmin 會顯示錯誤訊息: 缺少 mcrypt 擴充套件,請檢查 PHP 設定),預設的 YUM Repo 並沒有這些套件,需要新增 Repo 檔 (epel-release, Extra Packages for Enterprise Linux) .

      [root@localhost ~]# yum install -y epel-release
      [root@localhost ~]# yum install -y php-mcrypt
      
    • CentOS 8
      [root@localhost ~]# yum install -y php php-pdo php-pecl-zip php-json php-common php-fpm php-mbstring php-cli php-mysqlnd
      

    順便試一下 PHP 功能運作是否正常.可以使用編輯器來鍵入 PHP 程式碼,內容如下 (檔案需儲存在 /var/www/html – Apache 預設的目錄),或是透過 echo 直接產生.

    [root@localhost ~]# echo "<?php phpinfo() ?>" > /var/www/html/phpinfo.php
    
    [root@localhost ~]# systemctl restart httpd
    [root@localhost ~]# systemctl status httpd
    ● httpd.service - The Apache HTTP Server
       Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
       Active: active (running) since Fri 2017-07-21 14:54:28 CST; 1s ago
         Docs: man:httpd(8)
               man:apachectl(8)
      Process: 7072 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=0/SUCCESS)
     Main PID: 7078 (httpd)
       Status: "Processing requests..."
       CGroup: /system.slice/httpd.service
               ├─7078 /usr/sbin/httpd -DFOREGROUND
               ├─7080 /usr/sbin/httpd -DFOREGROUND
               ├─7081 /usr/sbin/httpd -DFOREGROUND
               ├─7082 /usr/sbin/httpd -DFOREGROUND
               ├─7083 /usr/sbin/httpd -DFOREGROUND
               └─7084 /usr/sbin/httpd -DFOREGROUND
    

    /var/www/html 是 Apache 預設的目錄,你可以修改 /etc/httpd/conf/httpd.conf 修改 DocumentRoot .
    這是 PHP 的格式,開啟你的網頁連上你 http://localhost/phpinfo.php ,如果一切運作正常那你會看到和下面一樣的網頁.

  2. HTTPS

    HTTPS 伺服器端需要 1. Root CA 給的 數位簽名憑證 與 2. 公私鑰非對偁式加密鑰匙 ,才能讓 http 伺服器端進行 SSL 加密 (需要 mod_ssl 模組).

    [root@localhost ~]# yum install -y mod_ssl
    

    建立 Root CA (Certification Authority)
    如何獲得 Root CA (Certification Authority) 給的數位簽名憑證, 數位簽名憑證採用的是 X.509,是由上至下階層式的評證制度.Serer 必須付費給 Root CA 才能使用.

    所以這邊簡單做個實驗,我們建立屬於自己的 Root CA 並發數位憑證給自己.因為不是公正的第三方,所以使用者端的瀏覽器需要使用者自行決定是否要信任這個網站.

    要發數位憑證需產生一組公私鑰非對偁式加密鑰匙,檔案建議儲存路徑為 /etc/ssl/private ,並限制只有 root 能存取.

    [root@localhost ~]# mkdir /etc/ssl/private
    [root@localhost ~]# chmod 700 /etc/ssl/private
    

    透過下面的指令可以產生 1. 發數位憑證所需產生一組 Private Key ,並產生 2. Certificate 的 CSR (憑證申請書) 與 CRT (憑證).

    [root@localhost ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt
    

    openssl 參數說明:

    • req -x509: Root CA (Certification Authority) 的數位簽名憑證採用的是 X.509 (由上至下階層式的評證制度).
    • -nodes: 產生的 apache-selfsigned.key 不使用 passphrase 作加密保護.
    • -days 365: 設定該 Certificate 有效期限.
    • -newkey rsa:2048: 產生新的 Certificate 所需的 Private Key (RSA 為非對稱式或稱公鑰密碼演算法,2048 為加密長度).
    • -keyout: 指定 Private key 檔案名稱與其存放位置.
    • -out: 指定 Certificate 檔案名稱與其檔案的存放位置,會產生 CSR (憑證申請書) 與 CRT (憑證).
    Generating a 2048 bit RSA private key
    ............+++
    ....................................................................+++
    writing new private key to '/etc/ssl/private/apache-selfsigned.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]:TW
    State or Province Name (full name) []:TAIWAN
    Locality Name (eg, city) [Default City]:TAIPEI
    Organization Name (eg, company) [Default Company Ltd]:Benjr
    Organizational Unit Name (eg, section) []:Benjr
    Common Name (eg, your name or your server's hostname) []:benjr.tw
    Email Address []:admin@benjr.tw
    

    依據網站內容填寫憑證申請書的內容.

    • Country Name (2 letter code) : 國家代碼,台灣是 TW
    • State or Province Name (full name) : 省份,你可以直接填台灣 TAIWAN
    • Locality Name (eg, city) : 城市名,你可以填台北 TAIPEI
    • Organization Name (eg, company) : 你的組織名稱,通常是公司,我這裡填的是 Benjr
    • Organizational Unit Name (eg, section) : 如果你剛填的是公司,那這就是公司部門的名稱 Benjr
    • Common Name (e.g. server FQDN or YOUR name) : 如果是伺服器憑證那就填上伺服器的全名 (benjr.tw) .若是 E-mail 憑證那就填上 E-mail.Root CA 填上組織名稱加上 RSA/2048 以供辨識.
    • Email Address :這裡請填上你的 e-mail 信箱

    剛剛的指令做了三件事情.

    1. 製作 Root CA Private Key
      指令會產生 2048 bits 的 Private Key (RSA 為非對稱式或稱公鑰密碼演算法) ,名稱為 apache-selfsigned.key ,也可以單獨使用下面指令來產生.

      [root@localhost ~]# openssl genrsa -out /etc/ssl/private/apache-selfsigned.key 2048
      Generating RSA private key, 2048 bit long modulus
      .......................+++
      ..........................................................................+++
      e is 65537 (0x10001)
      

      建立私鑰後最好將權限加以設限,以免被其他使用者取用.

      [root@localhost ~]# chmod 400 /etc/ssl/private/apache-selfsigned.key
      

      你可以用下面的指令來看 RSA 產生的 Private Key 內容.

      [root@localhost ~]# openssl rsa -noout -text -in /etc/ssl/private/apache-selfsigned.key
      Private-Key: (2048 bit)modulus:
      略...
      publicExponent: 65537 (0x10001)
      privateExponent:
      略...
      prime1:
      略...
      prime2:
      略...
      exponent1:
      略...
      exponent2:
      略...
      coefficient:
      略...
      
    2. 填寫憑證申請書 (CSR)+ 3. 簽發憑證 (CRT)
      前面指令直接產生 apache-selfsigned.csr (憑證申請書) ,並立即簽發憑證給自己 apache-selfsigned.crt (憑證) 也可以單獨使用下面指令來產生.
      正常步驟是需要給 Root CA 做簽合.

      [root@localhost ~]# openssl req -new -key /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.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]:TW
      State or Province Name (full name) []:TAIWAN
      Locality Name (eg, city) [Default City]:TAIPEI
      Organization Name (eg, company) [Default Company Ltd]:Benjr
      Organizational Unit Name (eg, section) []:Benjr
      Common Name (eg, your name or your server's hostname) []:benjr.tw
      Email Address []:admin@benjr.tw
      
      Please enter the following 'extra' attributes
      to be sent with your certificate request
      A challenge password []:
      An optional company name []:
      
      [root@localhost ~]# openssl x509 -req -days 365 -signkey /etc/ssl/private/apache-selfsigned.key -in /etc/ssl/certs/apache-selfsigned.csr -out /etc/ssl/certs/apache-selfsigned.crt
      Signature ok
      subject=/C=TW/ST=TAIWAN/L=TAIPEI/O=Benjr/OU=Benjr/CN=benjr.tw/emailAddress=admin@benjr.tw
      Getting Private key
      

      建立憑證後最好將權限加以設限,以免被其他使用者取用.

      [root@localhost ~]# chmod 400 /etc/ssl/certs/apache-selfsigned.crt
      

      可以用下面的指令來查看產生的 crt 憑證內容.

      [root@localhost ~]# openssl x509 -noout -text -in /etc/ssl/certs/apache-selfsigned.crt
      Certificate:
          Data:
              Version: 1 (0x0)
              Serial Number:
                  8b:a9:05:f5:e5:ee:9d:77
          Signature Algorithm: sha256WithRSAEncryption
              Issuer: C=TW, ST=TAIWAN, L=TAIPEI, O=Benjr, OU=Benjr, CN=benjr.tw/emailAddress=admin@benjr.tw
              Validity
                  Not Before: Aug 27 15:17:57 2019 GMT
                  Not After : Aug 26 15:17:57 2020 GMT
              Subject: C=TW, ST=TAIWAN, L=TAIPEI, O=Benjr, OU=Benjr, CN=benjr.tw/emailAddress=admin@benjr.tw
              Subject Public Key Info:
                  Public Key Algorithm: rsaEncryption
                      Public-Key: (2048 bit)
                      Modulus:
                          00:ca:a5:09:02:cc:36:9d:a9:67:3c:f3:4b:38:9b:
      略... 
                      Exponent: 65537 (0x10001)
          Signature Algorithm: sha256WithRSAEncryption
               9f:b2:e0:b6:1b:f6:ff:0f:3a:b7:1a:62:92:15:9c:e4:d9:2c:
      略... 
      

      可以看到的他的內容包括下列的東西
      第一部分是要申請的憑證內容
      第二部分是 Public Key
      第三部分將剛才的內容(第一二部分)經過 on way hash (SHA1256) 所得到的訊息摘要 (Digest Hash) . 這可確定在傳送過程資料不會遭到修改.

    編輯 Apache2 https 設定檔
    修改 /etc/httpd/conf.d/ssl.conf 設定檔裡 <VirtualHost _default_:443> </VirtualHost> 中間新增以下的內容.

    [root@localhost ~]# vi /etc/httpd/conf.d/ssl.conf
    DocumentRoot "/var/www/html"
    SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
    SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
    
    [root@localhost ~]# systemctl restart httpd
    

    檢視一下 http Port 80 與 https port 443 皆有啟動.

    [root@localhost ~]# journalctl -u httpd
    Aug 05 15:02:27 localhost.localdomain systemd[1]: Starting The Apache HTTP Server...
    Aug 05 15:02:27 localhost.localdomain httpd[36780]: AH00558: httpd: Could not reliably determine the server's fully qualified domain na>
    Aug 05 15:02:27 localhost.localdomain systemd[1]: Started The Apache HTTP Server.
    Aug 05 15:02:27 localhost.localdomain httpd[36780]: Server configured, listening on: port 443, port 80
    

    瀏覽 HTTPS 網頁
    直接透過 wget 來試試,要加入 –no-check-certificate ,不然會出現錯誤訊息.

    [root@localhost ~]# wget https://192.168.95.251/phpinfo.php
    --2019-08-27 23:26:16--  https://192.168.95.251/phpinfo.php
    Connecting to 192.168.95.251:443... connected.
    ERROR: cannot verify 192.168.95.251's certificate, issued by '/C=TW/ST=TAIWAN/L=TAIPEI/O=Benjr/OU=Benjr/CN=benjr.tw/emailAddress=admin@benjr.tw':
      Self-signed certificate encountered.
        ERROR: certificate common name 'benjr.tw' doesn't match requested host name '192.168.95.251'.
    To connect to 192.168.95.251 insecurely, use `--no-check-certificate'.
    
    [root@localhost ~]# wget --no-check-certificate https://192.168.95.251/phpinfo.php
    --2019-08-27 23:26:33--  https://192.168.95.251/phpinfo.php
    Connecting to 192.168.95.251:443... connected.
    WARNING: cannot verify 192.168.95.251's certificate, issued by '/C=TW/ST=TAIWAN/L=TAIPEI/O=Benjr/OU=Benjr/CN=benjr.tw/emailAddress=admin@benjr.tw':
      Self-signed certificate encountered.
        WARNING: certificate common name 'benjr.tw' doesn't match requested host name '192.168.95.251'.
    HTTP request sent, awaiting response... 200 OK
    Length: unspecified [text/html]
    Saving to: 'phpinfo.php'
    
        [ <=>                                                           ] 59,448      --.-K/s   in 0s      
    
    2019-08-27 23:26:33 (227 MB/s) - 'phpinfo.php' saved [59448]
    

    也可以使用 https:// 來開啟網站,但會看到如下的畫面.

    因為 Root CA 是自己(不是公正的第三方)而且並發數位憑證給自己,所以使用者端的瀏覽器需要使用者自行決定是否要信任這個網站.

    在檢視憑證中可以看到我們剛剛設定 CA 的詳細資料.

    清楚了 HTTPS 的架構後就可以正式找公正的第三方發數位憑證,大部分都需要收費, Let’s Encrypt 不收費但我也還沒使用過,請參考 https://free.com.tw/ssl-for-free/ 的說明.

    沒有解決問題,試試搜尋本站其他內容

3 thoughts on “CentOS – HTTPS (HTTP + SSL + CA)

  1. 謝謝您的文章,從六七年前就常因工作需要,會參考您的文章做一些環境架設及測試,
    近期拜讀了這篇文章終於把HTTP Boot 以及HTTPs Boot環境架設完成
    衷心感謝您的文章 讓我可以學到很多東西

  2. ssl 流程 3 寫錯了吧。
    “伺服器端 使用私鑰將這對稱式加密的鑰匙加密傳送,使用者端再用公鑰將資料解密還原成原本的對稱式加密的鑰匙. ”
    這樣的話攔到公鑰的人都可以解密訊息。
    應該是使用者用公鑰加密, 而只有持有私鑰的 server 能解開。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料