Commit fcca67d5 authored by Tuomas Jaakola's avatar Tuomas Jaakola Committed by Timo Teräs
Browse files

Support for DNS filtering added

parent a1f9da29
......@@ -20,13 +20,23 @@ end %>
displayformitem(form.value.domain, "domain")
%>
</DL>
<H2>DNS Parameters</H2>
<H2>DNS settings</H2>
<H3>DNS Parameters</H3>
<DL>
<%
displayformitem(form.value.mx_host, "mx_host")
%>
</DL>
<H3>DNS filtering</H3>
<DL>
<%
displayformitem(form.value.dns_filtering, "dns_filtering")
displayformitem(form.value.dns_whitelist, "dns_whitelist")
displayformitem(form.value.dns_default_address, "dns_default_address")
%>
</DL>
<H2>DHCP Parameters</H2>
<DL>
<%
......
......@@ -11,6 +11,7 @@ local configfile = "/etc/dnsmasq.conf"
local processname = "dnsmasq"
local packagename = "dnsmasq"
local leasefile = "/var/lib/misc/dnsmasq.leases"
local dnsfilterfile = "/etc/dnsmasq-dnsfilter.conf"
-- ################################################################################
-- LOCAL FUNCTIONS
......@@ -47,11 +48,8 @@ local function update_file (file, search_name, value_in)
if a and (search_name == a) then
-- Figure out the value
local b = string.match ( l, '=%s*(.*%S)%s*$' ) or ""
-- remove comments from end of line
if string.find ( b, '#' ) then
b = string.match ( b, '^(.*%S)%s*#.*$' ) or ""
end
-- no need to remove comments from end of line, they
-- should not be there, see 'man dnsmasq'
-- We found the name, change the value
if not value then
l = nil
......@@ -124,11 +122,8 @@ local function parse_file (file)
if a then
-- Figure out the value
local b = string.match ( l, '=%s*(.*%S)%s*$' ) or ""
-- remove comments from end of line
if string.find ( b, '#' ) then
b = string.match ( b, '^(.*%S)%s*#.*$' ) or ""
end
-- no need to remove comments from end of line, they
-- should not be there, see 'man dnsmasq'
if not (opts) then opts = {} end
if not opts[a] then
opts[a] = {b}
......@@ -157,7 +152,14 @@ local function validateconfig(config)
end
end
end
function testtext(param, test, errtxt)
if test(param.value) then
param.errtxt = errtxt
success = false
end
end
testlist(config.value.domain, function(v) return string.find(v, "%s") end, "Cannot contain spaces")
testlist(config.value.interface, function(v) return string.find(v, "%W") end, "Illegal character")
testlist(config.value.listen_address, function(v) return not validator.is_ipv4(v) end, "Invalid IP Address")
......@@ -166,10 +168,94 @@ local function validateconfig(config)
testlist(config.value.dhcp_host, function(v) return string.find(v, "%s") end, "Cannot contain spaces")
testlist(config.value.dhcp_option, function(v) return string.find(v, "%s") end, "Cannot contain spaces")
testlist(config.value.mx_host, function(v) return string.find(v, "%s") end, "Cannot contain spaces")
if config.value.dns_filtering.value then
-- validate ip address only if dns filtering is enabled
testtext(config.value.dns_default_address, function(v) return not validator.is_ipv4(v) end, "Invalid IP Address")
end
return success, config
end
local function dns_filtering_is_enabled(conf)
-- Returns true if dnsfilterfile is included in configfile.
-- conf - config variable from parse_file()
local conf_files = conf["conf-file"] or {}
for i,conf_file in ipairs(conf_files) do
if conf_file == dnsfilterfile then
return true
end
end
return false
end
local function set_dns_filtering(file, enable)
-- Returns new table of conf["conf-file"].
-- Includes existing conf-files and adds or removes dnsfilterfile.
-- file - config data
-- enabled - boolean for dns filtering
local conf = parse_file(file) or {}
local enabled = dns_filtering_is_enabled(conf)
local conf_files = conf["conf-file"] or {}
if enabled ~= enable then
-- state changed, we have to modify conf_files table
if enable then
-- add dnsfilterfile to conf-files
table.insert(conf_files, dnsfilterfile)
else
-- remove dnsfilterfile from conf-files
for i,conf_file in ipairs(conf_files) do
if conf_file == dnsfilterfile then
table.remove(conf_files, i)
break
end
end
end
end
return conf_files
end
local function update_dns_whitelist(servers, default_address)
-- Updates dnsfilterfile
-- servers - value from web form as table
local file = fs.read_file(dnsfilterfile) or ""
local serverlines = {}
for i,server in ipairs(servers or {}) do
local modified = "/" .. server .. "/#"
table.insert(serverlines, modified)
end
file = update_file(file, "server", serverlines)
-- update address to point to default_address
file = update_file(file, "address", "/#/" .. default_address)
fs.write_file(dnsfilterfile, file)
return true
end
local function parse_whitelist(file)
-- Parses dnsfilterfile and returns table of servers and
-- default address.
-- Format should be in:
-- server=/whitelisted.com/#
-- server=/another.com/#
-- address=/#/192.168.1.1
local servers = {}
local parsed = parse_file(file) or {}
local serverlines = parsed["server"] or {}
for i,value in ipairs(serverlines) do
-- remove '/' and '/#' from value
local server = string.match(value, "^/%s*([^=]*%S)%s*/#")
table.insert(servers, server)
end
-- parse default address
local default_address = ""
local addresses = parsed["address"] or {}
if #addresses > 0 then
-- get first address, anyway there shouldn't be more than 1?
default_address = string.match(addresses[1], "^/#/(.*%S)")
end
return servers, default_address
end
-- ################################################################################
-- PUBLIC FUNCTIONS
......@@ -183,6 +269,9 @@ end
function getconfig()
local conf = parse_file(fs.read_file(configfile) or "") or {}
local dns_filtering = {}
dns_filtering.enabled = dns_filtering_is_enabled(conf)
dns_filtering.whitelist, dns_filtering.default_address = parse_whitelist(fs.read_file(dnsfilterfile) or "")
local output = {}
output.domain = cfe({ type="list", value=conf.domain or {}, label="Local Domain",
......@@ -196,6 +285,9 @@ function getconfig()
output.dhcp_option = cfe({ type="list", value=conf["dhcp-option"] or {}, label="DHCP Option", descr="List of different or extra options to DHCP clients. See dnsmasq documentation." })
output.mx_host = cfe({ type="list", value=conf["mx-host"] or {}, label="MX Record", descr="List of MX records 'mx_name,hostname'." })
output.dns_filtering = cfe({ type="boolean", value=dns_filtering.enabled or false, label="DNS filtering enabled", descr="State of DNS filtering." })
output.dns_whitelist = cfe({ type="list", value=dns_filtering.whitelist or {}, label="DNS whitelist", descr="DNS whitelist for filtering. Type one allowed domain per one line." })
output.dns_default_address = cfe({ type="text", value=dns_filtering.default_address or "", label="Blocked page server address", descr="All DNS requests which are not on the white list, will be redirected to this IP address. This address should have a web server running that shows an address blocked page. Example: 192.168.1.1" })
return cfe({ type="group", value=output, label="DNS Masq Config" })
end
......@@ -212,11 +304,17 @@ function setconfig(config)
file = update_file(file,"dhcp-host",config.value.dhcp_host.value)
file = update_file(file,"dhcp-option",config.value.dhcp_option.value)
file = update_file(file,"mx-host",config.value.mx_host.value)
-- dns filtering
local conf_file_value = set_dns_filtering(file, config.value.dns_filtering.value)
file = update_file(file,"conf-file",conf_file_value)
fs.write_file(configfile, file)
else
config.errtxt = "Failed to set config"
end
-- update dns filter file
update_dns_whitelist(config.value.dns_whitelist.value, config.value.dns_default_address.value)
return config
end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment