上一篇 c# ACME client 漏了一部分内容,今天补上

除了之前介绍的在 asp.net core 使用方式,还可以单独在代码中使用client

简化用法

如果已经集成好完全的自动证书申请验证,就可以使用已经封装好的代码进行简单使用

举例在asp.net core提供 一个api 可以根据参数申请证书

starup

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddAcmeChallengeCore(config: c =>
{
c.HttpClientConfig = new VKProxy.Config.HttpClientConfig()
{
DangerousAcceptAnyServerCertificate = true
};
}); var app = builder.Build(); if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseAuthorization(); app.MapControllers(); app.Run();

api

using Microsoft.AspNetCore.Mvc;
using VKProxy.ACME.AspNetCore;
using VKProxy.Core.Extensions; namespace WithApi.Controllers; [ApiController]
[Route("[controller]")]
public class CertController : ControllerBase
{
private readonly IAcmeStateIniter initer; public CertController(IAcmeStateIniter initer)
{
this.initer = initer;
} [HttpGet]
public async Task<string> Get([FromQuery] string domain)
{
// 证书配置
var o = new AcmeChallengeOptions()
{
AllowedChallengeTypes = VKProxy.ACME.AspNetCore.ChallengeType.Http01,
Server = new Uri("https://127.0.0.1:14000/dir"),
DomainNames = new[] { domain },
AdditionalIssuers = new[] { """
-----BEGIN CERTIFICATE-----
MIIDGzCCAgOgAwIBAgIIUPFry5qBu34wDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVUGViYmxlIFJvb3QgQ0EgMjFjNjY3MCAXDTI1MDcyMjAxMTA0OVoYDzIwNTUw
NzIyMDExMDQ5WjAgMR4wHAYDVQQDExVQZWJibGUgUm9vdCBDQSAyMWM2NjcwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxNKa4y93OFYaSx8bcbuWsHHnW
mpfsobK5Elf7GE02mi/cDrMP+wR1l53BuucrW04OyoewkBsJNZoxEy1DkCjxv4+g
Q+HgGCR5R14ex17ZdFxpcl42H8QnRB3IqVBlJiz0JyGZwiaOamOkUTVEYTGDeuxu
PglpvboGeatsWQe0MJJfBN8OxLVUmi6Y/enbzlIdv3tvgQujfPNiS8MLDMBuIiMs
ixhu8YAzUqvVKZoQVK7GwbD9WrVBKub8w86StKFmU14aSXahidt8IENdpLO2OT3J
y1nt25QDsAmtS1/wGnTDPeefLGsM7kGYNesQkSW0w8Um4p9KLWKnKyOvzPZrAgMB
AAGjVzBVMA4GA1UdDwEB/wQEAwIChDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRoXcwo6c5J8jMweiHKPw4OlcWIQzANBgkq
hkiG9w0BAQsFAAOCAQEAad9XT4sN1KserYtCxBKmoPhPAHInHYgG/Z2gd6KqdsK9
biIgEbKo84tClLqA6XCN/yN1bMQL2ZMbWBF8oHv/A5o0atpTpd+Ho+punHYRIpqv
akUX21Zsu6NdAuH7g7m9t9h/lc6tgiqaAf2HwpC3NrXmUlPRqLay7/t+BFQU6dBa
E+qzmL7lHZQf1UArfb+QDYH2XsFCk9Pjv0xdP+PGwf8HqHhfPLctvus5JL+LXp0X
68eWKQCs1CrL8cUMwcELlW/mR1lKnJL1WgM1Bns9ZF1ha6egG539ruzQjItF6MHB
xAEt55nXfs+mjV1p7qrcmR8jIdByR9C36T21r+8pKA==
-----END CERTIFICATE----- """
}
}; // 申请全新account
o.NewAccount(new string[] { "mailto:test11@xxx.com" });
// 执行全套流程
var cert = await initer.CreateCertificateAsync(o);
return cert.ExportPem();
}
}

默认情况下三种验证方式:

http

