socket.gethostbyname多IP选择逻辑及解析zoidberg返回127.0.0.1异常排查
socket.gethostbyname()解析私有主机IP异常的原因排查
核心问题
我的/etc/hosts配置了:
10.1.2.3 zoidberg.local zoidberg
但Python的socket.gethostbyname('zoidberg')突然返回127.0.0.1,导致HTTPServer绑定到回环地址而非10.1.2.3,而ping、curl、Chrome等其他工具仍能正确解析zoidberg到10.1.2.3。该配置多年来一直正常,最近几天突然出现异常。
背景信息
- 运行环境:macOS 10.15,Python 3.8
- 多年来zoidberg始终映射到10.1.2.3,/etc/hosts从未修改
- 本地Python服务器一直使用
('zoidberg', 8888)作为监听地址,之前均绑定到10.1.2.3,现在通过netstat -an排查发现绑定到127.0.0.1,导致服务无法被外部访问 - 追踪Python标准库代码发现,TCPServer通过
socket.gethostbyname()解析主机地址,问题根源在此函数;该函数属于C接口,无法通过Python代码追踪逻辑
已排查的常见原因
- /etc/hosts配置无任何修改
- 已关闭系统自动更新,数月未进行系统更新
- ping、curl、Chrome等工具均能正确解析zoidberg到10.1.2.3
- Chrome近期自动更新,但不认为会影响系统级的名称解析逻辑
- 仅通过port安装过几个Python模块,PYTHONPATH包含/opt/local目录,但不认为会影响解析逻辑
关键发现(更新)
注释解析异常:
最初/etc/hosts的zoidberg条目带有# loopback注释,Python将#和loopback也视为zoidberg的别名,执行结果如下:>>> socket.gethostbyname_ex ('zoidberg') ('zoidberg.local', ['zoidberg','#','loopback'], ['10.1.2.3', '127.0.0.1', '192.168.1.62', '169.254.1.28', '10.1.2.3'])但ping
loopback或#时提示无法解析,说明ping与Python socket的解析逻辑存在差异。移除注释后仍异常:
删除/etc/hosts中的# loopback注释后,别名问题消失,但解析结果依旧异常:>>> socket.gethostbyname ('zoidberg') '127.0.0.1' >>> socket.gethostbyname_ex ('zoidberg') ('zoidberg.local', ['zoidberg'], ['10.1.2.3', '127.0.0.1', '192.168.1.62', '169.254.1.28', '10.1.2.3'])此时测试C语言的
gethostbyname函数,返回的IP列表与Python完全一致,但其他系统工具仍能正确解析到10.1.2.3。异常点总结:
- 10.1.2.3在IP列表中重复出现两次,原因未知
- 127.0.0.1未在/etc/hosts中与zoidberg关联,但出现在解析列表中,推测可能因为10.1.2.3和127.0.0.1同属macOS的lo0回环设备
gethostbyname_ex返回的列表包含本机所有网卡的IP(WiFi的192.168.1.62、以太网的169.254.1.28),这些IP并未在/etc/hosts中配置gethostbyname仅返回列表中的第二个IP(127.0.0.1),而非第一个配置的10.1.2.3
待解疑问
- 为何Python的
gethostbyname_ex会获取本机所有网卡的IP?是否存在轮询所有网卡的逻辑? - 为何
gethostbyname突然选择127.0.0.1而非10.1.2.3?之前多年都正常返回10.1.2.3,触发这一变化的因素是什么? - 是否存在恶意软件干扰解析逻辑的可能?
内容的提问来源于stack exchange,提问作者Ed_
相关产品推荐
相关产品推荐

