by Devin Yang

建立於: 1年前 ( 更新: 1年前 )

HAProxy的重載速度很快,跟本感覺不出有重啟,所有憑證都給HAProxy處理真的很方便。

主機環境需求,請確認您已有下面兩個指令
(Ubuntu怎麼裝? apt-get install -y haproxy cerbot,我猜的,如果不是請自行Google)

root@ptest:/usr/local/scripts# which certbot
/usr/bin/certbot
root@ptest:/usr/local/scripts# which haproxy
/usr/sbin/haproxy


本文介紹,我的如何用bash生成憑證全過程。

第一步: 建立產生憑證用的bash,我取名叫gen_cert.sh

首先我寫了一支產憑證的bash叫gen_cert.sh,我的習慣會放到/usr/local/scripts下,只有root可存取

#!/bin/bash
/usr/bin/certbot \
 --email unknow@ccc.tc \
 --no-eff-email \
 --webroot -w /var/www/html \
 -d ccc.tc \
 -d www.ccc.tc \
 中間...略過一大堆
 -d chat.ccc.tc \
 -d speed.ccc.tc \
 -d chat.ccc.tc \
 -d video.ccc.tc \
 certonly

在這裡的--webroot -w就是驗證檔的根目錄,代表命令執行時,下方的目錄會被放驗證檔
/var/www/html/.well-known/acme-challenge
其他的-d參數,就是你要申請的憑證的域名啦

開始前,我稍微解釋一下,我域名的DNS Record設定為*.ccc.tc,
也就是說,所有子域名不指定A Record的情況下IP都會指向220.134.172.98這個IP位置的。

好的,我直接試給大家看

root@ptest:/usr/local/scripts# host -t a eewoieoiewo.ccc.tc
eewoieoiewo.ccc.tc has address 220.134.172.98

因為這樣,大家或許猜到了,當我要申請域名時,只要在gen_cert上,補上-d <我要的域名即可>,再執行./gen_cert.sh即可。
例如:  -d dtest.ccc.tc \

/usr/bin/certbot \
 --email unknow@ccc.tc \
 --no-eff-email \
 --webroot -w /var/www/html \
 -d ccc.tc \
 -d www.ccc.tc \
 中間...略過一大堆
 -d chat.ccc.tc \
 -d speed.ccc.tc \
 -d chat.ccc.tc \
 -d video.ccc.tc \
 -d dtest.ccc.tc \
 certonly

以上,這個產憑證的bash說明完畢了。
也就是說,當Let's encrpyt要進行驗證時,不管子域名是什麼,只要後面的路徑是/.well-known/acme-challenge,一律導向我設定的本地端HTTP Server即可。

第二步: 我們需要安裝一台本地端的HTTP Server
在這裡我的例子採用apache2,網站根目錄就是/var/www/html,就是上面bash所指定的位置 (--webroot -w /var/www/html)。
您可以用您任何會安裝的Web Server或是Docker只要你喜歡,但有一點要注意,就是別開port 80,因為這要留給HAProxy用。

root@ptest:/etc/apache2/sites-enabled# systemctl status apache2
● apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2022-11-26 21:47:31 CST; 2 weeks 0 days ago
     Docs: https://httpd.apache.org/docs/2.4/
 Main PID: 701 (apache2)
    Tasks: 55 (limit: 4915)
   CGroup: /system.slice/apache2.service
           ├─  701 /usr/sbin/apache2 -k start
           ├─19344 /usr/sbin/apache2 -k start
           └─19345 /usr/sbin/apache2 -k start

在我的環境中apache2很幸運他啟動的連接埠預設是port 8080不是port 80。

root@ptest:/etc/apache2/sites-enabled# head -n1 000-default.conf
<VirtualHost *:8080>
root@ptest:/etc/apache2/sites-enabled# netstat -ntlp|grep :8080
tcp6       0      0 :::8080                 :::*                    LISTEN      701/apache2
root@ptest:/etc/apache2/sites-enabled#


第三步: 設定HAProxy的存取規則
HAProyx的設定檔應該會在/etc/haproxy/haproxy.cfg
請用自己常用的編輯器開啟進行編輯,開始前先來看底下兩個重要設定。

   acl acme path_beg -i /.well-known/acme-challenge
   redirect scheme https code 301 if !{ ssl_fc } !acme

