在
不久前CloudFlare正式为CDN全面启用了ECH(Encrypted Client Hello)功能,搭配DoH可以实现加密真实的SNI(Server Name Indication),而明文显示Public Name。目前Nginx官方并没有推出ECH功能测试,但是openssl已经为ech添加了新的branch,ECH标准或不久将写入RFC中。
sftcd为nginx和openssl添加了ECH测试功能,貌似它的nginx/ECH-experimental只能搭配他的openssl/ECH-draft-13c
sudo apt update sudo apt install -y build-essential ca-certificates zlib1g-dev libpcre3 libpcre3-dev tar unzip libssl-dev wget git cmake mercurial libunwind-dev pkg-config git clone https://github.com/sftcd/openssl.git git clone https://github.com/sftcd/nginx.git cd openssl git checkout ECH-draft-13c cd ../nginx git checkout ECH-experimental ./auto/configure --with-debug --prefix=/opt/ech --with-http_ssl_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-openssl=./openssl --with-openssl-opt="--debug '-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)'" --with-http_v2_module make && make install
这里的配置仅用于测试ECH。然后我们需要生成一个ech公私钥对,放入指定的文件夹(由ssl_echkeydir定义)中,文件名随意,-public_name 为外层不加密的SNI,你可以自由选择
mkdir /opt/ech/conf/ech_keys ../openssl/.openssl/bin/openssl ech -public_name cloudflare-ech.com -pemout /opt/ech/conf/ech_keys/config.ech ../openssl/.openssl/bin/openssl ech -pemin /opt/ech/conf/ech_keys/config.ech #查看相关信息 tail -2 /opt/ech/conf/ech_keys/config.ech | head -1
这样我们就得到了base64编码后的ECH公钥,然后需要将这个公钥添加到域名https记录,格式如下
1 . alpn="h2" ech=公钥填在这里
如果你使用bind9自建域名解析服务器,那么你可以使用nsupdate添加https记录,注意如果网站不在443端口上会导致ECH异常,这里的https记录默认为443端口!
nsupdate -l -k /var/cache/bind/acme.key > zone domain.com > update add domain.com. 300 HTTPS 1 . alpn="h2" ech=公钥填在这里 > send > quit
以下为nginx配置(/opt/ech/conf/nginx.conf)http部分参考,当然你需要对应的证书,参考使用acme.sh签发证书
http {
include mime.types;
default_type application/octet-stream;
ssl_echkeydir ech_keys;
sendfile on;
keepalive_timeout 65;
server {
listen 443 ssl default_server;
http2 on;
ssl_reject_handshake on;
}
server {
listen 443 ssl;
server_name ech.domain.com;
#http2 on;
ssl_certificate cert/ech.domain.com.cer;
ssl_certificate_key cert/ech.domain.com.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
ssi on;
index index.html index.htm;
keepalive_timeout 0;
# Force non-cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache';
if_modified_since off;
expires off;
etag off;
}
}
}
改写html/index.html
<!DOCTYPE html>
<html>
<head>
<title>ECH test!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<pre>
HTTP host: <!--# echo var="http_host" -->
ALPN protocol: <!--# echo var="ssl_alpn_protocol" -->
SSL cipher: <!--# echo var="ssl_cipher" -->
SSL protocol: <!--# echo var="ssl_protocol" -->
SNI: <!--# echo var="ssl_server_name" -->
ECH status: <!--# echo var="ssl_ech_status" -->
Outer SNI (public name): <!--# echo var="ssl_ech_outer_sni" -->
Inner SNI: <!--# echo var="ssl_ech_inner_sni" -->
</pre>
</body>
</html>
使用编译好的启用ECH功能的Curl或浏览器进行测试
curl -vv --ech true --doh-url https://doh.opendns.com/dns-query https://ech.domain.com ··· ECH status: success #代表ECH功能正常 ···
参考: