Golang中的mDNS问题处理(mDNS系列3)
起因
为了在Windows上跨平台编译Linux上运行的Golang程序,选择了CGO_ENABLED=0。此时DNS解析也被切换至了纯Go版本的解析器上,而这个版本的解析器不支持mDNS。为了方便我在自家使用mDNS,便有了下文的方案探究。
分析
首先查找了一些官方文档,发现官方明确短期内是不会在纯Go版本的解析器上支持mDNS的,具体详见参考1。为了通用,便想到了monkey patch这一方式去处理,而这种在Python很好处理的方案,在Golang中却并不好写。
在我目前写的代码中就gorm.io/gorm(gorm.io/driver/postgres)、github.com/influxdata/influxdb-client-go/v2这两部分库会用到mDNS,追了一下源码,发现会公共调用func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IPAddr, error)这个方法,那理论上只要处理它即可。之后查了使用较多的hook开源库,却发现gomonkey支持hook私有方法,但是hook后却没有办法调用原方法,而gohook支持调用原方法,却不支持hook私有方法。在衡量了一下处理难度后,决定对代码调用往上追踪一下,直到发现公有方法,之后在使用gohook处理。而这两个方法便是func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) 及 func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error)。
处理
完整版代码如下:
1 | package main |
之后在进入主流程前调用AddMDNSSupport即可,我个人是把调用放到了init函数当中了。注意使用时必须保证主机上avahi-resolve-address命令执行正常。