第一條: 設定開始路徑為這樣的/.well-known/acme-challenge就使用acme存取規則
第二條: 如果不符合acme規則,都自動跳轉HTTPS,也就是說,
假如當網址長這樣時 http://abc.ccc.tc/.well-known/acme-challenge,是不會被跳轉的。
為讓大家更有feel,底下的的域名是我隨便打的,基本上都開同一個檔,您可以試看看,
甚至您隨便改子域名的名稱,都可以看到Hello World文字。

http://iewoieoieo.ccc.tc/.well-known/acme-challenge/test.txt

http://lksjlkjkalfjlsjlj.ccc.tc/.well-known/acme-challenge/test.txt

現在,我們來看看/etc/haproxy/haproxy.cfg內容,大概就像下方這樣,我只列出重點哦,
您有注意到了嗎? 內容中底下use_backend local if acme這個設定。
他的意思非常直覺,不管域名是什麼,只要路徑是/.well-known/acme-challenge符合acme的存取規則,都會使用local這個後端服務(use_backend local)。
local這個名稱是我隨傳打的,您可以取您想要的名稱。

frontend proxy
   mode http
   bind :443 ssl crt /etc/ssl/ccc.tc/ccc.tc.pem alpn h2,http/1.1 crt /etc/ssl/ccc.tc/demo.ccc.tc.pem alpn h2,http/1.1  crt /etc/ssl/ccc.tc/e-course.app.pem alpn h2,http/1.1
   bind *:80
   acl acme path_beg -i /.well-known/acme-challenge
   redirect scheme https code 301 if !{ ssl_fc } !acme

   #acme-challenge 您應該跟我一樣會有很多backend,acme的lcoal server要放在最上面
   use_backend local if acme
   use_backend material_server if material_url
   use_backend wss_server if wss_url
   use_backend webrtc_server if webrtc_url
   use_backend linebot_server if linebot_url

在use_backend local if acme中,他指向的正是上方「第二步」中設定的主機

    backend local
       mode http
       balance roundrobin
       server ptest 127.0.0.1:8080


我自己的習慣會弄一個別名的驗證檔,檢測haproyx的設定是否有搞錯

alias hat='haproxy -f /etc/haproxy/haproxy.cfg -c'

像這樣

root@ptest:~# hat
Configuration file is valid

如果沒問題,基本上,我要產生憑證及子域名,只要調一下gen_cert.sh就可以產生啦,超方便。

要確認您的設定是否有效,可以隨傳到驗證的目錄(/var/www/html/.well-known/acme-challenge)下touch個檔案,
再從主機端透過網址的方式去開開看有沒有效。

因為我已經產生過很多啦,所以下方的例子,會問我是否擴張憑證,您也看到下面的畫面中,有一堆子域名,
多到我自己都忘了是做什麼用的了😆,就知道我用這環境產生憑證有多簡單啦。

root@ptest:/usr/local/scripts# ./gen_cert.sh
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Attempting to parse the version 1.22.0 renewal configuration file found at /etc/letsencrypt/renewal/ccc.tc.conf with version 0.31.0 of Certbot. This might not work.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You have an existing certificate that contains a portion of the domains you
requested (ref: /etc/letsencrypt/renewal/ccc.tc-0003.conf)

It contains these names: ccc.tc, 627csizs.ccc.tc, admin.ccc.tc, ai.ccc.tc,
auth2.ccc.tc, bbb.ccc.tc, cbk.ccc.tc, ccc-chat.ccc.tc, chat.ccc.tc,
chatroom.ccc.tc, cool.ccc.tc, d2.ccc.tc, ddm.ccc.tc, demo.ccc.tc, drive.ccc.tc,
dtest.ccc.tc, fb.ccc.tc, git.ccc.tc, gw.ccc.tc, imac.ccc.tc, ip.ccc.tc,
laravel.ccc.tc, line.ccc.tc, linebot.ccc.tc, linux.ccc.tc, mail.ccc.tc,
material.ccc.tc, nas.ccc.tc, notes.ccc.tc, pdf.ccc.tc, photo.ccc.tc,
phpenv.ccc.tc, pi4.ccc.tc, push.ccc.tc, reg.ccc.tc, sagent.ccc.tc,
sldrive.ccc.tc, speed.ccc.tc, station.ccc.tc, test.ccc.tc, tn.ccc.tc,
tools.ccc.tc, vbk.ccc.tc, video.ccc.tc, vm.ccc.tc, webrtc.ccc.tc, wss.ccc.tc,
www.ccc.tc, yty.ccc.tc

