Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践

0
0

本文使用 HTTP 和 DNS 两种校验方式对 Docker 下 linuxserver/letsencrypt 项目进行了实践。生成SpringBoot可用证书,使用 Nginx 的 htpasswd 来对网站进行密码保护,并测试使用 fail2ban 防止 htpasswd 被暴力破解。全文基于 linuxserver/letsencrypt 文档及其他官方资料,根据作者实践进行详细解析和记录。

1. 介绍 1.0 linuxserver/letsencrypt

这个容器设置了一个 Nginx 服务器,支持 php 的反向代理和一个内置的 letsencrypt 客户端,可以自动化生成或更新 SSL 服务器证书。它还包含用于防御入侵的 fail2ban。

1.1 使用 docker create \
--cap-add=NET_ADMIN \
--name=letsencrypt \
-v <path to data>:/config \
-e PGID=<gid> -e PUID=<uid> \
-e EMAIL=<email> \
-e URL=<url> \
-e SUBDOMAINS=<subdomains> \
-e VALIDATION=<method> \
-p 80:80 -p 443:443 \
-e TZ=<timezone> \
linuxserver/letsencrypt 1.2 参数 cap-add=NET_ADMIN cap-add:即 Add Linux capabilities 添加 Linux 内核能力。这里具体添加的能力是允许执行网络管理任务。这是因为 fail2ban 需要修改 iptables -p 80 -p 443:端口 -v /config:包括 webroot 在内的所有配置文件都保存在此处 -e URL:顶级域名(完全拥有则如:“customdomain.com”,动态 DNS 则如 “customsubdomain.ddnsprovider.com” ) -e SUBDOMAINS:证书覆盖的子域名 (逗号分隔,无空格) .如 www,ftp,cloud.对于通配符证书, 请将此明确地设置为通配符 (通配符证书只允许通过dns方式验证) -e VALIDATION:letsencrypt验证方法,选项是 http、tls-sni 或者 DNS 不同校验方式的区别: HTTP 校验 :需要使用到80端口,故宿主机80端口应该转发到容器的80端口 tls-sni 校验 :需要使用到443端口,故宿主机443端口应该转发到容器的443端口(注意:由于安全漏洞,letsencrypt 禁用了 tls-sni 验证,使用该方式会报错: Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA ) DNS 验证 :需要设置 DNSPLUGIN 变量(不是所有的DNS服务商都支持),并且需要在 /config/dns-conf 文件夹下输入凭据到相应的 ini 文件里,当无法通过端口验证时可使用这种方法验证 -e PGID 设置 GroupID -e PUID 设置 UserID -e TZ - 时区 如America/New_York:上海时区为Asia/Shanghai

通过指定用户ID和所属群的ID来避免数据卷挂载( -v )时容器和宿主机直接可能产生的权限问题。最好让挂载的数据卷目录的拥有者和指定的用户统一。

另外,需要注意:不能指定root用户(即PGID=0,PUID=0),否则会一直报错(但不影响使用)。

#宿主机root用户环境下使用例子(非官方,仅供参考)
#创建要挂载的目录,此时该目录属root用户和root组
mkdir /opt/letsencrypt
#创建docker用户(默认会顺带新建同名Group)
useradd dockeruser
#修改文件夹归属(R代表递归操作,文件夹下的也一并修改)
chown -R dockeruser:dockeruser /opt/letsencrypt
#查看dockeruser的用户id和群id
id dockeruser

可选设置:

-e DNSPLUGIN:如果 VALIDATION 设置为 DNS 则此项必选。选项有 cloudflare、cloudxns、digitalocean、dnsimple、dnsmadeeasy、google、luadns、nsone、rfc2136 和 route53。还需要在 /config/dns-conf 文件夹下输入凭据到相应的 ini 文件里。这里推荐使用 cloudflare,免费而且好用. 使用 Cloudflare 服务的话应确保设置为 dns only 而非 dns + proxy(事实上 Cloudflare 的 proxy 已经提供免费自动 SSL 服务了,也就没有本文的必要) Google DNS 插件的使用对象是企业付费产品“Google Cloud DNS”而非“Google Domains DNS” -e EMAIL:您的证书注册和通知的电子邮件地址 -e DHLEVEL:dhparams 位值(默认值= 2048,可设置为1024或4096) -p 80:VALIDATION设置为 http 而不是 dns 或 tls-sni 时需要80端口进行转发 -e ONLY_SUBDOMAINS:仅为子域名获取证书(主域名可能托管在另外一台计算机且无法验证)时请将此项设置为 true -e EXTRA_DOMAINS:额外的完全限定域名(逗号分隔,无空格)如 extradomain.com,subdomain.anotherdomain.org -e STAGING:设置为 true 可以提高速率限制,但证书不会通过浏览器的安全测试,仅用于测试 -e HTTPVAL:已弃用, 请用VALIDATION 代替 2. 实践 2.1 使用 HTTP 方式验证

首先,你应该先保证要获取证书的域名(子域名)能正确地访问到主机。注意:域名需要备案。

这里我映射的宿主机目录为 /opt/letsencrypt1 ,PGID 和 PUID 由上文提到的方式获得。配置的域名为 my.com 和 www.my.com (实际上我配置的是另外一个我自己真正拥有的域名,这里不贴出来)

