Skip to content
Snippets Groups Projects
Forked from Knot projects / Knot Resolver
8408 commits behind the upstream repository.
block.lua 2.39 KiB
local block = {
	-- Policies
	PASS = 1, DENY = 2, DROP = 3,
	-- Special values
	ANY = 0,
	-- Private, local, broadcast, test and special zones 
	private_zones = {
		-- RFC1918
		'10.in-addr.arpa.',
		'16.172.in-addr.arpa.',
		'17.172.in-addr.arpa.',
		'18.172.in-addr.arpa.',
		'19.172.in-addr.arpa.',
		'20.172.in-addr.arpa.',
		'21.172.in-addr.arpa.',
		'22.172.in-addr.arpa.',
		'23.172.in-addr.arpa.',
		'24.172.in-addr.arpa.',
		'25.172.in-addr.arpa.',
		'26.172.in-addr.arpa.',
		'27.172.in-addr.arpa.',
		'28.172.in-addr.arpa.',
		'29.172.in-addr.arpa.',
		'30.172.in-addr.arpa.',
		'31.172.in-addr.arpa.',
		'168.192.in-addr.arpa.',
		-- RFC5735, RFC5737
		'0.in-addr.arpa.',
		'127.in-addr.arpa.',
		'254.169.in-addr.arpa.',
		'2.0.192.in-addr.arpa.',
		'100.51.198.in-addr.arpa.',
		'113.0.203.in-addr.arpa.',
		'255.255.255.255.in-addr.arpa.',
		-- IPv6 local, example
		'0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.',
		'1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.',
		'd.f.ip6.arpa.',
		'8.e.f.ip6.arpa.',
		'9.e.f.ip6.arpa.',
		'a.e.f.ip6.arpa.',
		'b.e.f.ip6.arpa.',
		'8.b.d.0.1.0.0.2.ip6.arpa',
	}
}

-- @function Block requests which QNAME matches given zone list
function block.in_zone(zone_list)
	return function(pkt, qry)
		local qname = pkt:qname()
		for _,zone in pairs(zone_list) do
			if qname:sub(-zone:len()) == zone then
				return block.DENY
			end
		end
		return nil
	end
end

-- @function Evaluate packet in given rules to determine block action
function block.evaluate(block, pkt, qry)
	for _,rule in pairs(block.rules) do
		local action = rule(pkt, qry)
		if action then
			return action
		end
	end
	return block.PASS
end
-- @function Block layer implementation
block.layer = {
	produce = function(state, data, pkt)
		-- Only when a query isn't already answered
		if state ~= kres.CONSUME then
			return state
		end
		-- @todo Interpret QUERY (as it has final name)
		-- Interpret packet in Lua and evaluate
		local pkt = kres.packet(pkt)
		local action = block:evaluate(pkt, nil)
		if action == block.DENY then
			pkt:flag(kres.wire.QR)
			pkt:flag(kres.wire.AA)
			pkt:flag(kres.wire.CD)
			pkt:rcode(kres.rcode.NXDOMAIN)
			-- @todo add SOA record
			return kres.DONE
		elseif action == block.DROP then
			return kres.FAIL
		else
			return state
		end
	end
}

-- @var Default rules
block.rules = { block.in_zone(block.private_zones) }

return block