HTTPS-自己生成數字證書

無風聽海發表於2021-11-16

一、獲取證照的途徑

  1. 自簽名證照,適用於開發者測試HTTPS,最快速的途徑就是生成自簽名證照,非常方便。
  2. Let's Encrypt證照,可以使用免費CA機構簽發的證照。
  3. 使用收費CA機構簽發的證照,如果對證照安全性、相容性、功能有特殊需求,可以向CA機構申請證照。

二、自簽名證照

自簽名證照是我們自己簽發的,瀏覽器不會整合私有的CA機構的根證照,所以開啟頁面的時候會進行提示,使用者選擇信任證照之後,後續的通訊就會進行加密保護的。

自簽名證照的用途還是很廣泛的,對於一些企業內部系統,由於購買證照需要成本,可以生成自簽名證照,企業內部系統的使用者一般執行在同一個區域網下,由防火牆保護,風險相對可控,當瀏覽器提示使用者自簽名證照存在風險時,使用者可以選擇信任自簽名證照,等同於訪問了一個HTTPS網站。

生成自簽名證照的步驟如下

1.生成私鑰對和CSR

我們設定金鑰的長度為2048bit;

我們最終會得到flask_self_csr.pem和flask_self_key.pem兩個檔案;

CSR(Certificate Signing Request)表示證照籤名請求,裡面包含了伺服器的金鑰對,CA機構接收到請求會驗證CSR請求的簽名;

flask_self_csr.pem包含了我們的金鑰對;

執行命令之後,我們可以在互動式提示中,設定證照包含的一些資訊;

mango@mango-ubuntu:~/文件/blogs/web/證照$ openssl req  -newkey rsa:2048 -nodes -keyout flask_self_key.pem  -out flask_self_csr.pem
Generating a RSA private key
.........+++++
......+++++
writing new private key to 'flask_self_key.pem'
-----
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) [AU]:CN
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg, city) []:Beijing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:mango
Organizational Unit Name (eg, section) []:mango
Common Name (e.g. server FQDN or YOUR name) []:cee1-110-251-30-176.ngrok.io
Email Address []:mango@163.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:          
An optional company name []:

  1. 生成自簽名證照

接下來通過CSR生成證照,對於自簽名證照,我們可以認為自己就是一個CA機構,輸入如下命令生成證照:

mango@mango-ubuntu:~/文件/blogs/web/證照$ openssl x509 -signkey flask_self_key.pem -in flask_self_csr.pem  -req -days 365 -out flask_self_cert.pem
Signature ok
subject=C = CN, ST = Beijing, L = Beijing, O = mango, OU = mango, CN = cee1-110-251-30-176.ngrok.io, emailAddress = mango@163.com
Getting Private key

  1. 驗證證照

將生成的flask_self_cert.pem和flask_self_key.pem拷貝到站點根目錄下,並設定啟用ssl

from flask import Flask


app = Flask(__name__)

@app.route("/", methods=["GET"])
def hello():
    return 'hello python'

if __name__ == "__main__":
    app.run('0.0.0.0', ssl_context=('flask_self_cert.pem', 'flask_self_key.pem'))
    # app.run('0.0.0.0', debug=True, ssl_context='adhoc')

三、使用Let's Encrypt證照

Let's Encrypt首先是一個CA機構,得到了很多大公司的支援,相容性非常不錯,同時它定義了ACME協議,將管理證照的流程進行了標準化、自動化,不用人工管理。可以使用基於ACME協議的客戶端在Let's Encrypt管理證照,官方推薦Certbot客戶端,使用非常方便。

1.安裝Certbot客戶端

mango@mango-ubuntu:~/文件/blogs/web/證照/certbot$ sudo snap install --classic certbot
certbot 1.21.0 from Certbot Project (certbot-eff✓) installed

2.手動生成證照和金鑰檔案

mango@mango-ubuntu:~/文件/blogs/web/證照$ sudo certbot certonly --manual  -d 565c-110-251-30-176.ngrok.io 
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for 565c-110-251-30-176.ngrok.io

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Create a file containing just this data:

csM3J5YGt3V-PQDeRpcDhjlpy7Hdf9tjh-NsIqqoA6A.eRfiNKPaGpDq-g1FefRl52GbfFeSDV_Qg8Gwe1KQP5M

And make it available on your web server at this URL:

http://565c-110-251-30-176.ngrok.io/.well-known/acme-challenge/csM3J5YGt3V-PQDeRpcDhjlpy7Hdf9tjh-NsIqqoA6A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/565c-110-251-30-176.ngrok.io/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/565c-110-251-30-176.ngrok.io/privkey.pem
This certificate expires on 2022-02-10.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

為了通過CA對站點的驗證,我們需要新增對應的action來響應對應的請求

@app.route("/.well-known/acme-challenge/csM3J5YGt3V-PQDeRpcDhjlpy7Hdf9tjh-NsIqqoA6A")
def challenge():
    return 'csM3J5YGt3V-PQDeRpcDhjlpy7Hdf9tjh-NsIqqoA6A.eRfiNKPaGpDq-g1FefRl52GbfFeSDV_Qg8Gwe1KQP5M'
  1. 驗證證照

將生成的證照和金鑰檔案拷貝到站點根目錄,並修改檔案許可權

mango@mango-ubuntu:~/文件/blogs/webhook$ sudo cp /etc/letsencrypt/live/565c-110-251-30-176.ngrok.io/fullchain.pem fullchain.pem
mango@mango-ubuntu:~/文件/blogs/webhook$ sudo cp /etc/letsencrypt/live/565c-110-251-30-176.ngrok.io/privkey.pem 
mango@mango-ubuntu:~/文件/blogs/webhook$ sudo chown mango fullchain.pem
mango@mango-ubuntu:~/文件/blogs/webhook$ sudo chown mango privkey.pem 

修改站點啟用ssl

from flask import Flask

app = Flask(__name__)

@app.route("/", methods=["GET"])
def hello():
    return 'hello python'

@app.route("/.well-known/acme-challenge/csM3J5YGt3V-PQDeRpcDhjlpy7Hdf9tjh-NsIqqoA6A")
def challenge():
    return 'csM3J5YGt3V-PQDeRpcDhjlpy7Hdf9tjh-NsIqqoA6A.eRfiNKPaGpDq-g1FefRl52GbfFeSDV_Qg8Gwe1KQP5M'

if __name__ == "__main__":
    app.run('0.0.0.0', ssl_context=('fullchain.pem', 'privkey.pem'))
    # app.run('0.0.0.0', ssl_context=('flask_self_cert.pem', 'flask_self_key.pem'))
    # app.run('0.0.0.0', debug=True, ssl_context='adhoc')

相關文章