如在 asp.net core 中使用,默认已经添加了 app.Map("/.well-known/acme-challenge" 路由处理, 如要申请公网上权威认证的证书,请将 /.well-known/acme-challenge 路由暴露在公网让acme服务器可以访问

其次由于默认实现没有持久化和分布式处理验证信息,重启和多实例都会有问题,如有需求可以替换IHttpChallengeResponseStore实现以达到效果

public interface IHttpChallengeResponseStore
{
Task AddChallengeResponseAsync(string token, string keyAuth, CancellationToken cancellationToken); Task<string> GetChallengeResponse(string token, CancellationToken cancellationToken); Task RemoveChallengeResponseAsync(string token, CancellationToken cancellationToken);
}

dns

由于不同服务商有各自的api,所以默认没有实现,该功能其实无效,如需使用,请实现 IDnsChallengeStore

public interface IDnsChallengeStore
{
Task AddTxtRecordAsync(string acmeDomain, string dnsTxt, CancellationToken cancellationToken); Task RemoveTxtRecordAsync(string acmeDomain, string dnsTxt, CancellationToken cancellationToken);
}

tls

个人并不推荐使用tls验证方式,其由于验证自签证书和正式证书都会在 tls 层,运行时不停机重新申请对于tls管理还是有些挑战的

如想尝试可以实现ITlsAlpnChallengeStore (默认在 asp.net core 的实现并不能支持过滤验证自签证书只用于acme服务器请求)

public interface ITlsAlpnChallengeStore
{
Task AddChallengeAsync(string domainName, X509Certificate2 cert, CancellationToken cancellationToken); Task RemoveChallengeAsync(string domainName, X509Certificate2 cert, CancellationToken cancellationToken);
}

底层 client

如需直接使用原始 acme 协议client,可参考如下

starup

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); builder.Services.AddACME(c =>
{
c.HttpClientConfig = new VKProxy.Config.HttpClientConfig()
{
DangerousAcceptAnyServerCertificate = true
};
});

use

var context = services.BuildServiceProvider().GetRequiredService<IAcmeContext>();

await context.InitAsync(new Uri("https://127.0.0.1:14000/dir"), cancellationToken);

var account = await context.NewAccountAsync(new string[] { "mailto:xxx@xxx.com" }, true, KeyAlgorithm.RS256.NewKey());

var order = await context.NewOrderAsync(new string[] { "test.com" });
var aus = order.GetAuthorizationsAsync().ToBlockingEnumerable().ToArray();
var a = aus.First();
var b = await a.HttpAsync();
var c = await b.ValidateAsync(); Key privateKey = KeyAlgorithm.RS256.NewKey();
var csrInfo = new CsrInfo
{
CommonName = "test.com",
};
order = await context.FinalizeAsync(csr, key, cancellationToken);
var acmeCert = await order.DownloadAsync(); var pfxBuilder = acmeCert.ToPfx(privateKey);
if (!string.IsNullOrWhiteSpace(Args.AdditionalIssuer) && File.Exists(Args.AdditionalIssuer))
{
pfxBuilder.AddIssuer(File.ReadAllBytes(Args.AdditionalIssuer));
}
var pfx = pfxBuilder.Build("HTTPS Cert - " + Args.Domain, string.Empty);
var r = X509CertificateLoader.LoadPkcs12(pfx, string.Empty, X509KeyStorageFlags.Exportable);

ui

在 VKProxy管理站点的 ui sni 里面添加了 简单的 http 验证方式的acme证书界面配置 如下图

(当然使用前提得是 暴露 xxx域名/.well-known/acme-challenge 接口到公网,这样公网acme 才能验证)

专职ACME管理程序

其实对更多人来说,ACME都是低频率使用,只是现在免费证书大多90天,所以才期望有个工具帮自己干活

现成的很多,比如

  • acme.sh 脚本工具,稍显复杂
  • certimate 目前只支持 dns 验证,不过dns服务商/通知/证书部署都支持非常全面

所以珠玉在前,大家可以直接尽情使用

至于用c#再做一个,多半没有啥人关注,不信,和大家打个赌:评论留言说期望有个c#版的超过 30 条,就搞一个 (一条评论都没有,信不信,哈哈哈)

VKProxy 是使用c#开发的基于 Kestrel 实现 L4/L7的代理(感兴趣的同学烦请点个github小赞赞呢)

c# ACME client (补充)的更多相关文章

  1. 免费SSL证书 之Let’s Encrypt申请与部署(Windows Nginx)

    我着着皇帝的新衣,但是你看不见    有一颗愿意等待的心,说明你对未来充满希望.有一颗充满希望的心,那么等待又算什么.人就是在等待与希望中度过,我们永远要对未来充满信心! 读在最前面: 1.本文案例为 ...

  2. 从 HTTP 到 HTTPS - IIS 部署免费 HTTPS

    这篇文章首发于我的个人网站:听说 - https://tasaid.com/,建议在我的个人网站阅读,拥有更好的阅读体验. 这篇文章与 博客园 和 Segmentfault 共享. 前端开发QQ群:3 ...

  3. 快速入门系列--WCF--01基础概念

    转眼微软的WCF已走过十个年头,它是微软通信框架的集大成者,将之前微软所有的通信框架进行了整合,提供了统一的应用方式.记得从自己最开始做MFC时,就使用过Named Pipe命名管道,之后做Winfo ...

  4. Java多线程(四) 线程池

    一个优秀的软件不会随意的创建.销毁线程,因为创建和销毁线程需要耗费大量的CPU时间以及需要和内存做出大量的交互.因此JDK5提出了使用线程池,让程序员把更多的精力放在业务逻辑上面,弱化对线程的开闭管理 ...

  5. 再见WCF

    转眼微软的WCF已走过十个年头,它是微软通信框架的集大成者,将之前微软所有的通信框架进行了整合,提供了统一的应用方式.记得从自己最开始做MFC时,就使用过Named Pipe命名管道,之后做Winfo ...

  6. Awesome Go

    A curated list of awesome Go frameworks, libraries and software. Inspired by awesome-python. Contrib ...

  7. python-基于tcp协议的套接字(加强版)及粘包问题

    一.基于tcp协议的套接字(通信循环+链接循环) 服务端应该遵循: 1.绑定一个固定的ip和port 2.一直对外提供服务,稳定运行 3.能够支持并发 基础版套接字: from socket impo ...

  8. Spring Boot+CXF搭建WebService(转)

    概述 最近项目用到在Spring boot下搭建WebService服务,对Java语言下的WebService了解甚少,而今抽个时间查阅资料整理下Spring Boot结合CXF打架WebServi ...

  9. Lets encrypt安装及配置

    letsencrypt recommend that most people with shell access use the Certbot ACME client.It can automate ...

  10. 生成线上用https证书,支持通配符和多域名,初学Let’s Encrypt用于IIS,纯本地手动

    自简书发布的上篇<生成本地测试用https证书,支持通配符和多域名,初学OpenSSL>以来,本地测试用https用的妥妥的. 线上一直用的腾讯云的免费证书(每个域名都要一个证书(滑稽), ...

随机推荐

  1. Node v18.6 发布的这个新特性未来可能改变前端工程化

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  2. 传统的可扩展架构模式:分层架构和SOA

    极客时间:<从 0 开始学架构>:传统的可扩展架构模式:分层架构和SOA 分层架构 分层架构是很常见的架构模式,它也叫 N 层架构,通常情况下,N 至少是 2 层.例如,C/S 架构.B/ ...

  3. UML类图-UML Class Diagram

    .wj_nav { display: inline-block; width: 100%; margin-top: 0; margin-bottom: 0.375rem } .wj_nav_1 { p ...

  4. docker-compose用法

    以下的示例搭建龙一个wordpress博客 services: mysql: image: mysql:latest environment: - MYSQL_ROOT_PASSWORD=123456 ...

  5. 【2020.11.24提高组模拟】变换 (transform) 题解

    [2020.11.24提高组模拟]变换 (transform) 题解 题意描述 给一个大小为\(n\)的\(01\)环\(A\),点编号为\(0,1,\dots,n-1\).每一个点\(i\)都与\( ...

  6. [CRCI2008-2009] CVJETICI

    [CRCI2008-2009] CVJETICI 观察图片及样例一: 注:下文中的被占领,指的是在这一个区间内,才有交叉开花的可能. 第一张小图发现 $2 \sim 3$ 被占领. 第二张小图发现 $ ...

  7. (萌新向)对于nodejs原型链污染中merge函数的作用的个人理解

    merge函数 function merge(target,source){ for (let key in source){ if (key in source && key in ...

  8. Web前端入门第 66 问:JavaScript 作用域应用场景(闭包)

    什么是作用域? 就像孙悟空给唐僧画个圈圈一样,这个圈圈就可以称之为作用域,这个比喻可能不太形象. 作用域和孙悟空的圈圈还是有点区别,作用域内部可以获得作用域外部的变量,而内部的变量无法逃逸到作用域外面 ...

  9. PVE折腾笔记 (3) 在原QNAP使用的硬盘上创建ZFS

    前言 在经过一番研究后,我决定使用ZFS作为俩机械硬盘的文件系统,本来也可以和QNAP一样直接ext4的,但ZFS比较安全,有自愈功能,可以处理比特位翻转的问题,总之就是好用. 如果追求灵活性可以使用 ...

  10. 新起点!大数据分布式可视化的 DAG 任务调度系统 Taier 正式发布1.4版本

    我们很高兴向大家宣布,2023年4月14日,Taier 正式发布 1.4 版本.自2022年2月份 Taier 正式开源以来,收到了很多开发者和行业用户的积极评价,在诸多生产环境中已得到充分应用.Ta ...