goproxy HTTP over TLS 二级代理无法工作

1tuwyuhd  于 2022-10-27  发布在  Go
关注(0)|答案(7)|浏览(335)

配置流程

proxy keygen -C ca
proxy keygen -C ca -s -c win_proxy

机器 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

x9ybnkn6

x9ybnkn61#

使用证书错误,签发方式必须指定--ca.

nwnhqdif

nwnhqdif2#

@snail007
-C, --ca="" ca name
根据文档, -C 和 --ca 是同样的意思呀

apeeds0o

apeeds0o3#

仔细看命令帮助,
--ca="" ca cert file for tls
-C, --cert="proxy.crt" cert file for tls

kyvafyod

kyvafyod4#

@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

dhxwm5r4

dhxwm5r45#

使用 --ca="" 的方式进行 keygen 证书签发, 报错相同。

i5desfxk

i5desfxk6#

使用 Wireshark 抓包分析了 curl 和 goproxy 发出的包,发现在 TLS 握手阶段,goproxy 并没有给上游 server 发送正确的 client certificate,导致上游 server 发送了 Alert 拒绝握手。

ljsrvy3e

ljsrvy3e7#

@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 证书的,只是文档中没有说明。

建议在文档中强调这点,明确一下各个证书在各级的作用。这样配置起来会更加清晰。**

相关问题