0%

背景

Let’s Encrypt提供了3类验证(Challenge)方式,用于颁发证书:

  • HTTP-01:通过HTTP访问服务器80端口的.well-known/acme-challenge验证。
  • DNS-01:在DNS中添加_acme-challenge开头的TXT记录,这种方式因为能签发通配符证书(Wildcard)而被大范围使用。
  • TLS-SNI-01TLS-ALPN-01:通过TLS的方式对443端口访问进行验证。

DNS-01HTTP-01能在极少改动服务器配置的情况下,完成验证。然而,对应某些特殊环境下,80端口难以开放或DNS记录难以更改,只能通过443端口验证。

TLS-SNI-01的漏洞

TLS-SNI-01,顾名思义,是使用SNI进行验证。通过配置特定域名的SNI(例如773c7d.13445a.acme.invalid),生成临时证书进行验证。

然而,对于共享同一个IP的虚拟主机,一旦没有上传证书的SNI验证,攻击者就能轻而易举通过指向同一IP的域名的证书颁发验证。

因此,Let’s Encrypt在2018.1.9收到报告停止了新证书颁发。2019.2.13,TLS-SNI-01验证将被终止

替代

TLS-SNI-02和TLS-SNI-01具有同样的问题,TLS-SNI-03还在开发中,TLS-SNI验证短期内难以再次使用。

TLS-ALPN-01给出了一种替代。ALPN(应用层协议协商),是在HTTP/2中被引入、通过HTTPS进行协议协商的机制。TLS-ALPN-01利用了这个机制,将协议设为acme-tls进行验证。这避免了SNI的问题。2018.7.13,TLS-ALPN-01可用于Let’s Encrypt生产环境验证。

然而,根据讨论可以看出,TLS-ALPN-01支持的客户端非常少。对于提供自动HTTPS加密的Caddy,TLS-ALPN-01支持依旧未能合并。因此,下面我将谈谈的Nginx方案。

原理

Nginx不仅是HTTP/HTTPS服务器,跟提供了全面的TLS、UDP甚至是邮件协议支持。

Nginx的ngx_stream_ssl_preread_module模块提供了ClientHello访问。通过$ssl_preread_alpn_protocols变量,即可实现不同协议的分流。

配置

使用包含ngx_stream_ssl_preread_module的Nginx官方源安装Nginx。

参考dehydrated的TLS-ALPN-01配置

  1. 配置nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
stream {
tcp_nodelay on;
map $ssl_preread_alpn_protocols $tls_addr {
~\bacme-tls/1\b 127.0.0.1:10443; # TLS-ALPN-01验证服务的地址
default 127.0.0.1:8443; # HTTPS服务地址,此处以本机8443为例
}
server {
listen 443;
listen [::]:443;
proxy_pass $tls_addr; # 使用对应变量进行访问
proxy_protocol on; # 开启PROXY protocol,见后文
ssl_preread on;
}
}
  1. 安装dehydrated并配置
1
2
3
4
5
6
wget -O /usr/sbin/dehydrated -c https://raw.githubusercontent.com/lukas2511/dehydrated/master/dehydrated
chmod +x /usr/sbin/dehydrated

wget -O /etc/dehydrated/config -c https://github.com/lukas2511/dehydrated/raw/master/docs/examples/config
wget -O /etc/dehydrated/domains.txt -c https://github.com/lukas2511/dehydrated/raw/master/docs/examples/domains.txt
wget -O /etc/dehydrated/hook.sh -c https://github.com/lukas2511/dehydrated/raw/master/docs/examples/hook.sh

config修改如下参数

1
2
CHALLENGETYPE="tls-alpn-01"
HOOK="${BASEDIR}/hook.sh"

修改domains.txt中为所需域名。

  1. 配置Python验证服务

页面上的Example responder保存到/etc/dehydrated/tls.py

值得注意的是,FALLBACK的两个参数中的ssl-snakeoil证书是由ssl-cert这一包生成的,可以安装其来生成或自行处理。

接着,将其配置为服务tls-alpn.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=Python responder for tls-alpn-01

[Service]
Restart=on-abnormal

; User and group the process will run as.
User=root
Group=root

; 使用本机的Python3地址
ExecStart=python3 /etc/dehydrated/tls.py
ExecReload=/bin/kill -USR1 $MAINPID

[Install]
WantedBy=multi-user.target
  1. 配置钩子(hook)实现自动化

修改hook.sh中的以下函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
deploy_challenge() {
local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"

systemctl start tls-alpn
}

clean_challenge() {
local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}"

systemctl stop tls-alpn
}

deploy_cert() {
local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"

cp "${KEYFILE}" "${FULLCHAINFILE}" /etc/nginx/ssl/; chown -R nginx: /etc/nginx/ssl
systemctl reload nginx
}

/usr/sbin/dehydrated -c放入cron中定时运行即可实现自动更新证书。

  1. 进行证书获取
1
2
dehydrated --register --accept-terms
dehydrated -c
  1. 配置证书
1
2
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
  1. 配置PROXY protocol以实现客户端IP获取

Haproxy提出的PROXY protocol能实现TLS的客户端IP等信息的安全传递。

在http的server中,修改下列配置:

1
2
3
4
5
6
7
# 启用proxy_protocol监听
listen 8443 ssl http2 proxy_protocol;

# 记录proxy_protocol_addr变量
log_format main '$proxy_protocol_addr ( $remote_addr ) - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

结语

certbot从v0.26.0开始,进行了不完整支持,同上面类似,需要搭配cme-alpn-proxy等服务端食用。

