Open wzxjohn opened 5 years ago
使用证书错误,签发方式必须指定--ca.
@snail007 -C, --ca="" ca name 根据文档, -C 和 --ca 是同样的意思呀
仔细看命令帮助, --ca="" ca cert file for tls -C, --cert="proxy.crt" cert file for tls
@snail007 这是我看到的 help 信息:
$ proxy keygen --help
usage: proxy keygen [<flags>]
create certificate for proxy
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--version Show application version.
--debug debug log output
--daemon run proxy in background
--forever run proxy in forever,fail and retry
......
-n, --cn="" common name
-C, --ca="" ca name
-c, --cert="" cert name of sign to create
-d, --days=365 days of sign
-s, --sign cert is to signin
$ proxy http --help
usage: proxy http [<flags>]
proxy on http mode
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--version Show application version.
--debug debug log output
--daemon run proxy in background
--forever run proxy in forever,fail and retry
......
-P, --parent= ... parent address, such as: "23.32.32.19:28008"
--ca="" ca cert file for tls
-C, --cert="proxy.crt" cert file for tls
-K, --key="proxy.key" key file for tls
-t, --local-type=tcp local protocol type <tls|tcp|kcp>
-T, --parent-type=PARENT-TYPE parent protocol type <tls|tcp|ssh|kcp>
--always always use parent proxy
--timeout=2000 tcp timeout milliseconds when connect to real server or parent proxy
--http-timeout=3000 check domain if blocked , http request timeout milliseconds when connect to host
--interval=10 check domain if blocked every interval seconds
-b, --blocked="blocked" blocked domain file , one domain each line
-d, --direct="direct" direct domain file , one domain each line
-F, --auth-file=AUTH-FILE http basic auth file,"username:password" each line in file
-a, --auth=AUTH ... http basic auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2
-I, --check-parent-interval=3 check if proxy is okay every interval seconds,zero: means no check
-p, --local=":33080" local ip:port to listen,multiple address use comma split,such as: 0.0.0.0:80,0.0.0.0:443
......
我看到的 help 信息告诉我,证书签发时,-C = --ca,证书使用时,-C = --cert
使用 --ca="" 的方式进行 keygen 证书签发, 报错相同。
使用 Wireshark 抓包分析了 curl 和 goproxy 发出的包,发现在 TLS 握手阶段,goproxy 并没有给上游 server 发送正确的 client certificate,导致上游 server 发送了 Alert 拒绝握手。
@snail007 找到原因了。
上游 Server 会读取 -C 参数的证书,取 Subject 作为 Issuer 去发 Certification Request,然后 Client 会去使用自身的证书的 Issuer 去做匹配。
这个流程本身是没有问题的,问题在于,文档中说需要先生成 CA,再用 CA 签发上游 Server 和 Client 使用的证书。这一步说明存在问题。实际上,在目前的代码中,上游 Server 和 Client 都必须使用 CA 证书本身才可以通信成功。
也就是说,Server 和 Client 必须使用 Subject 和 Issuer 相同的证书才可以进行通信。
建议这里修改一下这个流程,上游 Server 向客户端发送的证书应该使用 -C -K 参数指定的证书,但是用来验证客户端的证书应该是 --ca 参数指定的证书。否则客户端和服务端就永远只能使用 CA 证书本身进行通信了。
经过测试,目前的代码是支持上游 Server 指定单独的 CA 证书的,只是文档中没有说明。 建议在文档中强调这点,明确一下各个证书在各级的作用。这样配置起来会更加清晰。
配置流程
机器 A 启动:
proxy.exe http -t tls -p ":8080" -C win_proxy.crt -K win_proxy.key
客户端启动:proxy http -t tcp -p ":8080" -T tls -P "a.b.c.d:8080" -C win_proxy.crt -K win_proxy.key
客户端报错
err:remote error: tls: bad certificate
服务端报错
ERR:http decoder read err:tls: client didn't provide a certificate
用 curl 测试可以连通,测试命令:
curl -i https://a.b.c.d:8080/ --insecure --cert win_proxy.crt --key win_proxy.key