You requested these names for the new certificate: ccc.tc, 627csizs.ccc.tc,
admin.ccc.tc, chat.ccc.tc, ddm.ccc.tc, drive.ccc.tc, fb.ccc.tc, imac.ccc.tc,
ip.ccc.tc, laravel.ccc.tc, line.ccc.tc, linux.ccc.tc, nas.ccc.tc, notes.ccc.tc,
station.ccc.tc, pdf.ccc.tc, reg.ccc.tc, sagent.ccc.tc, www.ccc.tc, vm.ccc.tc,
cool.ccc.tc, photo.ccc.tc, bbb.ccc.tc, yty.ccc.tc, cbk.ccc.tc, auth2.ccc.tc,
webrtc.ccc.tc, vbk.ccc.tc, d2.ccc.tc, git.ccc.tc, push.ccc.tc, video.ccc.tc,
dtest.ccc.tc, mail.ccc.tc, ccc-chat.ccc.tc, tools.ccc.tc, sldrive.ccc.tc,
tn.ccc.tc, pi4.ccc.tc, gw.ccc.tc, wss.ccc.tc, demo.ccc.tc, test.ccc.tc,
ai.ccc.tc, speed.ccc.tc, linebot.ccc.tc, chatroom.ccc.tc, material.ccc.tc

Do you want to expand and replace this existing certificate with the new
certificate?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(E)xpand/(C)ancel:

我壓大寫的E,即可進行憑證擴張。

第四步: 憑證更新renew.sh或憑證重載reload.sh
由於憑證是給HAProxy控管的,所以當產生新的憑證,我們要來重組新憑證的內容給HAProyx,並且重載haproxy服務。
您可以建兩個檔案,一個是會renew憑證用的,另一個則無renew指令,這樣產新憑證時執行reload.sh速度較快,不需檢測憑證是否需更新。

#!/bin/bash
#更新憑證
#/usr/bin/docker run --rm \
#       -v /etc/letsencrypt:/etc/letsencrypt \
#       -v /var/www/html:/html \
#       certbot/certbot:arm32v6-latest \
#       --webroot -w /html/ \
#       renew

/usr/bin/certbot \
--webroot -w /var/www/html/ \
renew

#重組
FOLDER=ccc.tc
cat /etc/letsencrypt/live/${FOLDER}/fullchain.pem \
    /etc/letsencrypt/live/${FOLDER}/privkey.pem > \
    /etc/ssl/ccc.tc/${FOLDER}.pem

#重啟HAProxykk
systemctl reload haproxy

第五步: 如果確認renew.sh手動執行沒問題,就放入排程每天跑自動更新

0 0 * * * /usr/local/scripts/renew.sh


總結
假定您的設定無誤,並且理解我本篇的說明,那所有的經過此HAProxy的後端主機都會經由HAProyx進行加密,
所有的後端主機完全不用設定憑證,並且所有後端主機的憑證都會被自動更新。

下方為示意說明

    use_backend local if acme

    use_backend material_server if material_url
    use_backend wss_server if wss_url
    use_backend webrtc_server if webrtc_url
    use_backend linebot_server if linebot_url
   
   backend ai_server
       mode http
       balance roundrobin
       fullconn   10000
       cookie SITEID insert indirect nocache
       server tplink 192.168.99.181:8000

    backend gw_router
       mode http
       balance roundrobin
       fullconn   10000
       cookie SITEID insert indirect nocache
       server tplink 192.168.99.254:80

    backend nas
       mode http
       balance roundrobin
       fullconn   10000
       cookie SITEID insert indirect nocache
       server nas 192.168.99.130:5000 check cookie synology

Tags: ssl haproxy certbot

Devin Yang

文章內容無法一一說明,如果您有什麼不了解處,歡迎提問哦:)

No Comment

Post your comment

需要登入才可留言!

類似的文章


openssl

如何移除PEM的密碼

您可以使用openssl rsa命令刪除密碼。 我們傳入SSL .key並獲得一個.key文件作為輸出。

php openssl curl

修正CA設定問題

有時可能PHP版本更新或環境變動造成找不到ca檔案。 修正很簡單

ssl,certbot

攻略docker版Let's Encrypt憑證申請

本文主要分享,我如何採用Docker的方式進行Let's Encrypt憑證申請, Let's Encrypt有相當多種類的ACME Client, 我將使用官方推廌Certbot(ACME Client)做說明。 並且使用docker的方式來執行ACME Client。