在Docker容器環(huán)境中用Let's Encrypt部署HTTPS

昨天嘗試了用Let's Encrypt給自己的博客部署了HTTPS,感覺(jué)這個(gè)服務(wù)真的是非常方便邻悬。網(wǎng)上有很多關(guān)于Let's Encrypt的文章症昏,不過(guò)本站因?yàn)椴渴鹪赿ocker容器中,關(guān)于這種架構(gòu)的文章不多父丰,我把自己的思路寫下來(lái)吧肝谭。

先來(lái)說(shuō)點(diǎn)基礎(chǔ)的話題。

HTTPS可以提供全面的密碼學(xué)保護(hù)蛾扇,換句話說(shuō)攘烛,訪問(wèn)HTTPS網(wǎng)站時(shí),用戶和網(wǎng)站之間傳輸?shù)臄?shù)據(jù)不會(huì)被第三方竊取和監(jiān)聽(tīng)镀首。這里的第三方包括黑客坟漱、運(yùn)營(yíng)商、監(jiān)管部門更哄,有你想得到的也有你想不到的芋齿。

HTTPS是基于公鑰密碼的,簡(jiǎn)單說(shuō)就是服務(wù)器提供一個(gè)公鑰成翩,用戶用這個(gè)公鑰加密數(shù)據(jù)后發(fā)給服務(wù)器觅捆,然后服務(wù)器用自己的私鑰解密。這里面有一個(gè)問(wèn)題麻敌,即如何確定服務(wù)器的公鑰是真的惠拭,如果第三方攔截并偽造服務(wù)器的公鑰,用戶用第三方的假公鑰加密數(shù)據(jù),那么這些數(shù)據(jù)就會(huì)被第三方解密并竊取职辅。

為了避免這樣的問(wèn)題棒呛,就出現(xiàn)了證書。證書本身是個(gè)數(shù)字簽名域携,就像給服務(wù)器的公鑰蓋個(gè)公章簇秒,用戶看到公章就知道公鑰是真的了。但是秀鞭,這個(gè)問(wèn)題沒(méi)有根本解決趋观,怎么知道公章本身是不是真的呢?因?yàn)楣碌谋举|(zhì)是數(shù)字簽名锋边,于是瀏覽器里面內(nèi)置了一份“可信公章清單”皱坛,凡是在這份清單里的簽名都認(rèn)為是可信的。

因此豆巨,原則上說(shuō)所有人都可以自己頒發(fā)證書剩辟,但自己頒發(fā)的證書不被瀏覽器信任(不在可信公章清單里),瀏覽器就會(huì)報(bào)錯(cuò)(比如12306網(wǎng)站遇到的錯(cuò)誤)往扔。這時(shí)有三種解決方法贩猎,第一是讓用戶強(qiáng)制認(rèn)為自己的證書是可信的(12306的做法),第二是請(qǐng)?jiān)诳尚殴虑鍐卫锏臋C(jī)構(gòu)給自己的網(wǎng)站發(fā)證書萍膛,第三是讓瀏覽器把自己列到可信清單里去(即成為可信的CA)吭服。

第一種做法簡(jiǎn)單粗暴,風(fēng)險(xiǎn)也很大蝗罗,因?yàn)橛脩舭惭b的證書如果是偽造的艇棕,那在訪問(wèn)偽造的釣魚網(wǎng)站時(shí),就會(huì)誤認(rèn)為訪問(wèn)了可信的網(wǎng)站串塑。第三種做法很難欠肾,因?yàn)槌蔀榭尚诺腃A需要嚴(yán)格的條件。大部分網(wǎng)站用的第二種做法拟赊,即請(qǐng)可信CA來(lái)頒發(fā)證書刺桃。

但是CA作為盈利機(jī)構(gòu)不會(huì)免費(fèi)給你提供這種服務(wù),因此請(qǐng)CA頒發(fā)證書是要收費(fèi)的吸祟,這個(gè)費(fèi)用現(xiàn)在越來(lái)越便宜瑟慈,但還是不太便宜。此外屋匕,簽發(fā)和更新證書都要通過(guò)人工完成葛碧,這對(duì)于越來(lái)越要求自動(dòng)化運(yùn)維的互聯(lián)網(wǎng)行業(yè)成了一個(gè)絆腳石。

于是2015年誕生了一個(gè)叫做Let's Encrypt的項(xiàng)目过吻,這個(gè)項(xiàng)目的目標(biāo)是實(shí)現(xiàn)全互聯(lián)網(wǎng)加密进泼。先不管這個(gè)目標(biāo)是否現(xiàn)實(shí)蔗衡,從技術(shù)層面上,Let's Encrypt推出了兩個(gè)革新:第一是免費(fèi)簽發(fā)可信的證書乳绕,第二是實(shí)現(xiàn)證書簽發(fā)和更新的完全自動(dòng)化绞惦。

