FEATURE: rolls up 1.2.*.* IP ranges when number of entries > 10

This commit is contained in:
Régis Hanol
2014-11-27 19:29:30 +01:00
parent 062e954122
commit 5b90ceb71d
5 changed files with 99 additions and 17 deletions

View File

@ -29,21 +29,51 @@ class Admin::ScreenedIpAddressesController < Admin::AdminController
render json: success_json
end
def roll_up
# 1 - retrieve all subnets that needs roll up
sql = <<-SQL
SELECT network(inet(host(ip_address) || './24')) AS ip_range
def star_subnets_query
@star_subnets_query ||= <<-SQL
SELECT network(inet(host(ip_address) || '/24')) AS ip_range
FROM screened_ip_addresses
WHERE action_type = :action_type
WHERE action_type = #{ScreenedIpAddress.actions[:block]}
AND family(ip_address) = 4
AND masklen(ip_address) = 32
GROUP BY ip_range
HAVING COUNT(*) >= :min_count
SQL
end
subnets = ScreenedIpAddress.exec_sql(sql,
action_type: ScreenedIpAddress.actions[:block],
min_count: SiteSetting.min_ban_entries_for_roll_up).values.flatten
def star_star_subnets_query
@star_star_subnets_query ||= <<-SQL
WITH weighted_subnets AS (
SELECT network(inet(host(ip_address) || '/16')) AS ip_range,
CASE masklen(ip_address)
WHEN 32 THEN 1
WHEN 24 THEN :roll_up_weight
ELSE 0
END AS weight
FROM screened_ip_addresses
WHERE action_type = #{ScreenedIpAddress.actions[:block]}
AND family(ip_address) = 4
)
SELECT ip_range
FROM weighted_subnets
GROUP BY ip_range
HAVING SUM(weight) >= :min_count
SQL
end
def star_subnets
min_count = SiteSetting.min_ban_entries_for_roll_up
ScreenedIpAddress.exec_sql(star_subnets_query, min_count: min_count).values.flatten
end
def star_star_subnets
weight = SiteSetting.min_ban_entries_for_roll_up
ScreenedIpAddress.exec_sql(star_star_subnets_query, min_count: 10, roll_up_weight: weight).values.flatten
end
def roll_up
# 1 - retrieve all subnets that needs roll up
subnets = [star_subnets, star_star_subnets].flatten
# 2 - log the call
StaffActionLogger.new(current_user).log_roll_up(subnets) unless subnets.blank?
@ -63,25 +93,23 @@ class Admin::ScreenedIpAddressesController < Admin::AdminController
MIN(created_at) AS min_created_at,
MAX(last_match_at) AS max_last_match_at
FROM screened_ip_addresses
WHERE action_type = :action_type
WHERE action_type = #{ScreenedIpAddress.actions[:block]}
AND family(ip_address) = 4
AND masklen(ip_address) = 32
AND ip_address << :ip_address
) s
WHERE ip_address = :ip_address
SQL
ScreenedIpAddress.exec_sql(sql, action_type: ScreenedIpAddress.actions[:block], ip_address: subnet)
ScreenedIpAddress.exec_sql(sql, ip_address: subnet)
# 5 - remove old matches
ScreenedIpAddress.where(action_type: ScreenedIpAddress.actions[:block])
.where("family(ip_address) = 4")
.where("masklen(ip_address) = 32")
.where("ip_address << ?", subnet)
.delete_all
end
render json: success_json
render json: success_json.merge!({ subnets: subnets })
end
private