我使用 CIDR 过滤器来检查 IP 是否在某些子网内。 我需要:
cidr {
id => "netflow-postproc-cidr-src_addr"
address => [ "%{[@metadata][netflow][src_addr]}" ]
network => [ "0.0.0.0/32", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fc00::/7", "127.0.0.0/8", "::1/128", "169.254.0.0/16", "fe80::/10", "224.0.0.0/4", "ff00::/8", "255.255.255.255/32", "::" ]
add_field => { "[@metadata][netflow][src_locality]" => "private" }
}
我需要的是获取哪个子网具有匹配的IP,而不仅仅是“至少一个”。
例如,如果我有 172.16.0.10,我需要用 172.16.0.0/12 填写新字段
举例说明我需要什么
cidr {
id => "netflow-cidr-src_addr"
address => [ "%{[@metadata][netflow][src_addr]}" ]
network_path => "/etc/logstash/dictionaries/internal_subnet.yml"
add_field => { "[@metadata][netflow][src_subnet]" => "<subnet_that_match>" }
}
如果您需要对 13 个网络中的每一个进行不同的标记,那么您将需要使用 13 个不同的 cidr 过滤器。
似乎没有解决方案,所以我找到了解决方法。 了解每个 CIDR,我编写了一个 python 程序来为每个子网中的每个 IP 创建一个 memcached 条目。
all_su = Subnet.objects.all()
for iss in all_su:
net = ip_network(iss.cidr)
## ITERATING ALL IP INSIDE CIDR
for i in net:
#creating memcached entry
所以在 memcahced 中我有这样的东西:
subnet-namespace:172.16.0.10-subnet-cidr = 172.16.0.0/12
subnet-namespace:172.16.0.11-subnet-cidr = 172.16.0.0/12
subnet-namespace:172.16.0.12-subnet-cidr = 172.16.0.0/12
[...]
然后在logstash中我可以使用默认过滤器签入memcached:
memcached {
hosts => ["localhost:11211"]
namespace => "subnet-namespace"
get => {
"%{[source][ip]}-subnet-cidr" => "[source][subnet]
}
add_tag => ["source_subnet_cached"]
}
您可以尝试使用 ruby 过滤器。
我这里有一个类似的用例,我需要使用有关源网络的信息来标记事件。
我们的域中有数百个范围,这些解决方案在我的环境中表现非常好。
我使用 CIDR 过滤器来识别 IP 是否属于任何内部网络 cidrs,然后使用 ruby 过滤器查看 json 文件 由使用 CIDR 作为密钥的单个对象组成。
如果您有子网地理位置数据,您甚至可以包含地理定位数据。
JSON 文件是这样的:
{
"10.0.0.0/24": {
"network_name": "network_of_division_1",
"network_region": "SouthWest",
"city": "some_city_name",
"latitude": 10,
"longitude": 20,
"province": "some_province_name"
},
"10.0.120.0/24":
"network_name": "network_of_division_2",
"network_region": "North",
"city": "some_city_name",
"latitude": 10,
"longitude": 20,
"province": "some_province_name"
},
...
}
过滤器代码如下:
filter{
# remove field if IP is not valid
if [source_ip] !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ {
mutate{
remove_field => ["source_ip"]
}
} else {
# Tag for IPs in internal ranges
cidr{
address => "%{source_ip}"
network => [ "10.0.0.0/8", "172.0.0.0/12", "192.168.0.0/16" ]
add_field => { "[CIP]" => "1" }
}
# Tag if IP is localhost
cidr{
address => "%{source_ip}"
network => ["0.0.0.0/32","127.0.0.0/8"]
add_field => {"[LOOPBACK]" => 1 }
}
}
if [source_ip] and ![LOOPBACK]{
# If IP is in internal ranges
if [CIP] {
ruby {
# Load the hash with network information
init => "
require 'json'
require 'ipaddr'
# Load json with information about the networks the structure is an object with the cidr as keys
networks = File.read('networks.json')
# Transform keys into strings - so you can use it
@@data_hash = JSON.parse(networks).transform_keys(&:to_s)
# Transform keys into IPAddr to perform the matching with CIDR
@@networks = @@data_hash.keys.map do |net_string|
IPAddr.new(net_string)
end
"
code => "
# Get source IP and transform it into an IPAddr obj
source_ip_string = event.get('source_ip')
source_ip_obj = IPAddr.new(source_ip_string)
# Set a variable to stop the loop immediatly once the network has been found
found = false
# Loop through the hash of networks
for net in @@networks do
break if found != false
if net === source_ip_obj
found = true
# Get a pointer to the network object
net_string = net.to_s + '/' + net.prefix.to_s
net_data = @@data_hash[net_string]
# Insert the data accordinglly ie.:
event.set('source_network', net_string)
event.set('source_network_name', net_data['network_name'])
event.tag(net_string)
end
end
"
}
}
}
}
希望有帮助。