--[[ Copyright (c) 2012-2014 Kaarle Ritvanen See LICENSE file for license details --]] local M = require('aconf.model') local object = require('aconf.object') local Direction = object.class(M.String) function Direction:init(params) if not params then params = {} end params.choice = {'in', 'out'} object.super(self, Direction):init(params) end -- TODO reference types? local IPSet = M.new() -- TODO choices IPSet.type = M.String{required=true} IPSet.family = M.String{required=true, choice={'inet', 'inet6'}} -- TODO only for bitmaps IPSet.range = M.Range{type=M.net.IPv4Address} local Service = M.new() Service.proto = M.String{required=true, ui_name='Protocol'} Service.port = M.Set{type=M.Range{type=M.net.Port}} Service.icmp_type = M.String{ui_name='ICMP type'} Service.ct_helper = M.String{ui_name='Connection tracking helper'} -- TODO fw zone local Zone = M.new() Zone.iface = M.Set{type=M.String, ui_name='Interfaces'} Zone.addr = M.Set{type=M.String, ui_name='Addresses'} Zone.route_back = M.Boolean{default=false} local LogClass = M.new() LogClass.mode = M.String{ required=true, default='log', choice={'log', 'nflog', 'ulog'} } LogClass.every = M.Integer{ui_name='Sampling frequency'} LogClass.limit = M.Integer LogClass.prefix = M.String LogClass.probability = M.Number LogClass.group = M.Integer LogClass.range = M.Integer LogClass.threshold = M.Integer local IPSetReference = M.new() IPSetReference.name = M.Reference{scope='/awall/ipset', required=true} IPSetReference.args = M.List{ type=Direction, required=true, ui_name='Arguments' } local Rule = M.new() Rule['in'] = M.Set{ type=M.Reference{scope='/awall/zone'}, ui_name='Ingress zones' } Rule.out = M.Set{ type=M.Reference{scope='/awall/zone'}, ui_name='Egress zones' } Rule.src = M.Set{type=M.String, ui_name='Sources'} Rule.dest = M.Set{type=M.String, ui_name='Destinations'} Rule.ipset = M.Model{model=IPSetReference, ui_name='IP set'} Rule.ipsec = Direction{ui_name='Require IPsec'} Rule.service = M.Set{type=M.Reference{scope='/awall/service'}} Rule.action = M.String{choice={'accept'}} local PacketLogRule = M.new(Rule) PacketLogRule.log = M.Reference{scope='../../log', ui_name='Log class'} -- TODO no service field local PolicyRule = M.new(PacketLogRule) PolicyRule.action = M.String{ required=true, choice={'accept', 'drop', 'reject', 'tarpit'} } local Limit = M.new() Limit.count = M.Integer Limit.interval = M.Integer Limit.log = M.Reference{scope='../../../log'} local FilterRule = M.new(PolicyRule) FilterRule.conn_limit = M.Model{model=Limit, ui_name='Connection limit'} FilterRule.flow_limit = M.Model{model=Limit, ui_name='Flow limit'} FilterRule.dnat = M.net.IPv4Address{ui_name='DNAT target'} FilterRule.no_track = M.Boolean{default=false, ui_name='CT bypass'} FilterRule.related = M.List{type=Rule, ui_name='Related packet rules'} local DivertRule = M.new(Rule) DivertRule.to_port = M.Range{type=M.net.Port, ui_name='Target port'} local NATRule = M.new(DivertRule) NATRule.to_addr = M.Range{type=M.net.IPv4Address, ui_name='Target address'} local MarkRule = M.new(Rule) MarkRule.mark = M.Integer{required=true} local ClampMSSRule = M.new(Rule) ClampMSSRule.mss = M.Integer{ui_name='MSS'} local AWall = M.new() -- TODO differentiate lists? AWall.service = M.Collection{type=M.List{type=Service}} AWall.zone = M.Collection{type=Zone} AWall.log = M.Collection{ type=LogClass, ui_name='Log classes', ui_member='Log class' } AWall.policy = M.List{type=PolicyRule, ui_name='Policies', ui_member='Policy'} AWall.packet_log = M.List{ type=PacketLogRule, ui_name='Logging', ui_member='Logging rule' } AWall.filter = M.List{type=FilterRule} AWall.dnat = M.List{type=NATRule, ui_name='DNAT', ui_member='DNAT rule'} AWall.snat = M.List{type=NATRule, ui_name='SNAT', ui_member='SNAT rule'} AWall.mark = M.List{ type=MarkRule, ui_name='Packet marking', ui_member='Packet marking rule' } AWall.route_track = M.List{ type=MarkRule, ui_name='Route tracking', ui_member='Route tracking rule' } AWall.tproxy = M.List{ type=DivertRule, ui_name='Transparent proxy', ui_member='Transparent proxy rule' } AWall.clamp_mss = M.List{ type=ClampMSSRule, ui_name='MSS clamping', ui_member='MSS clamping rule' } AWall.no_track = M.List{ type=Rule, ui_name='CT bypass', ui_member='Connection tracking bypass rule' } AWall.ipset = M.Collection{type=IPSet, ui_name='IP sets', ui_member='IP set'} M.register( 'awall', AWall, { addr='/json'..require('posix').getcwd()..'/config/awall.json', ui_name='Alpine Wall' } ) M.permission.defaults('/awall')