Commit 9fdf8d72 authored by Kaarle Ritvanen's avatar Kaarle Ritvanen

constrain 'netbios-ns' service to IPv4 only

parent 4313b0b6
......@@ -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
......
......@@ -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
......
......@@ -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 },
......
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