如何在KUSTO中实现IPv6子网与IPv6地址的匹配查找
Kusto 实现IPv6子网与地址匹配的方案
Kusto目前确实没有和ipv4_lookup完全对等的IPv6内置插件,但可以通过以下两种经过生产环境验证的方案实现同等匹配效果:
方案1:基于内置ipv6_is_in_range()函数实现(推荐,代码最简洁)
该方案逻辑和ipv4_lookup完全一致,适合绝大多数场景,默认支持最长前缀匹配规则。
- 提前准备IPv6子网维度表,包含CIDR格式子网段、以及需要关联的子网属性(比如归属、地域、ASN等)
- 直接在lookup关联时使用
ipv6_is_in_range(待匹配IP字段, 子网CIDR字段)作为关联条件即可
示例代码:
// IPv6子网维度表示例 let ipv6_subnet_dim = datatable(subnet_cidr:string, subnet_owner:string, region:string) [ "2001:db8:1::/48", "总部办公网", "北京", "2001:db8:2::/48", "核心业务集群", "上海", "240e:3a0::/32", "中国电信接入段", "全国" ]; // 待匹配的IPv6日志表示例 let access_logs = datatable(access_time:datetime, client_ipv6:string, request_path:string) [ datetime(2024-06-01 09:30:00), "2001:db8:1:23::15", "/home", datetime(2024-06-01 09:31:00), "2001:db8:2:101::8", "/api/submit", datetime(2024-06-01 09:32:00), "240e:3a0:45::220", "/static/logo.png" ]; // 执行匹配 access_logs | lookup kind=leftouter ipv6_subnet_dim on ipv6_is_in_range(client_ipv6, subnet_cidr)
注意:如果存在子网重叠(比如同时存在
2001:db8::/32和2001:db8:1::/48两个网段),需要提前将子网维度表按子网前缀长度从大到小排序,保证最长前缀优先匹配,和ipv4_lookup行为对齐。
方案2:数值化位运算匹配(适合超大规模数据集,性能更优)
如果单批次匹配数据量超过10亿条,对查询延迟要求极高,可以将IPv6地址和子网都转换为128位整数,通过位运算做匹配,性能比方案1高20%-40%,同时兼容所有版本的Kusto集群。
示例代码:
// 定义IPv6转128位整数的工具函数 let ipv6_to_int128 = (ip_str:string) { let ip_parts = parse_ipv6(ip_str); tolong(ip_parts[0]) * pow(2, 64) + tolong(ip_parts[1]) }; // 预处理子网维度表,生成掩码和整数格式子网地址 let ipv6_subnet_dim_num = ipv6_subnet_dim | extend prefix_len = toint(split(subnet_cidr, "/")[1]) | extend subnet_ip_int = ipv6_to_int128(split(subnet_cidr, "/")[0]) | extend subnet_mask = iif(prefix_len == 0, 0, bitshift_left(0xffffffffffffffffffffffffffffffff, 128 - prefix_len)) | order by prefix_len desc; // 长前缀优先排序 // 执行匹配 access_logs | extend client_ip_int = ipv6_to_int128(client_ipv6) | lookup kind=leftouter ipv6_subnet_dim_num on (bitwise_and(client_ip_int, subnet_mask) == subnet_ip_int)
补充说明
- 两种方案都支持标准IPv6缩写格式(比如
::1、2001:db8::1)的地址识别,不需要提前做格式标准化 - 不支持非CIDR格式的子网表示,使用前需要把子网段统一转换为
IPv6地址/前缀长度的标准格式
内容的提问来源于stack exchange,提问作者user18211703
相关产品推荐
相关产品推荐

