apernet / hysteria

Hysteria is a powerful, lightning fast and censorship resistant proxy.
https://v2.hysteria.network/
MIT License
14.03k stars 1.57k forks source link

acme非标端口申请证书 #1129

Closed ypxun closed 3 weeks ago

ypxun commented 1 month ago

不是bug,只是不知道使用什么分类的issue,就默认用这个了,不好意思。 因为nginx占用80和443端口的原因,hy2的acme使用80和443端口自动申请证书总是不太方便。我参照 #804 ,将

location /.well-known/acme-challenge {
    proxy_set_header Host $host;
    proxy_set_header X-Real_IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
    proxy_pass http://127.0.0.1:8080;
}

填入nginx.conf,但报错,主要错误是在 HTTP-01 挑战过程中,ACME 服务从 a.a.com 获取到的响应无效,通常是由于挑战响应文件无法正确访问: ERROR acme_client challenge failed {"identifier": "a.a.com", "challenge_type": "http-01", "problem": {"type": "urn:ietf:params:acme:error:unauthorized", "title": "", "detail": "1.2.3.4: Invalid response from https://a.a.com/.well-known/acme-challenge/YDqLJyBn-IOHaopgXCG7tzJFQ9sRymS5za6N1gwTiYU: \"<!DOCTYPE html>\\n<html lang=\\\"en\\\" translate=\\\"no\\\">\\n <head>\\n \\n <meta charset=\\\"utf-8\\\" >\\n <meta name=\\\"viewport\\\" content=\\\"wid\"", "instance": "", "subproblems": []}} 然后我又尝试在hy2的config.yaml acme部分填入altHTTPPort: 8080,还是不行,一样是响应文件不对。 我在nginx.conf里的默认80 server块设置:

    server {
        listen 80;
        listen [::]:80;

        location /.well-known/ {
            root /var/www/html;
        }

        # acme验证
        location /.well-known/acme-challenge/ {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8080;
        }

        location / {
            rewrite ^(.*)$ https://$host$1 permanent;
        }
    }
}

想问下,我设置到底错在哪,导致acme不能自动使用非标端口申请证书?

mritd commented 4 weeks ago

感觉像是没有转发成功, 这种方式我没测试过, 不过现在 master 已经支持了 DNS 挑战, 你可以试试直接使用 DNS 申请证书:

acme:
  domains:
     - "*.xxxx.com"
  email: hysteria@example.com
  type: dns
  dns:
    name: cloudflare
    config:
      cloudflare_api_token: xxxxxxxxxxxxx

name 可选值参考 https://github.com/apernet/hysteria/blob/master/app/cmd/server.go#L365case xxxx: 这块, config 可选值参考 case xxxx: 下面的 c.ACME.DNS.Config["xxxxx"]

ypxun commented 4 weeks ago

感觉像是没有转发成功, 这种方式我没测试过, 不过现在 master 已经支持了 DNS 挑战, 你可以试试直接使用 DNS 申请证书:

acme:
  domains:
     - "*.xxxx.com"
  email: hysteria@example.com
  type: dns
  dns:
    name: cloudflare
    config:
      cloudflare_api_token: xxxxxxxxxxxxx

name 可选值参考 https://github.com/apernet/hysteria/blob/master/app/cmd/server.go#L365case xxxx: 这块, config 可选值参考 case xxxx: 下面的 c.ACME.DNS.Config["xxxxx"]

你好,我去看了下那部分代码,然后和acme的dns api注册方式对比了下,有个疑问的点在于:

acme官方使用cf的dns api时,分为全局api(CF_Key和CF_Email),限制性的单域api(CF_Token和CF_Zone_ID)和多域api(CF_Token和CF_Account_ID)https://github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_cf

https://github.com/apernet/hysteria/blob/master/app/cmd/server.go#L365 我看这里不是这么细分的,效用相同吗?

mritd commented 4 weeks ago

邮箱是用来接受 ACME 提供商官方通知的, 比如使用 zerossl 它会定期提示你证书到期, 他跟你 CF 的邮箱没有什么关系.

至于 token, 只要该 token 有权限操作你对应域名的 DNS 解析即可, 准确的说是必须有权限添加 TXT DNS 记录.

mritd commented 4 weeks ago

具体的创建步骤:

image image