傳統(tǒng)的CA在簽發(fā)證書的時(shí)候必須驗(yàn)證申請(qǐng)人的身份,每個(gè)證書只能綁定特定的域名使用洋措,換句話說(shuō)济蝉,你得證明你擁有這個(gè)域名的控制權(quán)。Let's Encrypt可以采用多種方式自動(dòng)完成驗(yàn)證菠发,有多種客戶端程序支持Let's Encrypt的方案王滤,還提供了各種主流服務(wù)器的插件。不過(guò)本站的環(huán)境不是典型的環(huán)境滓鸠,關(guān)于各種典型環(huán)境下的部署方法請(qǐng)參見(jiàn)certbot(官方推薦的客戶端)的官方教程雁乡。

先介紹一下我的環(huán)境配置。服務(wù)器是Digital Ocean的一臺(tái)VPS糜俗,系統(tǒng)是CoreOS踱稍,所以這是一臺(tái)只能跑容器的服務(wù)器。服務(wù)器上運(yùn)行了3個(gè)網(wǎng)站吩跋,每個(gè)網(wǎng)站都是一個(gè)單獨(dú)的容器寞射,這些容器是基于PHP官方鏡像(with Apache)定制的渔工,另外有一個(gè)反向代理容器(基于nginx官方鏡像)負(fù)責(zé)根據(jù)域名將訪問(wèn)分配到每個(gè)網(wǎng)站锌钮。

由于CoreOS只能運(yùn)行容器,因此無(wú)法在CoreOS中直接安裝certbot引矩,還好certbot有個(gè)官方的docker鏡像梁丘,我們可以直接pull:

docker pull quay.io/letsencrypt/letsencrypt:latest

運(yùn)行這個(gè)鏡像就可以申請(qǐng)簽發(fā)證書,在運(yùn)行之前首先確保你要申請(qǐng)證書的域名能直接解析到你當(dāng)前這臺(tái)服務(wù)器上旺韭。

docker run -it --rm -p 80:80 -p 443:443 \
    -v /etc/letsencrypt:/etc/letsencrypt \
    quay.io/letsencrypt/letsencrypt auth

解釋一下這里都做了什么事氛谜。首先-it選項(xiàng)表示開(kāi)啟交互輸入,因?yàn)樵谏暾?qǐng)證書的過(guò)程中需要用戶輸入一些信息区端;--rm選項(xiàng)表示容器運(yùn)行結(jié)束后自動(dòng)刪除值漫,因?yàn)檫@是一個(gè)一次性容器;兩個(gè)-p選項(xiàng)表示映射主機(jī)的兩個(gè)端口织盼,因?yàn)閏ertbot需要通過(guò)這兩個(gè)端口來(lái)做驗(yàn)證杨何,這里需要注意的是,我的nginx容器已經(jīng)占用了這兩個(gè)端口沥邻,因此在申請(qǐng)證書之前危虱,需要先停止nginx容器;-v選項(xiàng)表示映射磁盤數(shù)據(jù)卷唐全,因?yàn)閏ertbot會(huì)將所有信息保存在/etc/letsencrypt目錄中埃跷,我們需要讓這個(gè)目錄的內(nèi)容持久化并可以從主機(jī)以及其他容器(主要是nginx容器)訪問(wèn)它。

第一次申請(qǐng)證書需要注冊(cè)賬號(hào),過(guò)程很簡(jiǎn)單弥雹,先同意里面的協(xié)議垃帅,然后輸入一個(gè)郵件地址作為ID就可以了(不需要驗(yàn)證這個(gè)郵箱,只是一個(gè)ID)缅糟,以后運(yùn)行時(shí)賬號(hào)會(huì)保存在本地挺智,就不需要再輸入郵件地址了。接下來(lái)需要選擇驗(yàn)證方式窗宦,這里選擇Temporary web server方式赦颇,也就是說(shuō)讓certbot自己?jiǎn)?dòng)一個(gè)臨時(shí)Web服務(wù)器(因此需要開(kāi)放80和443端口)完成驗(yàn)證。最后輸入你要簽發(fā)證書的域名赴涵,程序自動(dòng)完成認(rèn)證之后媒怯,證書就簽發(fā)好了。

如果你不喜歡這樣一步一步的方式(比如我就不喜歡)髓窜,可以在命令行里提供所有的參數(shù)扇苞,這樣就一步搞定了:

docker run --rm -p 80:80 -p 443:443 \
    -v /etc/letsencrypt:/etc/letsencrypt \
    quay.io/letsencrypt/letsencrypt auth \
    --standalone -m someone@email.com --agree-tos \
    -d your.domain1.com -d your.domain2.com

證書簽發(fā)之后,會(huì)存放到/etc/letsencrypt目錄中寄纵,剛才我們映射了數(shù)據(jù)卷鳖敷,因此可以直接從宿主機(jī)中看到這個(gè)目錄中的內(nèi)容,其中證書位于/etc/letsencrypt/live/your.domain1.com中程拭。接下來(lái)需要讓nginx容器也能夠讀取這些證書定踱,方法放簡(jiǎn)單,把這個(gè)目錄映射給nginx容器就可以了:

docker run --name nginx -p 80:80 -p 443:443 \
    -v /etc/nginx/conf.d:/etc/nginx/conf.d \
    -v /etc/letsencrypt:/etc/letsencrypt \
    nginx

