• 记一次线上websocket返回400问题排查


    现象

    生产环境websocket无法正常连接,服务端返回400 bad request,开发及测试环境均正常。

    抓包排查

    src:nginx服务器 172.16.177.193
    dst:imp应用服务器 172.16.177.218

    问题定位

    观察到header中的host值带有下划线,在一些中间件(如kafka、hadoop)中,对host中的特殊字符也有限制。由此猜测是header问题。
    经排查,此header来自nginx的upstream

    解决方案1

    修改nginx的upstream配置,去除下划线

    解决方案2

    既然upstream中用了下划线,为何普通的http请求正常,而websocket则返回400呢?

    再看正常的http请求的抓包

    src: nginx服务器 172.31.47.151
    dst: imp应用服务器 172.31.47.153

    可见,header中的host,被转发到了目标服务器,而此host并没有下划线,正常请求。
    所以,如果不修改nginx中的upstream下划线的配置,其实还可以在server中的websocket 对应的location中,添加参数,以便转发原始请求的host

    proxy_set_header Host $host;
    proxy_set_header X-real-ip $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


    配置后的抓包如下

    请求正常

    原因探讨

    带有下划线的host,为何会被服务端返回400?从上述排查过程可知,应是tomcat返回的。
    这一切要从一个RFC协议规范说起
    RFC-1034 是一个关于DNS及域名基础的标准。在「3.5 Preferred name syntax」中,有提及主机名的格式规范:由字母开头,字母或数字结尾,中间包含字母、数字或横杆

    可见,RFC-1034标准中下划线并不被允许。

    而Tomcat在一次8.x的升级中遵循该标准对host做了此校验,详见链接
    org.apache.coyote.AbstractProcessor#parseHost
    org.apache.tomcat.util.http.parser.Host#parse(java.io.Reader)

    总结

    在我们日常配置host参数时,都尽量避免使用下划线。包括在/etc/hosts下进行的配置,有时在集群环境中为了方便管理,会配置host,此时也应注意避免使用下划线。因为中间件可能也遵循了RTC规范。

    延伸阅读

    如果大家阅读了上述规范,可能会有疑问:为何网易163可以是数字开头?大家可以先去了解下域名的解析过程。
    此处科普几个基本概念。

    • domain name is the identifier of a resource in a DNS database
    • label is the part of a domain name in between dots
    • hostname is a special type of domain name which identifies Internet hosts

    域名是在dns库中的唯一标识,label是域名中以「.」分隔的单元,hostname是对于一个地址的特殊域名映射。

    在1989年的RFC-1101中的「3.1 Network name syntax」定义了网络名词的DNS编码规范。允许数字开头,只要不与十进制八位字节形式的ip地址冲突。
    在1997年的RFC-2181中「11 Name syntax」对域名语法作了澄清,下划线不应被DNS服务所拒绝。
    而在近年的一次CA/B论坛里,众多大厂发起投票,禁止在域名中使用下划线,否则SSL证书将不能正常申请使用。

    有兴趣的朋友可以尝试搭建一个网站并作域名映射。可以确定的是,做域名映射时,因为是hostname,A和MX记录是不能带下划线的。CNAME记录由于针对的是域名,是否支持则取决于你的DNS服务商了。

  • 相关阅读:
    yum下载安装mysql服务
    windows编写sh脚本在linux上不能执行
    ectouch第二讲之 文件结构
    ecshop第一讲之安装
    class id 区别
    thinkphp模板中截取中文字符串的方法分享
    CI 配置验证规则
    CodeIgniter配置之config
    codeigniter中base_url和site_url
    使用phpmyadmin导入SQL数据报错:#1062
  • 原文地址:https://www.cnblogs.com/CLAYJJ/p/16121557.html
Copyright © 2020-2023  润新知