Skip to content

Commit

Permalink
feat: 读取节点的 ca-str 和 _ca (后端文件路径) 字段, 自动计算 fingerprint
Browse files Browse the repository at this point in the history
  • Loading branch information
xream committed Jun 13, 2024
1 parent 3ad42f2 commit ad3d227
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 1 deletion.
3 changes: 2 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sub-store",
"version": "2.14.337",
"version": "2.14.339",
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
"main": "src/main.js",
"scripts": {
Expand All @@ -25,6 +25,7 @@
"express": "^4.17.1",
"http-proxy-middleware": "^2.0.6",
"js-base64": "^3.7.2",
"jsrsasign": "^11.1.0",
"lodash": "^4.17.21",
"request": "^2.88.2",
"requests": "^0.3.0",
Expand Down
9 changes: 9 additions & 0 deletions backend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions backend/src/core/proxy-utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import rs from '@/utils/rs';
import YAML from '@/utils/yaml';
import download from '@/utils/download';
import {
Expand Down Expand Up @@ -463,6 +464,25 @@ function lastParse(proxy) {
if (['', 'off'].includes(proxy.sni)) {
proxy['disable-sni'] = true;
}
let caStr = proxy['ca_str'];
if (proxy['ca-str']) {
caStr = proxy['ca-str'];
} else if (caStr) {
delete proxy['ca_str'];
proxy['ca-str'] = caStr;
}
try {
if ($.env.isNode && !caStr && proxy['_ca']) {
caStr = $.node.fs.readFileSync(proxy['_ca'], {
encoding: 'utf8',
});
}
} catch (e) {
$.error(`Read ca file failed\nReason: ${e}`);
}
if (!proxy['tls-fingerprint'] && caStr) {
proxy['tls-fingerprint'] = rs.generateFingerprint(caStr);

This comment has been minimized.

Copy link
@Ariesly

Ariesly Nov 1, 2024

Contributor

caStr 这里是证书不是服务端证书吧?
tls-fingerprint 这里验证的是服务端证书?

证书生成是参照这个:
https://v1.hysteria.network/zh/docs/custom-ca/

只能用 xxx.server.crt 产生的 fingerprint 才能验证通过.
openssl x509 -noout -fingerprint -sha256 -in xxx.server.crt

xxx.ca.crt 产生的 fingerprint 验证不通过.
openssl x509 -noout -fingerprint -sha256 -in xxx.ca.crt

This comment has been minimized.

Copy link
@xream

xream Nov 1, 2024

Author Member

mihomo 这么命名的. Sub-Store 大部分字段都参考 mihomo

This comment has been minimized.

Copy link
@Ariesly

Ariesly Nov 1, 2024

Contributor

mihomo 可能客户端和服务端用同一个证书的情况,这里自动生成的 tls-fingerprint 没问题

hysteria 中 客户端ca 和 服务端ca 会是2个不同的证书情况下,这里 自动生成的是 客户端ca 的 tls-fingerprint 而 hysteria 验证 pinSHA256 使用的 服务端ca fingerprint

这边 根据ca 生成的逻辑,可能需要后续判断是否生成 fingerprint

This comment has been minimized.

Copy link
@xream

xream Nov 1, 2024

Author Member

有点没看懂...这里就是帮你生成一下 fingerprint. 你想要用啥就传啥. 你是在纠结的字段名?

This comment has been minimized.

Copy link
@Ariesly

Ariesly Nov 1, 2024

Contributor

不是字段名哦,

CA 私钥和 CA 证书 (hysteria.ca.key 和 hysteria.ca.crt):hysteria.ca.key 用于生成和签署 CA 证书(hysteria.ca.crt),后者用于验证服务器的身份。
服务器私钥和服务器证书 (hysteria.server.key 和 hysteria.server.crt):hysteria.server.key 是服务器端私钥;hysteria.server.crt 是由 CA 签发的服务器证书,包含服务器公钥,提供给客户端以建立 TLS 连接。
在实际使用中:

服务器端:使用 hysteria.server.crt 和 hysteria.server.key 来建立加密连接。
客户端:使用 hysteria.ca.crt 来验证服务器证书的合法性,确保服务器的可信性。

客户端会是用根证书(hysteria.ca.crt)验证,
如果用根证书生成的指纹会是不对的. 验证是需要服务器证书 (hysteria.server.crt)的指纹

疑问在于这里是否生成的必要,已知只要配置 tls-fingerprint 就不会自动生成
这里自动生成的 tls-fingerprint 有可能是错误的. ps: 错误的意思是不是所需验证证书的指纹.

This comment has been minimized.

Copy link
@xream

xream Nov 1, 2024

Author Member

还是没看懂. 你需要用什么指纹就设置什么指纹. 可以直接设 tls-fingerprint 也可以设置 ca-str 也可以设置 _ca. 目的就是设置你想要的 tls-fingerprint. 什么叫自动生成的 tls-fingerprint 不是所需验证证书的指纹. ca-str 和 _ca 不是你自己传的吗

This comment has been minimized.

Copy link
@Ariesly

Ariesly Nov 1, 2024

Contributor

这个部分就是提到的自动生成

if (!proxy['tls-fingerprint'] && caStr) {
    proxy['tls-fingerprint'] = rs.generateFingerprint(caStr);
}

下面是证书关系说明(来自chatgpt

  1. hysteria.ca.crt 和 hysteria.server.crt 的关系
    CA 证书 (hysteria.ca.crt):这是自签名证书,充当证书链中的根证书。它包含 CA 的公钥,签署了 hysteria.server.crt。
    服务器证书 (hysteria.server.crt):这是由 hysteria.ca.crt 签发的证书,包含服务器的公钥。它表明该服务器的身份已被 CA 验证。
    在 TLS 连接中,服务器将 hysteria.server.crt 发送给客户端,客户端通过检查其签名是否匹配 hysteria.ca.crt,来确认服务器证书的真实性。

  2. 客户端可以直接使用 hysteria.server.crt 吗?
    通常不能直接使用。原因如下:
    客户端需要知道 hysteria.server.crt 是由可信的 CA(即 hysteria.ca.crt)签发的,直接信任 hysteria.server.crt 会带来安全隐患。
    在实际应用中,客户端应将 hysteria.ca.crt 添加到其可信根证书集合中。这样当服务器提供 hysteria.server.crt 时,客户端可以通过 hysteria.ca.crt 验证其签名,确保服务器的合法性。

客户端通常用 hysteria.ca.crt 作为证书
指纹验证合法性使用的是 hysteria.server.crt 的指纹

实际使用已传入 tls-fingerprint 来避免生成错误了.
提问的原因是看看配置中产生的 tls-fingerprint 实际的不一样,所以查到了这里,

感谢 owner 抽空解答.

This comment has been minimized.

Copy link
@xream

xream Nov 1, 2024

Author Member

客户端通常用 hysteria.ca.crt 作为证书
指纹验证合法性使用的是 hysteria.server.crt 的指纹

但是这个跟 mihomo surge 等客户端没啥关系吧. 我们用的 ca, ca-str, server-cert-fingerprint-sha256 都是 hysteria.server.crt 的指纹.

而 hysteria.ca.crt 是这么用的:

iOS 端如果使用的是小火箭 Shadowrocket,可以把文件 hysteria.ca.crt airdrop 到手机,然后在手机上安装并信任后, 就可以使用自定义 CA 证书了。

跟 Sub-Store 本来就没关系.

}
return proxy;
}

Expand Down
11 changes: 11 additions & 0 deletions backend/src/utils/rs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import rs from 'jsrsasign';

export function generateFingerprint(caStr) {
const hex = rs.pemtohex(caStr);
const fingerPrint = rs.KJUR.crypto.Util.hashHex(hex, 'sha256');
return fingerPrint.match(/.{2}/g).join(':').toUpperCase();
}

export default {
generateFingerprint,
};

0 comments on commit ad3d227

Please sign in to comment.