Current File : //etc/mass_hosting.lua |
-- vim: set ts=2 expandtab:
require "apache2"
-- NOTE: apache2.DECLINED simply means that we're returning without modifying the request at all
-- Converts an IP string into an integer for trivial comparison
function ip_to_int(ip)
oct1, oct2, oct3, oct4 = string.match(ip, "(%d+)%.(%d+)%.(%d+)%.(%d+)")
return ((oct1 * 256 + oct2)*256+oct3)*256+oct4
end
network_list = {}
network_list_file = '/etc/mass_hosting.list'
-- Doing this here rather than in mass_hosting() provides a speed improvement under certain configurations
test_file = io.open(network_list_file)
if test_file then
for network in test_file:lines() do
table.insert(network_list, network)
end
io.close(test_file)
end
function mass_hosting(r)
test_ip = r.useragent_ip
--[[
Handle Ezoic customers.
This header is akin to X-Forwarded-For.
This has the potential to be abused, but Ezoic uses EC2 so we're short on viable
alternatives at this time.
]]--
if r.headers_in['X-Middleton-Ip'] then
test_ip = r.headers_in['X-Middleton-Ip']
end
-- We only care about POST requests right now
if r.method ~= 'POST' then
return apache2.DECLINED
end
-- Check for IPv4 IPs
if not string.match(test_ip, "%d+%.%d+%.%d+%.%d+") then
r:warn("useragent_ip is not an ipv4 IP; declining")
return apache2.DECLINED
end
ip_int_rep = ip_to_int(test_ip)
for idx, network in ipairs(network_list) do
-- Ignore comments
if string.find(network, '%#') == 1 then
goto continue
end
net_addr, maskbits = string.match(network, "(%d+%.%d+%.%d+%.%d+)/(%d+)")
-- Figure out how many host bits we're working with
hostbits = 32 - maskbits
--integer representation of the starting and ending IPs of the network space
base_int_rep = ip_to_int(net_addr)
max_int_rep = base_int_rep + (2^hostbits)
if (ip_int_rep >= base_int_rep and ip_int_rep <= max_int_rep) then
-- Found the connecting IP in a mass hosting network so return HTTP_FORBIDDEN
r:debug(string.format("Found %s inside %s", test_ip, network))
r.status = 403
return apache2.DONE
end
::continue::
end
-- If we got this far, we didn't find the IP listed so do nothing
r:debug(string.format("Unable to find %s inside any known networks", test_ip))
return apache2.DECLINED
end