diff options
-rw-r--r-- | awall/model.lua | 115 | ||||
-rw-r--r-- | awall/modules/filter.lua | 85 | ||||
-rw-r--r-- | json/services.json | 9 |
3 files changed, 121 insertions, 88 deletions
diff --git a/awall/model.lua b/awall/model.lua index ff747ff..b766532 100644 --- a/awall/model.lua +++ b/awall/model.lua @@ -223,12 +223,7 @@ function Rule:servoptfrags() if not self.service then return end - local function containskey(tbl, key) - for k, v in pairs(tbl) do if k == key then return true end end - return false - end - - local ports = {} + local fports = {inet={}, inet6={}} local res = {} for i, serv in ipairs(self.service) do @@ -236,15 +231,24 @@ function Rule:servoptfrags() if not sdef.proto then self:error('Protocol not defined') end if util.contains({6, 'tcp', 17, 'udp'}, sdef.proto) then - local new = not containskey(ports, sdef.proto) - if new then ports[sdef.proto] = {} end - - if new or ports[sdef.proto][1] then - if sdef.port then - util.extend(ports[sdef.proto], - util.maplist(sdef.port, - function(p) return string.gsub(p, '-', ':') end)) - else ports[sdef.proto] = {} end + for family, ports in pairs(fports) do + if not sdef.family or family == sdef.family then + + local new = not ports[sdef.proto] + if new then ports[sdef.proto] = {} end + + if new or ports[sdef.proto][1] then + if sdef.port then + util.extend( + ports[sdef.proto], + util.maplist( + sdef.port, + function(p) return string.gsub(p, '-', ':') end + ) + ) + else ports[sdef.proto] = {} end + end + end end else @@ -263,47 +267,62 @@ function Rule:servoptfrags() elseif sdef.type then self:error('Type specification not valid with '..sdef.proto) end - if sdef.type then opts = opts..' --'..oname..' '..sdef.type end + if sdef.family then + if not family then family = sdef.family + elseif family ~= sdef.family then + self:error( + 'Protocol '..sdef.proto..' is incompatible with '..sdef.family + ) + end + end + + if sdef.type then opts = opts..' --'..oname..' '..sdef.type end table.insert(res, {family=family, opts=opts}) end end end local popt = ' --'..(self.reverse and 's' or 'd')..'port' - for proto, plist in pairs(ports) do - local propt = '-p '..proto - - if plist[1] then - local len = #plist - repeat - local opts - - if len == 1 then - opts = propt..popt..' '..plist[1] - len = 0 - - else - opts = propt..' -m multiport'..popt..'s ' - local pc = 0 - repeat - local sep = pc == 0 and '' or ',' - local port = plist[1] - - pc = pc + (string.find(port, ':') and 2 or 1) - if pc > 15 then break end - - opts = opts..sep..port - - table.remove(plist, 1) - len = len - 1 - until len == 0 - end - - table.insert(res, {opts=opts}) - until len == 0 + for family, pports in pairs(fports) do + local ofrags = {} + + for proto, ports in pairs(pports) do + local propt = '-p '..proto + + if ports[1] then + local len = #ports + repeat + local opts + + if len == 1 then + opts = propt..popt..' '..ports[1] + len = 0 + + else + opts = propt..' -m multiport'..popt..'s ' + local pc = 0 + repeat + local sep = pc == 0 and '' or ',' + local port = ports[1] + + pc = pc + (string.find(port, ':') and 2 or 1) + if pc > 15 then break end + + opts = opts..sep..port + + table.remove(ports, 1) + len = len - 1 + until len == 0 + end + + table.insert(ofrags, {opts=opts}) + until len == 0 + + else table.insert(ofrags, {opts=propt}) end + end - else table.insert(res, {opts=propt}) end + util.extend(res, combinations(ofrags, {{family=family}})) end return res diff --git a/awall/modules/filter.lua b/awall/modules/filter.lua index 35c5f30..e44d129 100644 --- a/awall/modules/filter.lua +++ b/awall/modules/filter.lua @@ -27,6 +27,7 @@ function RelatedRule:servoptfrags() local helper = sdef['ct-helper'] if helper then helpers[helper] = { + family=sdef.family, opts='-m conntrack --ctstate RELATED -m helper --helper '..helper } end @@ -259,51 +260,59 @@ local fchains = {{chain='FORWARD'}, {chain='INPUT'}, {chain='OUTPUT'}} function stateful(config) local res = {} - local families = {{family='inet'}, {family='inet6'}} + for i, family in ipairs{'inet', 'inet6'} do - local er = combinations( - fchains, - {{opts='-m conntrack --ctstate ESTABLISHED'}} - ) - for i, chain in ipairs({'INPUT', 'OUTPUT'}) do - table.insert( - er, - { - chain=chain, - opts='-'..string.lower(string.sub(chain, 1, 1))..' lo' - } + local er = combinations( + fchains, + {{opts='-m conntrack --ctstate ESTABLISHED'}} ) - end - extend(res, combinations(families, er, {{table='filter', target='ACCEPT'}})) - - -- TODO avoid creating unnecessary CT rules by inspecting the - -- filter rules' target families and chains - local visited = {} - local ofrags = {} - for i, rule in listpairs(config.filter) do - for i, serv in listpairs(rule.service) do - if not visited[serv] then - for i, sdef in listpairs(serv) do - if sdef['ct-helper'] then - local of = model.Rule.morph({service={sdef}}):servoptfrags() - assert(#of == 1) - of[1].target = 'CT --helper '..sdef['ct-helper'] - table.insert(ofrags, of[1]) + for i, chain in ipairs({'INPUT', 'OUTPUT'}) do + table.insert( + er, + { + chain=chain, + opts='-'..string.lower(string.sub(chain, 1, 1))..' lo' + } + ) + end + extend( + res, + combinations(er, {{family=family, table='filter', target='ACCEPT'}}) + ) + + -- TODO avoid creating unnecessary CT rules by inspecting the + -- filter rules' target families and chains + local visited = {} + local ofrags = {} + for i, rule in listpairs(config.filter) do + for i, serv in listpairs(rule.service) do + if not visited[serv] then + for i, sdef in listpairs(serv) do + if sdef['ct-helper'] then + local of = combinations( + model.Rule.morph{service={sdef}}:servoptfrags(), + {{family=family}} + ) + if of[1] then + assert(#of == 1) + of[1].target = 'CT --helper '..sdef['ct-helper'] + table.insert(ofrags, of[1]) + end + end end + visited[serv] = true end - visited[serv] = true end end - end - extend( - res, - combinations( - families, - {{table='raw'}}, - {{chain='PREROUTING'}, {chain='OUTPUT'}}, - ofrags + extend( + res, + combinations( + {{table='raw'}}, + {{chain='PREROUTING'}, {chain='OUTPUT'}}, + ofrags + ) ) - ) + end return res end diff --git a/json/services.json b/json/services.json index b64e709..c193ce9 100644 --- a/json/services.json +++ b/json/services.json @@ -66,8 +66,13 @@ { "proto": "udp", "port": 138 } ], "netbios-ns": [ - { "proto": "tcp", "port": 137 }, - { "proto": "udp", "port": 137, "ct-helper": "netbios-ns" } + { "family": "inet", "proto": "tcp", "port": 137 }, + { + "family": "inet", + "proto": "udp", + "port": 137, + "ct-helper": "netbios-ns" + } ], "netbios-ssn": [ { "proto": "tcp", "port": 139 }, |