注意:使用 HTTP 方式验证的话开发80端口就可以了,这里443端口也进行映射。这是为了证书获取成功后可以通过使用 HTTPS 登录该容器提供的默认首页进行确认。

docker run -d \
--cap-add=NET_ADMIN \
--name=letsencrypt \
-v /opt/letsencrypt1:/config \
-e PGID=1002 -e PUID=1001 \
-e URL=my.com \
-e SUBDOMAINS=www \
-e VALIDATION=http \
-p 80:80 -p 443:443 \
-e TZ=Asia/Shanghai \
linuxserver/letsencrypt

容器会在后台运行,这个时候应该提供如下指令查看日志输出(CTRL + z退出)

docker logs -f letsencrypt
Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践

最后,我卡在 Cleaning up challenges 这一步。这是因为我域名没有备案,无法通过域名访问到我所在的主机。这个时候打开域名链接被重定向到云主机提供商的网页禁止访问,Let’s encrypt 没办法通过域名访问到本机,所以验证失败(事实上它也没有说失败,只是一直停在那里)。


Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践

毋庸置疑,我是因为这个原因被禁止访问的。

既然 HTTP(80端口)方式验证走不通,tls-sni本来就不行,那就只能用 dns 验证了。

2.2 使用dns方式验证 这里以CloudFlare为例 第一步 完成域名服务器配置

首先,要有一个 cloudflare 账号。然后,在域名提供商那里将域名的 DNS 服务器改成 cloudflare 提供的 DNS 服务器。然后,在cloudflare那里添加对应的解析记录。

注意:解析记录 Status 的图标应该是灰色的,表示 DNS only。如果图标亮了,表示 DNS and HTTP proay(CDN),要使用 let’s encrypt 的 DNS 校验的话就不要再开 HTTP 代理和 CDN 了。开了代理的话 cloudflare 会免费给你提供(及自动维护更新)SSL证书,就可以直接 HTTP 访问了。不需要本文再干嘛了,而且还有免费 CDN,可谓十分良心。


Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践
第二步 完成域名服务器 API-KEY 相关配置并启动

这一步先正常启动,会启动失败但会生成所有的配置文件。再根据相应的 ini 文件里的提示去域名服务器提供商那里找到相对应的凭证,修改 ini 文件,重新启动容器。

启动如下。这次我映射到宿主机目录 /opt/letsencrypt2 下,把 VALIDATION 改为 dns ,增加 DNSPLUGIN 配置为 cloudflare。

docker run -d \
--cap-add=NET_ADMIN \
--name=letsencrypt \
-v /opt/letsencrypt2:/config \
-e PGID=1002 -e PUID=1001 \
-e URL=my.com \
-e SUBDOMAINS=www \
-e VALIDATION=dns \
-e DNSPLUGIN=cloudflare \
-p 80:80 -p 443:443 \
-e TZ=Asia/Shanghai \
linuxserver/letsencrypt

使用 docker logs -f letsencrypt 查看。

这次是在 Cleaning up challenges 之后报错… 错误提示也很明确,是 Unknown X-Auth-Key or X-Auth-Email 的问题,配置是在 /config/dns-conf/cloudflare.ini 这个文件里面。

Cleaning up challenges
Error determining zone_id: 9103 Unknown X-Auth-Key or X-Auth-Email. Please confirm that you have supplied valid Cloudflare API credentials. (Did you enter the correct email address?)
IMPORTANT NOTES:
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
ERROR: Cert does not exist! Please see the validation error above. Make sure you entered correct credentials into the /config/dns-conf/cloudflare.ini file.

打开 /config/dns-conf/cloudflare.ini 可以看到

# Instructions: https://github.com/certbot/certbot/blob/master/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py#L20
# Replace with your values
dns_cloudflare_email = cloudflare@example.com
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567

感兴趣的可以到介绍的页面去查看相关信息,也可以直接到对应域名解析服务提供商那里去看。cloudflare 查看的地址是 https://dash.cloudflare.com/profile ,最上面是 Email,最下面是 API Keys。


Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践
Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践

将对应内容替换到 /config/dns-conf/cloudflare.ini 里面(即宿主机的 /opt/letsencrypt2/dns-conf/cloudflare.ini 里面)。 然后,使用 docker rm -f letsencrypt 强制删掉原容器。 再重新运行上面的 docker run 就可以成功启动了。

查看日志如下:


Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践

最终会停在 Server ready 这一行(如果用 root 用户的 uid 和 gid 的话,现在会一直报错,但仍可使用)。这个时候就可以用 HTTPS 打开了(内置的 Nginx 只监听443端口,所以不能用 HTTP 打开),显示如下界面即为正常。


Docker使用 linuxserver/letsencrypt 生成SSL证书最全解析及实践
3. 设置 3.1 安全和密码保护

可以使用 Nginx 的 htpasswd 来对网站进行密码保护。htpasswd 的相关用法可见 htpasswd命令 。

添加第一个密码访问用户( -c 参数表示创建一个加密文件,如果原来有的话则把原来的删掉) docker exec -it letsencrypt htpasswd -c /config/nginx/.htpasswd <username> 继续添加密码访问用

Viewing all articles
Browse latest Browse all 12749