一次容器内WebSocket wss连接失败问题定位

问题描述

在容器中运行一个websocket client时,连接websocket server失败,并且无报错信息。

建立websocket连接的代码为:

// var wsAdapterEndpoint = "wss://openbot.xxxx-inc.com/ws"
func (l *GuardBot) setupWebsocketConn() error {
    c, rsp, err := websocket.DefaultDialer.Dial(wsAdapterEndpoint, nil)
    if err != nil {
        logger.Fatalf("failed to connect ws, endpoint: %v, error: %v", wsAdapterEndpoint, rsp)
        return err
    }
    l.conn = c
    return nil
}

报错信息如下:

setupWebsocketConn() failed to connect ws, endpoint: wss://openbot.xxxx-inc.com/ws, error: <nil> 

问题分析

  1. 该程序在本地host上直接运行是正常的,可以成功连到websocket server。
  2. 容器中启动该程序时,连接失败。使用telnet openbot.xxxx-inc.com命令发现其IP和本地解析出来的的IP地址是一样的,排除了网络域名解析问题。
    由于缺乏error日志,只能一点点排查了。在容器内使用命令apt-get install curl后,直接启动执行文件竟然可以连接成功websocket server了。看了下apt-get install curl的日志,发现有openssl和ca证书相关组件也被安装了。恰好我们使用的websocket连接是加密过的(wss连接),极大可能就是由这个引起的。
    于是重启了一把容器,在容器内手动安装了openssl和ca工具包,手动执行程序发现果然可以连接websocket server成功。

问题解决

Dockerfile中构建镜像时,添加openssl和证书相关工具包即可。启动容器发现可以正常连接到websocket server。

FROM debian:buster-slim
RUN apt-get update && apt-get install -y openssl ca-certificates
...

其他

没想到debian的基础镜像连ca证书包都精简掉了,刚好碰到github.com/gorilla/websocket包连接wss缺少ca时没有报错信息。这次问题也算是瞎猫碰到死耗子。
不过还是可以靠排除法来逐步缩小范围,譬如把websocket server端不使用tls,直接用ws连接,这样容器内应该就能连上websocket,从而判断出是tls、证书相关问题。

有时间还是要看一下github.com/gorilla/websocket包的源码,分析下为啥这种场景没有error日志。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容