安装依赖
# nginx版本:1.25.0以上
# boringssl版本:需要go语言1.18.9以上、cmake3.12以上
yum provides */cmake
yum install gcc-c++ libunwind-devel golang cmake;
cd /midware/make
wget https://github.com/Kitware/CMake/releases/download/v3.28.0-rc3/cmake-3.28.0-rc3.tar.gz
tar xvf cmake-3.28.0-rc3.tar.gz
cd cmake-3.28.0-rc3
yum remove cmake -y
./configure --prefix=/usr/local/cmake
make && make install
ln -s /usr/local/cmake/bin/cmake /usr/bin/cmake
vim /etc/profile
export CMAKE_HOME=/usr/local/cmake
export PATH=$PATH:$CMAKE_HOME/bin
source /etc/profile
cmake -version
wget https://boringssl.googlesource.com/boringssl/+archive/refs/heads/master.tar.gz
mkdir -p /midware/make/boringssl
tar xvf master.tar.gz -C boringssl
cd boringssl && mkdir build && cd build && cmake .. && make && cd ../../
yum install gcc gcc-c++ pcre-devel openssl-devel zlib-devel cmake make libunwind-devel hg git wget
./auto/configure --user=www --group=www --prefix=/www/server/nginx --with-pcre --add-module=/root/ngx_brotli --with-http_v2_module --with-stream --with-stream_ssl_module --with-http_ssl_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --with-http_v3_module \
--with-cc-opt=-I../boringssl/include \
--with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto'
./configure
--with-debug
--with-http_v3_module
--with-cc-opt="-I../boringssl/include"
--with-ld-opt="-L../boringssl/build/ssl
-L../boringssl/build/crypto"
http {
log_format quic '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$http3"';
access_log logs/access.log quic;
server {
listen 443 ssl;
listen [::]:443 ssl;
# 用于支持Quic或HTTP/3
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
# 用以支持HTTP/2
http2 on;
# 默认值
http3 on;
# 设置一个连接中并发HTTP/3请求流的最大数量
http3_max_concurrent_streams 128;
# 设置用于读取和写入QUIC流的缓冲区的大小
http3_stream_buffer_size 64k;
# 客户端连接ID的最大数量 可以存储在服务器上
quic_active_connection_id_limit 2;
# QUIC地址验证
quic_retry off;
# 0-RTT
ssl_early_data off;
# 通用分割卸载
quic_gso off;
# 设置各种令牌的主机密钥
# quic_host_key <filename>;
server_name r2wind.cn;
# Quic或HTTP/3响应头,其中如果是
add_header Alt-Svc 'h3=":443"; ma=86400';
# add_header Alt-Svc 'quic=":443"; ma=86400, h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3-30=":443"; ma=86400, h3-31=":443"; ma=86400, h3-32=":443"; ma=86400';
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
location / {
root /www/wwwroot/r2wind.cn;
index index.html index.htm;
}
# 证书配置
ssl_certificate /root/.acme.sh/smb.wiki/fullchain.cer;
ssl_certificate_key /root/.acme.sh/smb.wiki/smb.wiki.key;
ssl_session_timeout 5m;
# http3的SSL必须是TLSv1.3版本
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
}
}
xquic_log "pipe:rollback /home/admin/tengine/logs/tengine-xquic.log baknum=10 maxsize=1G interval=1d adjust=600" info;
http {
## add for xquic ####
xquic_ssl_certificate /etc/tengine/ssl/certificate.crt;
xquic_ssl_certificate_key /etc/tengine/ssl/certificate.key;
xquic_ssl_session_ticket_key /etc/tengine/ssl/session_ticket.key;
xquic_congestion_control bbr;
xquic_socket_rcvbuf 5242880;
xquic_socket_sndbuf 5242880;
xquic_anti_amplification_limit 5;
## end for xquic ####
server {
listen 2443 xquic reuseport;
...
}
}
国密配置
环境与工具准备
- 在gmssl.com网站下载
- 国密版wireshark(重要)
- Tongsuo国密库(替换openssl)
- Tengine(基于Tongsuo编译,替换nginx)
- 国密版curl、wget
编译
准备Tengine源码包、Tongsuo源码包
# (非必要)Tongsuo编译二进制
./config no-devcryptoeng enable-ntls --prefix=/midware/tongsuo && make
# curl编译(非必要) 基于tongsuo二进制
./configure --prefix=/midware/curl --enable-warnging --enable--werror --with-openssl=/midware/tongsuo
# Tengine编译(必要) 基于tongsuo源码
./configure --prefix=/midware/tengine --add-module=modules/ngx_tongsuo_ntls \
--with-openssl=../Tongsuo-8.3.2 \
--with-openssl-opt='enable-ntls' \
--with-http_ssl_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_sni \
--with-http_sub_module
make && make install
groupadd tengine
useradd -g tengine -s /sbin/nologin tengine
chown tengine:tengine /midware/tengine -R
cat >/usr/lib/systemd/system/tengine.service <<EOF
[Unit]
Description=tengine web server
Documentation=http://tengine.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
User=tengine
Group=tengine
Type=forking
PIDFile=/midware/tengine/logs/nginx.pid
ExecStartPre=/usr/bin/rm -f /midware/tengine/logs/nginx.pid
ExecStartPre=/midware/tengine/sbin/nginx -t -c /midware/tengine/conf/nginx.conf
ExecStart=/midware/tengine/sbin/nginx -c /midware/tengine/conf/nginx.conf
ExecReload=/midware/tengine/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start tengine
Tengine国密配置
目前需求是访问普通http端口, 再由网关或中间件做转发到国密的端口; 目前tengine实现方法是监听一个名为http端口8081, 转发到国密的对端端口7051, 信任CA证书 人行给出的加密套件是ECDHE_SM4_CBC_SM3(0xe011)、ECC_SM4_CBC_SM3(0xe013)、ECDHE_SM4_GCM_SM3(0xe051)、ECC_SM4_GCM_SM3(0xe053) Tongsuo的加密套件命名不一致, wireshark抓包显示的加密套件名称也不一致,只要后面的十六进制如(0xe051)一致即可,为ECC-SM2-SM4-CBC-SM3:ECC-SM2-SM4-GCM-SM3:ECDHE-SM2-SM4-CBC-SM3:ECDHE-SM2-SM4-GCM-SM3
# nginx.conf 配置日志格式和转发
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request_method $scheme://$host$request_uri $server_protocol" '
'$status $upstream_status $ssl_protocol $ssl_cipher $body_bytes_sent "$http_referer" "$http_user_agent" '
'"$upstream_response_time $request_time" '
'$http_x_forwarded_for $upstream_addr $ssl_protocol';
access_log /midware/tengine/logs/access.log main;
server {
listen 8081;
server_name localhost test.com;
proxy_connect_timeout 10s;
location / {
proxy_enable_ntls on;
proxy_ssl_ciphers "ECC-SM2-SM4-CBC-SM3:ECC-SM2-SM4-GCM-SM3:ECDHE-SM2-SM4-CBC-SM3:ECDHE-SM2-SM4-GCM-SM3";
proxy_ssl_trusted_certificate certs/ca.pem;
proxy_pass https://xx.com:7051;
# 人行的接口会返回一个指定链接,让客户端重新发起请求,这里把url替换为nginx的8081端口
sub_filter "http://xx.com:7051" "http://localhost:8081";
sub_filter_types *;
}
}
验证与测试
# 抓包测试即可
tcpdump -i any -w cert.out
# 用国密版wireshark打开cert.out
# 其中会由GMSSLv1协议的请求,再Server Hello的报文的Secure Sockets Layer的Handshake Protocol: Server Hello里面的Cipher Suite
# 如果使用了国密则会显示ECC_SM4_SM3(0xe013)等四个算法套件
# 如果需要测试国密客户端访问国密服务端,则需要使用国密版的curl或者wget等工具 类似下面请求即可,开启tlcp
/midware/curl/bin/curl -kv --capath /midware/tengine/conf/cert/ca.pem --tlcp --ciphers "ECC-SM2-SM4-CBC-SM3:ECC-SM2-SM4-GCM-SM3:ECDHE-SM2-SM4-CBC-SM3:ECDHE-SM2-SM4-GCM-SM3:ECDHE-SM2-WITH-SM4-SM3" https://xx.com:7051/cerditreferencetest/index.html
番外:自己对外提供国密端口配置
# 需要配置签名的证书和密钥,加密的证书和密钥,国密证书分为签名和加密证书两部分
server {
listen 443 ssl;
server_name 23.6.2.42;
enable_ntls on;
ssl_certificate certs/test_rsa.crt;
ssl_certificate_key certs/test_rsa.key;
ssl_certificate certs/test_ecc.crt;
ssl_certificate_key certs/test_ecc.key;
ssl_sign_certificate certs/SS.cert.pem;
ssl_sign_certificate_key certs/SS.key.pem;
ssl_enc_certificate certs/SE.cert.pem;
ssl_enc_certificate_key certs/SE.key.pem;
ssl_ciphers "ECC-SM2-SM4-CBC-SM3:ECC-SM2-SM4-GCM-SM3:ECDHE-SM2-SM4-CBC-SM3:ECDHE-SM2-SM4-GCM-SM3";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
location / {
return 200 "success";
}
}
...