测试bind-9.8.1-P1 的edns的时候发现,google DNS解析的结果一直在跳,有时候在电信区,有时候在us区
于是给它打了第一个patch,让query log 支持edns的client subnet显示,便于排查
筛选下日志,发现很多edns请求不在我们的ecs ACL范围内,最终落到了google DNS IP 所在的us区域,推测应该是这个造成了google DNS 的错误缓存
于是,把ecs的default区域加入拦截
view "default_ecs" {
match-clients { ecs 0.0.0.0/0; ecs ::/0;};
... ...
};
这样一来,的确是响应了edns请求,结果却是更多的出现了default 区的结果(热数据),或者在client所属区域和default区结果之间跳动(冷数据)
听包,发现google DNS发送过来的请求Scope Netmask 都是0,如果ecs ACL拦截不成功到了default_ecs区域,最终被ecs 0.0.0.0/0; ecs ::/0; 拦截成功,导致返回的Scope Netmask变成了0
Scope Netmask 变为0意味着什么? 意味着这个结果集有效并且范围最大,从而污染所有的subnet client结果集
目前来看,只能给它打个patch
让client subnet 到了default区域的结果集Scope Netmask 为起address netmask长度,控制结果集的有效范围
测试下,把某个网段故意从ecs ACL挪走,让default ecs拦截看看响应是否是我们期待的
上线测试,目前服务正常
附上edns 文档,非常重要:
https://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-01
http://noops.me/?p=653
以上的显示EDNS 的代码存在bug, 需要初始化
char edbuf[ISC_NETADDR_FORMATSIZE] = { 0 };
这里需要特别解释下 为什么char数组初始化使用 {0}, 这里有个解释
it’s a C-style cast. That is, it converts 0 (which is a literal of type int) to char (the \0 character). That cast could have been avoided entirely by simply using the ‘\0’ literal.
测试char = 0; 的时候打印出来直接是null, 从stackoverflow的解释看是这么回事
https://stackoverflow.com/questions/10004297/what-does-char0-mean-in-c