Rust TLS自动证书管理库rustls-acme的使用,支持ACME协议自动化HTTPS证书签发与续期

以下是关于Rust TLS自动证书管理库rustls-acme的使用介绍,支持ACME协议自动化HTTPS证书签发与续期:

许可证

rustls-acme采用双许可证:

  • Apache License 2.0
  • MIT license

贡献者提交的代码默认会按上述双许可证授权。

安装方式

在项目目录中运行:

cargo add rustls-acme

或在Cargo.toml中添加:

rustls-acme = "0.14.0"

完整示例

以下是一个使用rustls-acme自动管理TLS证书的完整示例:

use rustls_acme::{AcmeConfig, caches::DirCache};
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() {
    // 创建ACME配置
    let mut acme = AcmeConfig::new(["example.com"])
        .contact(["mailto:admin@example.com"])
        .cache(DirCache::new("./cache"))
        .directory_lets_encrypt(true)  // 使用Let's Encrypt生产环境
        .state_path("./state")
        .await;

    // 获取TLS配置
    let tls_config = acme.tls_config();
    
    // 创建TCP监听
    let listener = tokio::net::TcpListener::bind("0.0.0.0:443").await.unwrap();
    
    // 接受和处理连接
    loop {
        let (mut stream, _) = listener.accept().await.unwrap();
        let tls_config = tls_config.clone();
        
        tokio::spawn(async move {
            // 建立TLS连接
            let mut tls_stream = tokio_rustls::TlsServer::new(stream, tls_config).await.unwrap();
            
            // 处理HTTP请求
            let mut buf = [0; 1024];
            let n = tls_stream.read(&mut buf).await.unwrap();
            let req = String::from_utf8_lossy(&buf[..n]);
            
            // 发送响应
            let resp = "HTTP/1.1 200 OK\r\n\r\nHello ACME!";
            tls_stream.write_all(resp.as_bytes()).await.unwrap();
        });
    }
}

功能说明

  1. 自动获取和续期Let’s Encrypt证书
  2. 支持多域名配置
  3. 提供本地缓存功能
  4. 内置TLS服务器配置

注意事项

  1. 需要开放80端口用于ACME验证
  2. 生产环境应确保state目录持久化
  3. 首次运行可能需要几分钟获取初始证书

这个库特别适合需要自动化TLS证书管理的Rust网络服务,如HTTP服务器、gRPC服务等。


1 回复

Rust TLS自动证书管理库rustls-acme的使用

简介

rustls-acme是一个基于Rust语言的库,实现了ACME协议(如Let’s Encrypt使用的协议)的客户端功能,用于自动化HTTPS证书的签发和续期。它集成了rustls TLS库,可以方便地为Rust网络服务添加自动化的HTTPS证书管理功能。

主要特性

  • 支持ACME v2协议(兼容Let’s Encrypt)
  • 自动证书签发和续期
  • 零配置使用默认证书颁发机构
  • 与rustls无缝集成
  • 支持HTTP-01和TLS-ALPN-01挑战验证方式
  • 内置小型HTTP服务器用于挑战响应

完整示例代码

以下是基于内容中提供的示例代码的完整演示demo:

use rustls_acme::caches::DirCache;
use rustls_acme::AcmeConfig;
use std::net::Ipv4Addr;
use std::path::PathBuf;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio_stream::StreamExt;

#[tokio::main]
async fn main() {
    // 配置ACME,使用example.com域名
    let mut state = AcmeConfig::new(["example.com"])
        .contact(["mailto:admin@example.com"]) // 设置联系邮箱
        .cache(DirCache::new(PathBuf::from("/tmp/rustls-acme-cache"))) // 使用临时目录存储证书
        .directory_lets_encrypt(true) // 使用Let's Encrypt生产环境
        .state();

    // 创建Tokio异步任务处理ACME事件
    tokio::spawn(async move {
        while let Some(event) = state.next().await {
            match event {
                Ok(event) => println!("ACME事件: {:?}", event),
                Err(err) => eprintln!("ACME错误: {:?}", err),
            }
        }
    });

    // 获取TLS acceptor
    let acceptor = state.acceptor();
    
    // 绑定443端口
    let listener = tokio::net::TcpListener::bind((Ipv4Addr::UNSPECIFIED, 443)).await.unwrap();
    println!("服务器已启动,监听443端口...");

    // 接受并处理连接
    while let Ok((stream, _)) = listener.accept().await {
        let acceptor = acceptor.clone();
        
        tokio::spawn(async move {
            // 进行TLS握手
            match acceptor.accept(stream).await {
                Ok(mut tls_stream) => {
                    // 简单的HTTP响应
                    let response = b"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello, TLS!";
                    tls_stream.write_all(response).await.unwrap();
                }
                Err(err) => {
                    eprintln!("TLS握手失败: {:?}", err);
                }
            }
        });
    }
}

配置说明

  1. Cargo.toml依赖:
[dependencies]
rustls-acme = "0.8"
tokio = { version = "1", features = ["full"] }
tokio-rustls = "0.23"
async-trait = "0.1"  # 如果需要自定义缓存实现
  1. 生产环境注意事项:
  • 确保域名已正确解析到服务器IP
  • 确保服务器80和443端口可被外部访问
  • 建议使用持久化存储而不是临时目录存储证书
  • 监控证书续期事件,确保续期成功
  1. 自定义配置:
// 多个域名配置
AcmeConfig::new(["example.com", "www.example.com", "api.example.com"])

// 使用自定义ACME服务器
.directory_url("https://acme-staging-v02.api.letsencrypt.org/directory")

// 只使用HTTP-01挑战验证
.http01_challenge()

高级用法示例

自定义HTTP处理器

use rustls_acme::futures_rustls::server::TlsStream;
use std::sync::Arc;

async fn handle_client(mut stream: TlsStream<tokio::net::TcpStream>) {
    let mut buf = [0u8; 1024];
    match stream.read(&mut buf).await {
        Ok(n) if n > 0 => {
            let request = String::from_utf8_lossy(&buf[..n]);
            println!("收到请求:\n{}", request);
            
            let response = "HTTP/1.1 200 OK\r\n\r\nHello from secure server!";
            stream.write_all(response.as_bytes()).await.unwrap();
        }
        _ => eprintln!("读取客户端数据失败"),
    }
}

#[tokio::main]
async fn main() {
    let tls_acceptor = AcmeConfig::new(["example.com"])
        .state()
        .acceptor();
    
    let listener = tokio::net::TcpListener::bind("0.0.0.0:443").await.unwrap();
    
    while let Ok((tcp_stream, _)) = listener.accept().await {
        let tls_acceptor = tls_acceptor.clone();
        tokio::spawn(async move {
            match tls_acceptor.accept(tcp_stream).await {
                Ok(tls_stream) => handle_client(tls_stream).await,
                Err(err) => eprintln!("TLS握手失败: {:?}", err),
            }
        });
    }
}

总结

rustls-acme通过自动化证书管理简化了Rust应用的HTTPS部署,开发者只需关注业务逻辑而无需手动管理证书。该库支持Let’s Encrypt等ACME协议证书颁发机构,提供了灵活的配置选项和扩展接口,是构建安全网络服务的理想选择。

回到顶部