diff options
author | Tuomas Jaakola <tuomas.jaakola@iki.fi> | 2011-07-22 13:24:58 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2011-07-22 13:31:18 +0300 |
commit | fcca67d52532a16ef0e9cbbecf2c623582364ab5 (patch) | |
tree | b6c110653118e283bbc3c99defffd4de45bb1394 | |
parent | a1f9da29de6d5abcb0adb7bfa4a4baeb9d930a08 (diff) | |
download | acf-dnsmasq-fcca67d52532a16ef0e9cbbecf2c623582364ab5.tar.bz2 acf-dnsmasq-fcca67d52532a16ef0e9cbbecf2c623582364ab5.tar.xz |
Support for DNS filtering added
-rw-r--r-- | dnsmasq-config-html.lsp | 12 | ||||
-rw-r--r-- | dnsmasq-model.lua | 120 |
2 files changed, 120 insertions, 12 deletions
diff --git a/dnsmasq-config-html.lsp b/dnsmasq-config-html.lsp index edfe950..a9db81a 100644 --- a/dnsmasq-config-html.lsp +++ b/dnsmasq-config-html.lsp @@ -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> <% diff --git a/dnsmasq-model.lua b/dnsmasq-model.lua index 1e6c5b8..b2a6465 100644 --- a/dnsmasq-model.lua +++ b/dnsmasq-model.lua @@ -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 |