第一個(gè)-v是存放nginx配置文件的目錄恃鞋,第二個(gè)-v就是存放證書的目錄崖媚,接下來(lái)我們?cè)诰W(wǎng)站的配置文件里把證書配上去:

server {
    listen 443 ssl;
    server_name your.domain1.com;
 
    ssl_certificate /etc/letsencrypt/your.domain1.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/your.domain1.com/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
 
    location / {
        proxy_pass http://172.17.0.1:8001;
    }
}
 
server {
    listen 80;
    server_name your.domain1.com;
    return 301 https://$host$request_uri;
}

配置文件主要就是ssl_certificatessl_certificate_key兩行,第一行是提供給客戶端的公鑰(證書)恤浪,第二行是服務(wù)器用來(lái)解密客戶端消息的私鑰(私鑰不會(huì)畅哑,也不應(yīng)該在網(wǎng)絡(luò)上傳輸)。后面第二個(gè)server塊是將直接用HTTP的訪問(wèn)重定向到HTTPS連接上水由。

修改好配置文件之后重啟nginx容器荠呐,順利的話網(wǎng)站就可以通過(guò)HTTPS訪問(wèn)了,可以通過(guò)瀏覽器看一下證書信息砂客,頒發(fā)者是Let's Encrypt Authority X3泥张,它的根CA是DST,即IdenTrust鞭盟,這是一個(gè)為銀行和金融提供證書的可信CA圾结,通過(guò)和IdenTrust交叉驗(yàn)證,Let's Encrypt的證書可以在各種瀏覽器上確背菟撸可信筝野。不過(guò)Let's Encrypt簽發(fā)的證書是短效證書晌姚,有效期只有3個(gè)月,但沒(méi)關(guān)系歇竟,我們可以通過(guò)一個(gè)簡(jiǎn)單的命令對(duì)證書進(jìn)行更新挥唠,同樣是通過(guò)docker容器來(lái)運(yùn)行:

docker run --rm -p 80:80 -p 443:443 \
    -v /etc/letsencrypt:/etc/letsencrypt \
    quay.io/letsencrypt/letsencrypt renew \
    --standalone

運(yùn)行這個(gè)命令時(shí),certbot會(huì)自動(dòng)檢查確認(rèn)證書有效期焕议,如果過(guò)期時(shí)間在一個(gè)月之內(nèi)宝磨,就會(huì)自動(dòng)更新。在CoreOS中盅安,由于沒(méi)有Cron唤锉,我們需要通過(guò)systemd的timer來(lái)做定時(shí)調(diào)度,比如每個(gè)月運(yùn)行一次這個(gè)renew任務(wù)就可以了别瞭,不過(guò)記得運(yùn)行之前先停止nginx容器窿祥,運(yùn)行之后再啟動(dòng)nginx容器。

除了standalone方式驗(yàn)證之外蝙寨,還可以使用wwwroot方式來(lái)做驗(yàn)證晒衩,但在我的環(huán)境中,nginx容器只是反向代理墙歪,本身沒(méi)有wwwroot听系,因此standalone方式比較簡(jiǎn)單,當(dāng)然缺點(diǎn)是每次簽發(fā)和更新證書都要先停止nginx容器虹菲,這會(huì)造成網(wǎng)站服務(wù)中斷靠胜。如果需要保證服務(wù)不中斷,可以為nginx容器單獨(dú)配一個(gè)驗(yàn)證用的wwwroot届惋。

好了髓帽,祝大家加密愉快菠赚,祝Let's Encrypt不要那么快被墻脑豹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衡查,隨后出現(xiàn)的幾起案子瘩欺,更是在濱河造成了極大的恐慌,老刑警劉巖拌牲,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱饿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡塌忽,警方通過(guò)查閱死者的電腦和手機(jī)拍埠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)土居,“玉大人枣购,你說(shuō)我怎么就攤上這事嬉探。” “怎么了棉圈?”我有些...
    開(kāi)封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵涩堤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我分瘾,道長(zhǎng)胎围,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任德召,我火速辦了婚禮唤反,結(jié)果婚禮上纵隔,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好厦章,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著野宜,像睡著了一般乔妈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捆等,一...
    開(kāi)封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天滞造,我揣著相機(jī)與錄音,去河邊找鬼栋烤。 笑死谒养,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的明郭。 我是一名探鬼主播买窟,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼薯定!你這毒婦竟也來(lái)了始绍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤话侄,失蹤者是張志新(化名)和其女友劉穎亏推,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體年堆,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吞杭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了变丧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芽狗。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖痒蓬,靈堂內(nèi)的尸體忽然破棺而出童擎,到底是詐尸還是另有隱情曼月,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布柔昼,位于F島的核電站哑芹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捕透。R本人自食惡果不足惜聪姿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乙嘀。 院中可真熱鬧末购,春花似錦、人聲如沸虎谢。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)婴噩。三九已至擎场,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間几莽,已是汗流浹背迅办。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留章蚣,地道東北人站欺。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像纤垂,于是被迫代替她去往敵國(guó)和親矾策。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容