但是这种使用ssl_preread分流的做法,需要PROXY protocol才能接近原效果,也只有为数不多的Web服务器支持。希望Caddy能早日集成TLS-ALPN-01支持。

作为有着N次丢失数据惨痛经历的萌新,选择一个良好的备份方案是最吼的。备份到哪?在云上是较为便捷的。但普通云存储的价格比较昂贵。这里,要说的是归档存储这种专门为长期备份准备的服务。具体地,本文描述AWS S3中Amazon Glacier 存储、Google Cloud Storage中的Coldline和Azure Storage中的Archive和国内的阿里云、腾讯云。

AWS S3

虽然Amazon Glacier有着单独的产品存在,但其需要自行维护目录列表等信息,较为不便,所以我偏向于使用生命周期来转存(每个对象需8KB存储元数据的标准存储)。

存储在区域内至少三个可用区 (AZ) 中的多个设备上,99.999999999%(11个9) 持久性。

  • 价格 0.004-0.005 USD/GB 每月

  • 至少存储 90 天

  • 标准检索 0.01 USD/GB 每月10GB免费 1-3h

  • 加急检索 0.03 USD/GB 1-5min

  • 批量检索 0.0025 USD/GB 5-12h

  • 传出 0.09 USD/GB 每月1GB免费

  • 使用Transfer Acceleration加速 0.04 USD/GB

AWS基本上所有区域都提供Glacier。Ping值的话亚洲和美洲差不多(

Google Cloud Storage

有趣的是,在G家的对比图上,将Coldline放在了GlacierS3 IA之间,让我们看看吧。

在单个“区域”(如us-west1)内。99.9% 每月正常运行时间,99.999999999%(11个9) 耐久性。

  • 价格 0.007-0.014 USD/GB 每月

  • 至少存储 90 天

  • 检索 0.05 USD/GB 亚秒级

  • 传出 0.12 USD/GB 0.23 USD/GB(中国) 每月1GB免费

G家提供亚秒级检索是一大特色,但价格相对昂贵。值得注意的是Nearline提供了0.01-0.02 USD/GB,30天,0.01 USD/GB检索。

G家基本上都是走HK的,所以延迟是有一定保证的。

Azure Storage

Azure提供了非常细致的区域控制。对于,提供本地冗余存储 (LRS)、异地冗余存储 (GRS)、读取访问异地冗余存储 (RA-GRS)三种选项。“本地”指单个数据中心。具体的“异地”配对区域查看这里。遇到问题时,GRS需要等待Microsoft修改DNS,而RA-GRS可以手动选择异地进行读取。

LRS为99.999999999%(11个9),GRS为99.99999999999999%(16个9)

  • LRS价格 0.002-0.003 USD/GB 每月

  • (RA-)GRS价格 0.004-0.0055 USD/GB 每月

  • 至少存储 180

  • 检索 0.02 USD/GB maybe 15h

  • 传出 0.087 USD/GB 0.12 USD/GB(亚洲的区域) 每月5GB免费

目前,Archive在美洲、欧洲和印度的区域可用。虽然都从HK走MSN,但速度堪忧。经测试发现,美洲向的普遍比较缓慢。印度南部、印度西部、欧洲北部的速度较佳。而美洲的节点大多在100KB/S左右。

阿里云 归档存储

阿里云归档存储并入在对象存储OSS中。

“多重冗余备份”,99.999999999%(11个9) 持久性。

  • 价格 0.033 CNY/GB 每月

  • 至少存储 60 天

  • 检索 0.06 CNY/GB

  • 传出 0.25/0.50 CNY/GB

和AWS价格差不多emmm。

99元1TB3年,有了飞机还用什么自行车

腾讯云 归档存储

这里我选择腾讯云对象存储COS的归档存储。

“通过硬盘、主机、机架、集群等各个层面的容灾策略”,99.999999999%(11个9) 持久性。

  • 价格 0.033 CNY/GB 每月

  • 至少存储 60 天

  • 检索 0.2/0.06/0.016 CNY/GB

  • 传出 0.5 CNY/GB

从坏处想,不敢用。从好处想,操作emmm应该规范了吧。

总结

Azure的价格最便宜,与AWS价格相近却还提供异地冗余,但取回极慢,只有若干区域网络速度较好。

GCP的价格最贵,没有提供可用区冗余,但取回超快和网络有一定保障。

AWS的价格适中,提供可用区冗余。

国内的两家价格和AWS类似,但具体冗余方法不明。

莫非要用咖喱味的归档???

自从设了三节点MongoDB副本集、运行一段时间后,服务却常常炸裂、动不动地就换主。于是乎就scale咯。Scale后发现一台机器的MongoDB经常无故重启,机器也反应超慢。

top图

如图所示。。。wa高得可怕(,I/O炸得腻害。肿么办呢?那就照着文档调优咯。

配置环境

  • 使用官方、最新、文档的软件包
  • 尽可能使用SSD
  • 使用EXT4、XFS,对于WiredTiger存储引擎尽可能使用XFS
  • 如使用NFS,配置bg,nolock,noatime
  • 数据存储卷上noatime,不记录访问时间
  • 配置交换空间

禁用Transparent Huge Pages

参见Disable Transparent Huge Pages

sysctl配置

禁用 zone reclaim

vm.zone_reclaim_mode=0

Swappiness

“Swappiness”是一种Linux内核设置,它在需要分配交换时会影响虚拟内存的管理,范围从0至100。越大越积极存进硬盘。

于是我们。。。

vm.swappiness=1

ulimit

合适的ulimit有利于mongod的运行。

1
2
3
4
5
6
7
ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -l unlimited
ulimit -n 64000
ulimit -m unlimited
ulimit -u 64000