然后再根据需求选择特定域名或全部域名创建即可

ypxun commented 4 weeks ago

具体的创建步骤: image image

然后再根据需求选择特定域名或全部域名创建即可

感谢这么细致的回复。其实我的疑问在于:acme官方申请,强制要求使用token+email(CF账户邮箱)/ID(单域ID或CF账户ID),两项配合才能自动申请。而 https://github.com/apernet/hysteria/blob/master/app/cmd/server.go#L365 只用了token,就完全够了吗?

mritd commented 4 weeks ago

ACME 并没有所谓的必须 Token + Email 的要求, ACME 只是一种证书申请协议或者说流程; 其申请核心点在于: 你如何向证书颁发机构(Let's Encrypt/ZeroSSL)证明你拥有这个域名的控制权?

对于普通的 HTTP 挑战来说, 基本流程如下:

所以这种方式你只能申请单独域名/子域名的证书.

对于 DNS 挑战来说, 基本流程如下:

所以这种方式你可以申请泛域名证书.

综合整个流程来说, ACME DNS 申请并不捆绑任何邮箱、服务商 Token, 他只需要你 "加好 TXT 记录" 即可; 在 hysteria 中使用的 acmez 库默认对接了 CF API, 所以你只需要给 hysteria 一个能控制该域名解析的 CF Token 即可.

ypxun commented 4 weeks ago

ACME 并没有所谓的必须 Token + Email 的要求, ACME 只是一种证书申请协议或者说流程; 其申请核心点在于: 你如何向证书颁发机构(Let's Encrypt/ZeroSSL)证明你拥有这个域名的控制权?

对于普通的 HTTP 挑战来说, 基本流程如下:

* 首先你向证书颁发机构发起申请请求

* 证书颁发机构给你一个随机 Token

* 你将这个 Token 放在网站根目录特定位置(一般由程序自动完成)

* 证书颁发机构尝试访问并验证 Token, 成功则证明你能控制该网站的 80/443, 间接证明你对该域名有控制权

所以这种方式你只能申请单独域名/子域名的证书.

对于 DNS 挑战来说, 基本流程如下:

* 首先你向证书颁发机构发起申请请求

* 证书颁发机构给你一个随机 Token

* 你将这个 Token 加入到域名的 TXT 记录中(一般由程序自动完成)

* 证书颁发机构尝试查询 DNS 解析并验证 Token, 成功则**证明你拥有该域名的 DNS 解析权限**, 间接证明你对该域名有完全控制权

所以这种方式你可以申请泛域名证书.

综合整个流程来说, ACME DNS 申请并不捆绑任何邮箱、服务商 Token, 他只需要你 "加好 TXT 记录" 即可; 在 hysteria 中使用的 acmez 库默认对接了 CF API, 所以你只需要给 hysteria 一个能控制该域名解析的 CF Token 即可.

了解了,非常感谢你的耐心。

不过我说的“acme官方申请,强制要求使用token+email(CF账户邮箱)/ID(单域ID或CF账户ID)”,对于cf家,确实是写在官方wiki 里的😳

(i) Single DNS zone

You must give acme.sh the zone ID of the DNS zone it needs to edit.

(ii) Multiple DNS zones

You must give acme.sh the account ID of the Cloudflare account to which the relevant DNS zones belong.

(b) Using the global API key

You must also set CF_Email to the email address that is associated with your Cloudflare account; this is the email address you enter when logging in to Cloudflare.

mritd commented 4 weeks ago

acme.sh != 官方 它只是脚本化的一个 客户端实现.

ypxun commented 4 weeks ago

acme.sh != 官方 它只是脚本化的一个 客户端实现.

原来如此,我一直以为是一个东西🤣醉了

mritd commented 4 weeks ago

具体规范你可以看这里 https://datatracker.ietf.org/doc/html/rfc8555#section-8.4, 以 Let's Encrypt 为例 这些都是已知的支持客户端 https://letsencrypt.org/zh-cn/docs/client-options/

ypxun commented 3 weeks ago

具体规范你可以看这里 https://datatracker.ietf.org/doc/html/rfc8555#section-8.4, 以 Let's Encrypt 为例 这些都是已知的支持客户端 https://letsencrypt.org/zh-cn/docs/client-options/

感谢热心解答!