【Prometheus】【Blackbox Exporter】深入解析 ProbeTCP 函数:如何实现 Go 中的 TCP/SSL 协议探测

在监控和性能分析的场景中,探测远程服务的可达性和安全性是至关重要的。blackbox_exporter 是 Prometheus 项目的一部分,它能够帮助我们在不同协议层(HTTP、HTTPS、TCP、DNS 等)上进行服务监控。本文将详细解读 blackbox_exporter 中的 ProbeTCP 函数,分析如何使用 Go 实现对 TCP 连接的探测、SSL/TLS 协议的支持,以及如何在探测过程中获取并处理 SSL 证书和响应信息。

1. 函数定义

func ProbeTCP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry, logger *slog.Logger) bool {

ProbeTCP 函数的目的是对指定目标(target)进行 TCP 连接探测。它会根据配置(module)发送查询请求,读取响应数据,并在需要时升级到 TLS 连接。

参数说明:

  • ctx:上下文,用于控制超时、取消等操作。
  • target:目标地址,通常是一个 IP 或域名。
  • module:配置模块,包含了与 TCP 连接相关的配置(如查询、响应、TLS 设置等)。
  • registry:Prometheus 注册表,用于注册和暴露监控指标。
  • logger:日志记录器,用于记录操作信息和错误。

2. 创建 Prometheus 指标

probeSSLEarliestCertExpiry := prometheus.NewGauge(sslEarliestCertExpiryGaugeOpts)
probeSSLLastChainExpiryTimestampSeconds := prometheus.NewGauge(sslChainExpiryInTimeStampGaugeOpts)
probeSSLLastInformation := prometheus.NewGaugeVec(
	prometheus.GaugeOpts{
		Name: "probe_ssl_last_chain_info",
		Help: "Contains SSL leaf certificate information",
	},
	[]string{"fingerprint_sha256", "subject", "issuer", "subjectalternative"},
)
probeTLSVersion := prometheus.NewGaugeVec(
	probeTLSInfoGaugeOpts,
	[]string{"version"},
)
probeFailedDueToRegex := prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "probe_failed_due_to_regex",
	Help: "Indicates if probe failed due to regex",
})
registry.MustRegister(probeFailedDueToRegex)

这些代码片段创建了多个 Prometheus 指标,用于收集与 SSL/TLS 相关的数据。具体包括:

  • SSL证书到期时间probeSSLEarliestCertExpiry
  • SSL链上证书到期时间戳probeSSLLastChainExpiryTimestampSeconds
  • SSL证书的详细信息probeSSLLastInformation),包括证书指纹、主题、发行者等
  • TLS版本probeTLSVersion
  • 正则表达式匹配失败的标记probeFailedDueToRegex

这些指标可以帮助我们监控目标服务的 SSL 证书状态、TLS 版本以及连接的安全性。

3. 建立 TCP 连接

conn, err := dialTCP(ctx, target, module, registry, logger)
if err != nil {
	logger.Error("Error dialing TCP", "err", err)
	return false
}
defer conn.Close()
logger.Info("Successfully dialed")

这里尝试通过 dialTCP 函数建立 TCP 连接。如果连接失败,则记录错误并返回 false。否则,成功建立连接后会调用 defer conn.Close() 确保连接在函数结束时被关闭。

4. 设置连接超时

deadline, _ := ctx.Deadline()
if err := conn.SetDeadline(deadline); err != nil {
	logger.Error("Error setting deadline", "err", err)
	return false
}

为了防止代码阻塞太长时间,设置了连接的超时时间(deadline)。这确保了连接不会因等待某些操作而永远挂起。

5. SSL/TLS 连接处理

if module.TCP.TLS {
	state := conn.(*tls.Conn).ConnectionState()
	registry.MustRegister(probeSSLEarliestCertExpiry, probeTLSVersion, probeSSLLastChainExpiryTimestampSeconds, probeSSLLastInformation)
	probeSSLEarliestCertExpiry.Set(float64(getEarliestCertExpiry(&state).Unix()))
	probeTLSVersion.WithLabelValues(getTLSVersion(&state)).Set(1)
	probeSSLLastChainExpiryTimestampSeconds.Set(float64(getLastChainExpiry(&state).Unix()))
	probeSSLLastInformation.WithLabelValues(getFingerprint(&state), getSubject(&state), getIssuer(&state), getDNSNames(&state)).Set(1)
}

如果配置要求使用 TLS(module.TCP.TLS),则会对 TCP 连接进行升级为 TLS 连接,并获取证书的相关信息,包括:

  • 证书的最早到期时间
  • 使用的 TLS 版本
  • SSL 链上证书的到期时间
  • 证书的指纹、主题、发行者等信息

这些数据会通过 Prometheus 指标进行暴露。

6. 处理查询和响应

