Kusto下登录日志IP与恶意IP范围匹配实现及报错解决问询
解决方案
你的报错根源是自定义函数返回表结构,无法直接作为iff()的布尔判断参数,以下是两种可直接运行的修复方案:
方案1:修改自定义函数返回标量值
直接调整你的GetPackage函数,用toscalar()将查询结果转为标量,匹配成功返回对应恶意IP段,匹配失败返回空值,改动最小适配原有逻辑,适合数据量较小的场景:
let GetPackage = (v_IPAddress: string){ toscalar( _GetWatchlist('Bad_IP_Ranges') | where ipv4_is_in_range(v_IPAddress, IPAddress) | take 1 // 匹配到第一条就返回,避免多匹配的重复结果 | project IPAddress ) }; SigninLogs | union AADNonInteractiveUserSignInLogs | extend Malicious_IP = coalesce(GetPackage(IPAddress), "null") | project TimeGenerated, Category, ResultType, ResultDescription, Identity, Malicious_IP, AppDisplayName | order by TimeGenerated | take 1000
方案2:高性能无函数写法(推荐大数据量场景)
逐行调用自定义函数在日志量级大时会出现明显性能问题,改用左连接+聚合的写法性能提升显著:
// 提前拉取所有恶意IP段 let BadIPRanges = _GetWatchlist('Bad_IP_Ranges') | project BadRange = IPAddress; // 拉取所有登录事件 let SigninEvents = union SigninLogs, AADNonInteractiveUserSignInLogs | project TimeGenerated, Category, ResultType, ResultDescription, Identity, IPAddress, AppDisplayName; SigninEvents | extend dummy = 1 // 新增临时字段用于关联 | join kind=leftouter (BadIPRanges | extend dummy = 1) on dummy // 过滤出未匹配/匹配成功的条目 | where isempty(BadRange) or ipv4_is_in_range(IPAddress, BadRange) // 每个登录事件聚合成一条,多匹配时取第一个命中的IP段 | summarize Malicious_IP = coalesce(make_list(BadRange)[0], "null") by TimeGenerated, Category, ResultType, ResultDescription, Identity, AppDisplayName | order by TimeGenerated | take 1000
注意事项
- 请确保
Bad_IP_Ranges监视列表的IP字段格式符合ipv4_is_in_range要求,支持CIDR(如192.168.1.0/24)、范围格式(如192.168.1.1-192.168.1.10)两种写法 - 如果需要保留所有命中的恶意IP段,只需把
make_list(BadRange)[0]改为strcat_array(make_list(BadRange), ",")即可
内容的提问来源于stack exchange,提问作者Matt M
相关产品推荐
相关产品推荐

