Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wss 协议的证书锁定无效 #629

Closed
luyuhuang opened this issue Aug 12, 2020 · 17 comments
Closed

wss 协议的证书锁定无效 #629

luyuhuang opened this issue Aug 12, 2020 · 17 comments

Comments

@luyuhuang
Copy link
Contributor

版本: gost 2.11.1 (go1.14.2 linux/amd64)

重现步骤:

  • 随意生成一个证书 server.crt
  • 使用 ./gost -L 'wss://127.0.0.1:10040' 在本地启动一个服务端
  • 使用 ./gost -L 127.0.0.1:10030 -F 'wss://127.0.0.1:10040?ca=server.crt' 启动客户端
  • 设置浏览器 socks5 代理为 127.0.0.1:10030 这时是可以正常访问的.

在服务端没有使用 server.crt 作为证书的情况下应该校验失败才对. 而如果将 wss 协议改成 https, 就能看到 certificate signed by unknown authority 的错误日志了.

@kingwilliam
Copy link

kingwilliam commented Aug 14, 2020

如理解有误请指正.

您提出有以下3点.

  1. 随意生成一个证书 server.crt
  2. 使用 ./gost -L 'wss://127.0.0.1:10040' 在本地启动一个服务端
  3. 使用 ./gost -L 127.0.0.1:10030 -F 'wss://127.0.0.1:10040?ca=server.crt' 启动客户端

A1. server.crt视为server的电子证书, 但密匙?
A2. -L wss视为一个服务端 security websocket, 但没证书?
A3. -F wss.....?ca=server.crt 视为一个客户端, 但为何伺服器证书会放在客户端?
A3.1 但又为何伺服器证书会放在ca?,
A3.2 因您上面3点也没有说您有 ca.crt, 那麽您的ca.crt?

您的问题是 “在服务端没有使用 server.crt 作为证书的情况下应该校验失败才对. 而如果将 wss 协议改成 https, 就能看到 certificate signed by unknown authority 的错误日志了”

我尝试题供一些例子给参考,看看可否解答您的问题

  1. 首先电子证书有证书时 server.crt, 同时也要有 server.key 密匙 (证书和密匙是一对的)
  2. 有证书和密匙 当然也应该有 ca.crt (在您的例子是可以没ca密匙的)
  3. 首先修改您的服务端
    ./gost -L 'wss://127.0.0.1:10040?cert=server.crt&key=server.key'
  4. 再修改您的客户端
    ./gost -L 127.0.0.1:10030 -F 'wss://127.0.0.1:10040?ca=ca.crt'

不知能否解决您的问题?

@luyuhuang
Copy link
Contributor Author

luyuhuang commented Aug 14, 2020

@kingwilliam 谢谢您的回复. 我的意思是这样的:

服务端使用 -L wss , 没有指定证书, 这时 gost 会使用内置的证书 (见 https://docs.ginuerzh.xyz/gost/tls/);

而客户端使用随意生成的证书 server.crt 作为 ca 证书进行证书锁定, 也就是指定 ?ca=server.crt;

然后客户端尝试与服务端建立 TLS 连接;

此时, 服务端使用的内置证书显然不是我们随意生成的 ca 证书 server.crt 所签名的. 客户端应该认为这个服务端是不被信任的, 我们应该能看到 certificate signed by unknown authority 这样的报错才对. 但事实是, 没有报错, 正常连接. 这应该是不对的.

而如果把 wss 改成 https, 执行同样的操作, 我们就能在客户端看到我们所期望的报错: certificate signed by unknown authority

@luyuhuang
Copy link
Contributor Author

luyuhuang commented Aug 14, 2020

我在阅读源码时没有发现 wss 协议使用 ca 参数所指定的证书对服务端证书作校验的代码 (TLS 有, https 使用的就是 TLS, 但是 wss 协议使用的是 websocket 库, 与 TLS 不同). 于是我尝试对 ws.go 作了一些修改, 见 #630. 修改后的客户端执行上述操作, 就能看到期望的报错了.

@k79e
Copy link

k79e commented Sep 3, 2020

你开secure试试

@luyuhuang
Copy link
Contributor Author

你开secure试试

开了 secure 就是正常校验证书, 并不会使用 ca 参数指定的证书校验. 而且这样的话自签名的证书就没法用了.

@k79e
Copy link

k79e commented Sep 3, 2020

正常的+ca 两个一起用就行了

@luyuhuang
Copy link
Contributor Author

正常的+ca 两个一起用就行了

不行. 这样自签名的证书就用不了了.

@k79e
Copy link

k79e commented Sep 3, 2020

可以 要有域名
我以前测的是带域名的 没域名的没测过

@luyuhuang
Copy link
Contributor Author

如果这样可以的话, 那你有没有试过这样:

  • 服务器执行 ./gost -L 'wss://0.0.0.0:10040?cert=server.crt&key=server.key' 启动服务端, 其中证书 server.crtca.crt 颁发, 且与服务器域名匹配;
  • 客户端随意生成一个 ca1.crt 证书
  • 客户端执行 ./gost -L 127.0.0.1:10030 -F 'wss://server.com:10040?ca=ca1.crt&secure=true' 启动客户端, 假设 server.com 是服务器域名
  • 客户端测试 socks5://127.0.0.1:10030

这种情况下, 客户端仅信任 ca1.crt 及其颁发的证书. 这个例子中的服务器应该是不被信任的. 如果这样能够正常运行的话, 说明证书锁定无效.

可以 要有域名

如果在开启 secure 的情况下, 只要自签名证书与域名匹配就有效的话, 是不安全的. 中间人只需随意签名一个域名与之匹配的证书就可以劫持你的 ssl 链接, 并且不被你察觉, 你的传输内容就会被破解.

@luyuhuang
Copy link
Contributor Author

又看了一遍代码, 在有域名的情况下, 开启 secure 并指定 ca= 是有效的. 而且, 在使用自签名证书的情况下, 开启 secure 但不指定 ca= 会不被信任. 这些都没有问题, 上面我说的问题也都不存在.

现在唯一的问题就是不使用域名就无法安全地使用 wss. 因为在没有域名的情况下不能使用正式的证书, 也无法使用证书锁定. 我看到 tls.go 271 行的 wrapTLSClient 函数就是用来解决这个问题的, 它对证书进行手动校验. 这样对于 https 协议, 不使用域名, 不开启 secure 也能够证书锁定. 所以我想 wss 也做类似的事情, 这样不使用域名也能正常证书锁定, 应该要好一些.

@proxy666-dev
Copy link
Contributor

proxy666-dev commented Sep 4, 2020

又看了一遍代码, 在有域名的情况下, 开启 secure 并指定 ca= 是有效的. 而且, 在使用自签名证书的情况下, 开启 secure 但不指定 ca= 会不被信任. 这些都没有问题, 上面我说的问题也都不存在.

现在唯一的问题就是不使用域名就无法安全地使用 wss. 因为在没有域名的情况下不能使用正式的证书, 也无法使用证书锁定. 我看到 tls.go 271 行的 wrapTLSClient 函数就是用来解决这个问题的, 它对证书进行手动校验. 这样对于 https 协议, 不使用域名, 不开启 secure 也能够证书锁定. 所以我想 wss 也做类似的事情, 这样不使用域名也能正常证书锁定, 应该要好一些.

你的意思是说,这个如标题所说的bug是不存在的?(如果是的话,这就很尴尬了。)

@luyuhuang
Copy link
Contributor Author

你的意思是说,这个如标题所说的bug是不存在的?(如果是的话,这就很尴尬了。)

严格地来说, 是的. 只能说之前我理解的不充分. 应该是在不使用域名的情况下, wss 协议无法使用证书锁定. 我列出的复现步骤也能说明这个问题; #630 也能解决这个问题, 不过这种做法可能不够好, 应该有更好的办法.

@proxy666-dev
Copy link
Contributor

你的意思是说,这个如标题所说的bug是不存在的?(如果是的话,这就很尴尬了。)

严格地来说, 是的. 只能说之前我理解的不充分. 应该是在不使用域名的情况下, wss 协议无法使用证书锁定. 我列出的复现步骤也能说明这个问题; #630 也能解决这个问题, 不过这种做法可能不够好, 应该有更好的办法.

#630 不用了,用 #641

@proxy666-dev
Copy link
Contributor

你的意思是说,这个如标题所说的bug是不存在的?(如果是的话,这就很尴尬了。)

严格地来说, 是的. 只能说之前我理解的不充分. 应该是在不使用域名的情况下, wss 协议无法使用证书锁定. 我列出的复现步骤也能说明这个问题; #630 也能解决这个问题, 不过这种做法可能不够好, 应该有更好的办法.

#630 不用了,用 #641

@luyuhuang 等确定了我再合并到我的gost

@luyuhuang
Copy link
Contributor Author

嗯, 还是要请作者大大看下

@proxy666-dev
Copy link
Contributor

嗯, 还是要请作者大大看下

帮你@作者大大 @ginuerzh

@proxy666-dev
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants