summaryrefslogtreecommitdiffstats
path: root/acf/modules/awall.lua
diff options
context:
space:
mode:
Diffstat (limited to 'acf/modules/awall.lua')
-rw-r--r--acf/modules/awall.lua138
1 files changed, 138 insertions, 0 deletions
diff --git a/acf/modules/awall.lua b/acf/modules/awall.lua
new file mode 100644
index 0000000..8d25638
--- /dev/null
+++ b/acf/modules/awall.lua
@@ -0,0 +1,138 @@
+--[[
+Copyright (c) 2012 Kaarle Ritvanen
+See LICENSE file for license details
+--]]
+
+module(..., package.seeall)
+
+local M = require('acf.model')
+
+local object = require('acf.object')
+local class = object.class
+local super = object.super
+
+
+IPv4Addr = class(M.String)
+function IPv4Addr:validate(txn, path, value)
+ local function test(...)
+ if #arg ~= 4 then return true end
+ for _, octet in ipairs(arg) do
+ if tonumber(octet) > 255 then return true end
+ end
+ end
+ if test(string.match(value, '(%d+)%.(%d+)%.(%d+)%.(%d+)')) then
+ error('Invalid IP address: '..value)
+ end
+end
+
+Port = class(M.Integer)
+function Port:validate(txn, path, value)
+ super(self, Port):validate(txn, path, value)
+ if value < 0 or value > 65535 then error('Invalid port: '..value) end
+end
+
+Range = class(M.String)
+function Range:validate(txn, path, value)
+ local comps = stringy.split(value, '-')
+ if #comps > 2 then error('Invalid range: '..value) end
+ for _, v in ipairs(comps) do
+ local num = tonumber(v)
+ if not num then error('Invalid range: ' ..value) end
+ M.to_field(self.type):validate(txn, path, num)
+ end
+end
+
+PortRange = class(Range)
+function PortRange:init() super(self, PortRange):init{type=Port} end
+
+Direction = class(M.String)
+function Direction:init()
+ super(self, Direction):init{choice={'in', 'out'}}
+end
+
+
+-- TODO reference types?
+
+IPSet = M.new()
+-- TODO choices
+IPSet.type = M.String{required=true}
+IPSet.family = M.String{required=true, choice={'inet', 'inet6'}}
+
+Service = M.new()
+Service.proto = M.String{required=true}
+Service.port = M.Collection{type=PortRange}
+Service['icmp-type'] = M.String
+
+-- TODO fw zone
+
+Zone = M.new()
+Zone.iface = M.PrimitiveList{type=M.String}
+Zone.addr = M.PrimitiveList{type=M.String}
+Zone['route-back'] = M.Boolean{default=false}
+
+LogClass = M.new()
+LogClass.mode = M.String{default='log', choice={'log', 'nflog', 'ulog'}}
+LogClass.limit = M.Integer
+LogClass.prefix = M.String
+
+IPSetReference = M.new()
+IPSetReference.name = M.Reference{scope='../../ipset', required=true}
+IPSetReference.args = M.Collection{type=Direction, required=true}
+
+Rule = M.new()
+Rule['in'] = M.Collection{type=M.Reference{scope='../../zone'}}
+Rule.out = M.Collection{type=M.Reference{scope='../../zone'}}
+Rule.src = M.Collection{type=M.String}
+Rule.dest = M.Collection{type=M.String}
+Rule.ipset = IPSetReference
+Rule.ipsec = Direction
+Rule.service = M.Collection{type=M.Reference{scope='../../service'}}
+Rule.action = M.String{choice={'accept'}}
+
+
+-- TODO no service field
+PolicyRule = M.new(Rule)
+PolicyRule.log = M.Reference{scope='../log'}
+PolicyRule.action = M.String{required=true,
+ choice={'accept', 'drop', 'reject', 'tarpit'}}
+
+Limit = M.new()
+Limit.count = M.Integer
+Limit.interval = M.Integer
+Limit.log = M.Reference{scope='../../log'}
+
+FilterRule = M.new(PolicyRule)
+FilterRule['conn-limit'] = Limit
+FilterRule['flow-limit'] = Limit
+FilterRule.dnat = IPv4Addr
+FilterRule['no-track'] = M.Boolean{default=false}
+
+NATRule = M.new(Rule)
+NATRule['to-addr'] = Range{type=IPv4Addr}
+NATRule['to-port'] = PortRange
+
+MarkRule = M.new(Rule)
+MarkRule.mark = M.Integer{required=true}
+
+ClampMSSRule = M.new(Rule)
+ClampMSSRule.mss = M.Integer
+
+
+AWall = M.new()
+-- TODO differentiate lists?
+AWall.service = M.Collection{type=M.Collection{type=Service}}
+AWall.zone = M.Collection{type=Zone}
+AWall.log = M.Collection{type=LogClass}
+AWall.policy = M.Collection{type=PolicyRule}
+AWall.filter = M.Collection{type=FilterRule}
+AWall.dnat = M.Collection{type=NATRule}
+AWall.snat = M.Collection{type=NATRule}
+AWall.mark = M.Collection{type=MarkRule}
+AWall['route-track'] = M.Collection{type=MarkRule}
+AWall['clamp-mss'] = M.Collection{type=ClampMSSRule}
+AWall['no-track'] = M.Collection{type=Rule}
+AWall.ipset = M.Collection{type=IPSet}
+
+M.register('awall',
+ '/json'..require('lfs').currentdir()..'/config/awall.json',
+ AWall)