說明:以下腳本在Ubuntu 18.04運行通過,大部分腳本執(zhí)行需要管理員權(quán)限仑鸥。
1. 準(zhǔn)備docker環(huán)境
# 安裝必備工具包
apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# 添加docker阿里云源僵芹,相對官方源速度更快
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# 安裝最新版社區(qū)版docker
apt update -y
apt install -y docker-ce
# 如果想要安裝指定版本的docker-ce,如下:
# 查看有哪些版本
apt-cache madison docker-ce
# 安裝指定版本
apt install -y docker-ce=[版本]
# 設(shè)置阿里云docker源
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://uon07it7.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
# 下載安裝docker-compose
curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
2. Let's Encrypt免費證書簽發(fā)過程簡介
Let's Encrypt免費證書簽發(fā)過程包含以下三個階段:
- 在本地服務(wù)器上安裝
Certbot
膛壹,Certbot
是簽發(fā)/更新證書的客戶端程序涡拘; - 運行
Certbot
獲取SSL/TLS
證書嚼锄,證書有效期為3個月
诞外; - 設(shè)置定時腳本每周運行一次
Certbot
更新證書。如果證書有效期小于30天灾票,Certbot
會更新證書;
3. Certbot工作原理簡介
不論是第一次申請證書茫虽,還是更新證書刊苍,Certbot
都會發(fā)起一次ACME請求既们,來驗證你是否擁有該域名。如果驗證通過正什,Certbot
就會將新證書安裝到本地服務(wù)啥纸,其實就是將證書保存在一個目錄中。證書一般包含兩個文件(包含公鑰婴氮、私鑰以及證書等信息)斯棒,web服務(wù)器需要配置使用這兩個證書文件,來實現(xiàn)HTTPS訪問主经。
ACME
驗證過程如下:
- 假設(shè)你有一個域名:example.com荣暮,和一個公網(wǎng)IP:xxx.xxx.xxx.xxx,并設(shè)置好了DNS解析罩驻;
- 配置好一臺web服務(wù)器穗酥,在80端口和443端口接受examle.com的請求;
-
Certbot
向Let's Encrypt
發(fā)起證書申請惠遏; -
Let's Encrypt
返回Certbot
一個唯一的token
砾跃; -
Certbot
配置web服務(wù)器,使token
可以通過url:http://example.com/.well-known/acme-challenge/{token}
訪問节吮; -
Let's Encrypt CA
訪問上述url抽高,如果獲取到的token
和它發(fā)送給Certbot
的token
一致,就可以證明你擁有該域名透绩;
注意:
Certbot
需要配置web服務(wù)器的相應(yīng)權(quán)限翘骂。以nginx為例,Certbot
需要權(quán)限將token
寫入.well-known/acme-challenge
目錄渺贤。
4. 通過docker來運行Certbot
為了方便維護雏胃、升級,推薦使用docker來運行Certbot
志鞍。整個過程可以分為兩部分:首次申請證書和更新證書瞭亮。
4.1 首次申請證書
- 創(chuàng)建web服務(wù)目錄:
mkdir -p /letsencrypt/site
。這里以靜態(tài)網(wǎng)頁為例固棚,也可以設(shè)為反向代理统翩。 - 創(chuàng)建docker-compose文件:
nano /letsencrypt/docker-compose.yml
version: '3.1'
services:
demo-site:
container_name: 'demo-site'
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./site:/usr/share/nginx/html
networks:
- docker-network
networks:
docker-network:
driver: bridge
- 創(chuàng)建nginx配置文件:
nano /letsencrypt/nginx.conf
server {
listen 80;
server_name example.com www.example.com;
location ~ /.well-known/acme-challenge {
allow all;
root /usr/share/nginx/html;
}
root /usr/share/nginx/html;
index index.html;
}
- 啟動web服務(wù)器:
cd /letsencrypt && docker-compose up -d
- 運行
Certbot
申請證書
docker run --rm -it \
-v /letsencrypt/certbot/etc/letsencrypt:/etc/letsencrypt \ # 證書申請工作目錄
-v /letsencrypt/certbot/var/log/letsencrypt:/var/log/letsencrypt \ # 日志記錄
-v /letsencrypt/site:/data/letsencrypt \ # ACME驗證token目錄,與nginx服務(wù)器共享
certbot/certbot \
certonly --webroot \ # 指定ACME驗證方式:token文件驗證
--email youremail@domain.com --agree-tos --no-eff-email \ # 申請者郵件
--webroot-path=/data/letsencrypt \ # ACME驗證token文件放置目錄
-d example.com -d www.example.com # 指定要申請證書的域名列表
如果腳本正常運行此洲,可以在
/letsencrypt/certbot/etc/letsencrypt/live
下找到example.com
文件夾厂汗,其中包含申請成功的證書文件:fullchain.pem
和privkey.pem
。
- 停止web服務(wù)器:
cd /letsencrypt && docker-compose down
- 更新docker-compose配置
version: '3.1'
services:
demo-site:
container_name: 'demo-site'
image: nginx:alpine
ports:
- "80:80" # 保留80端口呜师,用于證書更新
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./site:/usr/share/nginx/html
- ./certbot/etc/letsencrypt/live:/letsencrypt/live # 當(dāng)前證書目錄
- ./certbot/etc/letsencrypt/archive:/letsencrypt/archive # 歷史證書目錄
- ./dhparam-2048.pem:/letsencrypt/dhparam-2048.pem # 使用2048位DH(Diffie-Hellman)參數(shù)
networks:
- docker-network
networks:
docker-network:
driver: bridge
生成2048位的DH參數(shù)文件命令如下:
openssl dhparam -out /letsencrypt/dhparam-2048.pem 2048
live目錄的證書會soft link到archive目錄娶桦,而docker對soft link支持不好,因此需要同時映射live和archive目錄。
- 更新nginx配置衷畦,啟用HTTPS
處理http:
server {
listen 80;
server_name example.com www.example.com;
# 重定向到https
location / {
rewrite ^ https://$host$request_uri? permanent;
}
# 高優(yōu)先級栗涂,僅用于更新證書
location ~ /.well-known/acme-challenge {
allow all;
root /data/letsencrypt;
}
}
處理https:
server {
listen 443 ssl http2;
server_name example.com www.example.com;
server_tokens off;
ssl on;
ssl_certificate /letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /letsencrypt/live/example.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /letsencrypt/dhparam-2048.pem; # 使用2048位DH參數(shù),加強安全
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
root /usr/share/nginx/html;
index index.html;
}
DH以及OCSP內(nèi)容請參考:Strong SSL Security On nginx
- 重新啟動web服務(wù)器:
cd /letsencrypt && docker-compose up -d
4.2 更新證書
- 設(shè)置更新腳本
touch /letsencrypt/renew.sh && chmod +x /letsencrypt/renew.sh
nano /letsencrypt/renew.sh
renew.sh腳本內(nèi)容如下:
#!/bin/bash
docker run -it --rm \
-v /letsencrypt/certbot/etc/letsencrypt:/etc/letsencrypt \
-v /letsencrypt/certbot/var/lib/letsencrypt:/var/lib/letsencrypt \
-v /letsencrypt/certbot/var/log/letsencrypt:/var/log/letsencrypt \
-v /letsencrypt/site:/data/letsencrypt \
certbot/certbot \
renew --webroot -w /data/letsencrypt --quiet && docker kill --signal=HUP demo-site
最后一行腳本說明:在更新完證書后祈争,通知nginx重新加載配置斤程。
- 設(shè)置定時任務(wù)
通過crontab設(shè)置定時任務(wù):
crontab -e
添加一行,每周執(zhí)行一次更新腳本:
0 1 * * 0 /letsencrypt/renew.sh
5. 安全加強
可以通過ssllabs.com驗證證書菩混,如果按照上述配置忿墅,應(yīng)該可以獲得A+
評價。
當(dāng)然沮峡,還可以進一步通過securityheaders.io校驗網(wǎng)站安全性疚脐,對于nginx可以添加以下配置:
server {
# ....
location / {
#security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
#CSP
add_header Content-Security-Policy "frame-src 'self'; default-src 'self'; script-src 'self' 'unsafe-inline' https://maxcdn.bootstrapcdn.com https://ajax.googleapis.com; img-src 'self'; style-src 'self' https://maxcdn.bootstrapcdn.com; font-src 'self' data: https://maxcdn.bootstrapcdn.com; form-action 'self'; upgrade-insecure-requests;" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
# ....
}
6. 小結(jié)
本文參考How to Set Up Free SSL Certificates from Let's Encrypt using Docker and Nginx,對Docker環(huán)境下如何使用Let's Encrypt自動獲取/更新SSL證書做了一個簡明攻略帖烘。
如果你正在使用K8S亮曹,ingress nginx和traefik都對let‘s encrypt
提供了很好的支持,配合helm來安裝部署秘症,也更為簡單方便照卦。