scanner := bufio.NewScanner(conn)
for i, qr := range module.TCP.QueryResponse {
	logger.Info("Processing query response entry", "entry_number", i)
	send := qr.Send
	if qr.Expect.Regexp != nil {
		var match []int
		// Read lines until one of them matches the configured regexp.
		for scanner.Scan() {
			logger.Debug("Read line", "line", scanner.Text())
			match = qr.Expect.Regexp.FindSubmatchIndex(scanner.Bytes())
			if match != nil {
				logger.Info("Regexp matched", "regexp", qr.Expect.Regexp, "line", scanner.Text())
				break
			}
		}
		if scanner.Err() != nil {
			logger.Error("Error reading from connection", "err", scanner.Err().Error())
			return false
		}
		if match == nil {
			probeFailedDueToRegex.Set(1)
			logger.Error("Regexp did not match", "regexp", qr.Expect.Regexp, "line", scanner.Text())
			return false
		}
		probeFailedDueToRegex.Set(0)
		send = string(qr.Expect.Regexp.Expand(nil, []byte(send), scanner.Bytes(), match))
		if qr.Labels != nil {
			probeExpectInfo(registry, &qr, scanner.Bytes(), match)
		}
	}

在这个部分,代码循环处理 QueryResponse 配置,发送查询并等待响应。对于每个查询:

  • 如果配置了正则表达式(qr.Expect.Regexp),则会逐行读取响应数据,直到找到匹配的行。
  • 如果没有找到匹配,记录失败并返回 false

7. 启动 TLS 升级

if qr.StartTLS {
	// Upgrade TCP connection to TLS.
	tlsConfig, err := pconfig.NewTLSConfig(&module.TCP.TLSConfig)
	if err != nil {
		logger.Error("Failed to create TLS configuration", "err", err)
		return false
	}
	if tlsConfig.ServerName == "" {
		targetAddress, _, _ := net.SplitHostPort(target) // Had succeeded in dialTCP already.
		tlsConfig.ServerName = targetAddress
	}
	tlsConn := tls.Client(conn, tlsConfig)
	defer tlsConn.Close()

	// Initiate TLS handshake (required here to get TLS state).
	if err := tlsConn.Handshake(); err != nil {
		logger.Error("TLS Handshake (client) failed", "err", err)
		return false
	}
	logger.Info("TLS Handshake (client) succeeded.")
	conn = net.Conn(tlsConn)
	scanner = bufio.NewScanner(conn)

在需要启动 TLS 协议时,代码会创建一个新的 TLS 配置并升级现有的 TCP 连接为 TLS 连接。成功完成 TLS 握手后,继续使用 tlsConn 进行数据交换。

8. 完成探测并返回结果

最后,ProbeTCP 函数会返回 true,表示探测成功。

return true

总结

本文深入分析了 blackbox_exporter 中的 ProbeTCP 函数,详细解释了如何通过 Go 实现 TCP 和 SSL/TLS 协议的探测功能。我们探讨了如何使用 Prometheus 指标暴露 SSL 证书的相关信息、如何处理正则表达式匹配失败以及如何升级到 TLS 连接等技术细节。希望这篇文章能帮助你更好地理解 TCP 协议探测的实现过程及其在监控中的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/950565.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA 撤销 merge 操作(详解)

作为一个开发者,我们都知道Git是一个非常重要的版本控制工具,尤其是在协作开发的过程中。然而,在使用Git的过程中难免会踩一些坑,今天我来给大家分享一个我曾经遇到的问题:在使用IDEA中进行merge操作后如何撤销错误的合…

WD5105同步降压转换器:9.2V-95V宽电压输入,4.5A大电流输出,95%高效率,多重保护功能

概述 • WD5105同步降压转换器 • 封装形式:QFN-20封装 • 应用场景:适用于车载充电器、电动车仪表、电信基站电源、电源适配器等 性能特点 • 输入电压范围:9.2V至95V • 输出电流:可提供4.5A连续负载电流 • 效率:高…

【C++】B2108 图像模糊处理

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述题目内容输入格式输出格式示例输入:输出: 💯题目分析问题拆解 💯我的做法代码实现代码分析 💯老师的做法…

怎么把word试题转成excel?

在教育行业、学校管理以及在线学习平台中,试题库的高效管理是一项核心任务。许多教育工作者和系统开发人员常常面临将 Word 中的试题批量导入 Excel 的需求。本文将详细介绍如何快速将试题从 Word 转换为 Excel,帮助您轻松解决繁琐的数据整理问题&#x…

minibatch时,损失如何记录

目录 minibatch时,损失如何记录 报错:UnboundLocalError: local variable coef referenced before assignment是什么回事 未溢出则不会报错,可以完整滴运行完成 indent 缩进 炫酷技能:一遍运行,一遍画图 实例1 解释…

Linux : Linux环境开发工具vim / gcc / makefile / gdb / git的使用

Linux环境开发工具的使用 一、操作系统的生态二、程序下载安装(一)程序安装方式(二)包管理器 yum / apt 运行原理 三、文本编辑器 vim(一)认识vim 下的操作模式(二)命令模式常用的快…

国产游戏崛起,燕云十六移动端1.9上线,ToDesk云电脑先开玩

游戏爱好者的利好消息出新了!网易大型武侠仙游《燕云十六声》正式官宣,移动端要在1月9日正式上线了!你期待手游版的燕云吗?不妨评论区留言说说你的看法。小编分别花了几个小时在台式机电脑和手机上都试了下,欣赏画面还…

力扣刷题:数组OJ篇(下)

大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 目录 1.轮转数组(1)题目描述…

有序数据中插入不确定数据保证数据插入的位置顺序正确排序

解决有序数据中插入不确定数据保证数据插入的位置顺序正确排序 前言 java 数据库中存储自增id 有序的数据, 前端页面基于 id 5和 6 之间新增一条数据,在 id 6 和 7之间新增 2条,或者更复杂的场景,后台接口如何保存数据使得页面数…

python无需验证码免登录12306抢票 --selenium(2)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 [TOC](python无需验证码免登录12306抢票 --selenium(2)) 前言 提示:这里可以添加本文要记录的大概内容: 就在刚刚我抢的票:2025年1月8日…

DNS协议漏洞利用实验_hust计算机网络安全实验

文章目录 计算机网络安全实验 DNS协议漏洞利用实验 docker使用 建立实验环境docker常用指令 一些注意事项设置本地 DNS 服务器 配置用户计算机设置本地DNS服务器在本地 DNS 服务器中建一个区域 修改主机文件(可略)netwox实施DNS的用户响应欺骗攻击netwo…

基于MP157AAA的I2C练习

练习要求: 通过I2C分别实现与芯片si7006(获取湿度、温度)和芯片ap3216(获取环境光照强度)的通讯; 1、运行效果 2、分析ap3216如何获取光照强度 2.1、需要操作的寄存器 通过分析手册,需要操作以下寄存器: 0x00:系统配置 0x0C&…

【Linux】深入理解文件系统(超详细)

目录 一.磁盘 1-1 磁盘、服务器、机柜、机房 📌补充: 📌通常网络中用高低电平,磁盘中用磁化方向来表示。以下是具体说明: 📌如果有一块磁盘要进行销毁该怎么办? 1-2 磁盘存储结构 ​编辑…

网络安全图谱以及溯源算法

​ 本文提出了一种网络攻击溯源框架&#xff0c;以及一种网络安全知识图谱&#xff0c;该图由六个部分组成&#xff0c;G <H&#xff0c;V&#xff0c;A&#xff0c;E&#xff0c;L&#xff0c;S&#xff0c;R>。 1|11.知识图 ​ 网络知识图由六个部分组成&#xff0c…

《Spring Framework实战》7:4.1.2.容器概述

欢迎观看《Spring Framework实战》视频教程 容器概述 该接口表示 Spring IoC 容器&#xff0c;并负责实例化、配置和组装 bean。 容器在组件上获取其指令&#xff0c;以实例化、配置和 通过读取配置元数据进行汇编。可以表示配置元数据 作为带注释的组件类、具有工厂方法的配置…

学生公寓技术规格书如何编写?

学生公寓限电柜的技术规格书主要包括以下内容‌&#xff1a; ‌用电计量计费‌&#xff1a;限电柜可以通过计算机售电管理系统进行用电计量计费&#xff0c;学生需要预交电费&#xff0c;系统会自动将数据传给控电柜和配电箱&#xff0c;对宿舍的电量进行累减计量‌。 ‌时间控…

【HarmonyOS NEXT】鸿蒙应用点9图的处理(draw9patch)

【HarmonyOS NEXT】鸿蒙应用点9图的处理&#xff08;draw9patch&#xff09; 一、前言&#xff1a; 首先在鸿蒙中是不支持安卓 .9图的图片直接使用。只有类似拉伸的处理方案&#xff0c;鸿蒙提供的Image组件有与点九图相同功能的API设置。 可以通过设置resizable属性来设置R…

SpringBoot 使用 Cache 集成 Redis做缓存保姆教程

1. 项目背景 Spring Cache是Spring框架提供的一个缓存抽象层&#xff0c;它简化了缓存的使用和管理。Spring Cache默认使用服务器内存&#xff0c;并无法控制缓存时长&#xff0c;查找缓存中的数据比较麻烦。 因此Spring Cache支持将缓存数据集成到各种缓存中间件中。本文已常…

MySQL事件功能简介

MySQL 的事件调度器&#xff08;Event Scheduler&#xff09;提供了一种便捷的方法来定时执行 SQL 语句&#xff0c;从而实现数据维护、报告生成等自动化操作。本文将详细介绍 MySQL 的事件功能&#xff0c;并说明如何使用 Navicat 管理这些事件。 1. 什么是 MySQL 事件调度器…

高光谱相机的特点

光谱特性 高光谱分辨率&#xff1a;能将光谱范围分割成极窄的波段&#xff0c;光谱分辨率通常达到纳米级甚至亚纳米级&#xff0c;可精确捕捉到不同物质在细微光谱差异上的特征&#xff0c;比如可以区分不同种类的植被因叶绿素含量等差异而在光谱上的细微变化。 多波段探测&a…