本文记录的是修改tidb数据库版本号信息,由于本文涉及知识点不多,没有技术含量,请谨慎按需阅读。
起因
近来似乎流行国产化适配,上半年做的一个项目,原先是用mysql的,经历过从5.7升级到8.0,经历过不同版本数据不兼容的痛苦阶段。后来上峰一声令下,要切换到国产数据库。考虑到项目中需用mysql的是一个java写的低代码平台微服务,考虑到团队开发人员的技术栈,考虑到时效,考虑到切换平滑,在多重考虑后,在一段时间选型后,决定使用TiDB,当时有文章记录了TiDB的编译部署。不久前,负责安全的团队发来报告,说扫描出重大漏洞,一项是tomcat的,另一项是数据库的。编号达20多个:
CVE-2023-21912、CVE-2019-3822、CVE-2022-37434、CVE-2021-3711、CVE-2021-22926、CVE-2019-5443、CVE-2019-5482、CVE-2022-43551、CVE-2021-22946、CVE-2022-27778、CVE-2021-2144、CVE-2019-2632、CVE-2023-21980、CVE-2021-22946、CVE-2021-22945、CVE-2021-22901、CVE-2019-17543、CVE-2023-0215、CVE-2022-32221、CVE-2020-1967、CVE-2022-1292、CVE-2022-0778
不管哪一个,都指向了mysql/5.7.25
。
报告还给出了官方修复的链接:
https://www.oracle.com/security-alerts/cpuapr2023.html
https://www.oracle.com/security-alerts/cpuapr2022.html
https://www.oracle.com/security-alerts/cpuapr2021.html
https://www.oracle.com/security-alerts/cpuapr2020.html
https://www.oracle.com/security-alerts/cpuapr2019.html
好家伙,我家大妞从没生出到会背“床前明月光”的年份都有,不管哪一个年份列表,都没法做到,因为TiDB虽然高度兼容MySQL,但毕竟不是MySQL。正如说“当作自己人”,就很明显地说明了“不是自己人”。
但不管如何,出了问题总是要解决,想办法解决,克服困难解决,别人不懂的要自己上场解决。
排查及解决
开始解决
首先,在网上搜索,找到TiDB社区相关的帖子,这一个是帖子,另一个也是帖子。里面提到修改版本号的方案。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oo7oxFxo-1691135417973)(2023-08-03-tidb修改版本号/image-20230804152153334.png)]
但里面说的是有集群的情况,无法直接使用该方案。但TiDB是开源的,当时也是自己亲自编译的,于是决定看源码,下文就是通过修改源码或配置文件达到修改版本号的目的。
问题定位
注意看,漏洞扫描报告里提到的MySQL版本是5.7.25
。使用mysql
命令连接TiDB数据库,会先显示版本号信息:
$ mysql -uroot -h 127.0.0.1 -P4000
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 405
Server version: 5.7.25-TiDB- TiDB Server (Apache License 2.0) Community Edition, MySQL 5.7 compatible
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
TiDB版本号信息是这一行Server version: 5.7.25-TiDB- TiDB Server (Apache License 2.0) Community Edition, MySQL 5.7 compatible
,除了没有TiDB版本号外,其它的都具备了。
既然5.7.25
那么重要,直接在源码工程搜索,果然发现了端倪。
修改字样 5.7.25-TiDB-
在parser\mysql\const.go
文件中,相关代码片段如下:
// parser\mysql\const.go
// Version information.
var (
// TiDBReleaseVersion is initialized by (git describe --tags) in Makefile.
TiDBReleaseVersion = "None"
// ServerVersion is the version information of this tidb-server in MySQL's format.
ServerVersion = fmt.Sprintf("5.7.25-TiDB-%s", TiDBReleaseVersion)
)
ServerVersion
由固定前缀5.7.25-TiDB-
和TiDBReleaseVersion
组成。
继续分析,在config\config.go
有相关版本号的定义,如下:
// config\config.go
ServerVersion string `toml:"server-version" json:"server-version"`
VersionComment string `toml:"version-comment" json:"version-comment"`
TiDBEdition string `toml:"tidb-edition" json:"tidb-edition"`
TiDBReleaseVersion string `toml:"tidb-release-version" json:"tidb-release-version"`
这些字段均属于Config
结构体,里面的字段即是命令行--config
指定的配置文件中的字段。其中,TiDBReleaseVersion
表示TiDB发布的版本号,ServerVersion
表示整体的版本号,如字段不为空(默认为空_),则用其值代替。
因此直接在配置文件tidb.toml
中添加如下版本号字段:
server-version = "7.1.1"
#tidb-release-version = "7.1.1"
# TiDB server host.
。。。
运行数据库:
./bin/tidb-server --config tidb.toml
在另一终端使用mysql
连接,信息如下:
$ mysql -uroot -h 127.0.0.1 -P4000
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 403
Server version: 7.1.1 TiDB Server (Apache License 2.0) Community Edition, MySQL 5.7 compatible
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
然而,版本信息那一行依然有MySQL 5.7 compatible
字样。这时就要真的动源码了。
删除字样MySQL 5.7 compatible
搜索关键字, MySQL 5.7 compatible
,在tidb-server\main.go
和sessionctx\variable\sysvar.go
文件中都有相关字符串,为安全起见,均删除掉。
// tidb-server\main.go setGlobalVars函数
if len(cfg.TiDBEdition) > 0 {
versioninfo.TiDBEdition = cfg.TiDBEdition
variable.SetSysVar(variable.VersionComment, "TiDB Server (Apache License 2.0) "+versioninfo.TiDBEdition+" Edition, MySQL 5.7 compatible")
}
// sessionctx\variable\sysvar.go defaultSysVars 数组
{Scope: ScopeNone, Name: VersionComment, Value: "TiDB Server (Apache License 2.0) " + versioninfo.TiDBEdition + " Edition, MySQL 5.7 compatible"},
在联网情况下,在安装go情况下,在工程目录中输入make
即可。注意,1.18版本无法编译,提示undefined: atomic.Bool
,本文使用1.20能正常编译。
测试
运行数据库:
./bin/tidb-server --config tidb.toml
在另一终端使用mysql
连接,信息如下:
$ mysql -uroot -h 127.0.0.1 -P4000
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 403
Server version: 7.1.1 TiDB Server (Apache License 2.0) Community Edition
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
此时,可以看到版本号信息已经达到预期效果了。
其它说明
值得一提的是,更新TiDB源码,不影响数据目录,笔者使用的docker部署,数据目录做了持久化挂载,能快速适用于不同的机器。就当前阶段,已经有2台国产化ARM服务器在使用了,即使在一台x86平台的服务器,笔者也是运行ARM版本TiDB。
另外,本文针对的是版本号的修改和验证。TiDB的root账户默认没有密码,端口默认为4000。
小结
本文记录了从发现问题,思索问题,定位问题,到解决问题的过程,期间看了源码,编了源码,换了go编译器。是不是真的能解决所谓的漏洞,还要等待一段时间才知晓。