Skip to content

Commit

Permalink
Allow pfmatch actions for l7fw rules
Browse files Browse the repository at this point in the history
  • Loading branch information
takikawa committed Jan 20, 2017
1 parent 62672d2 commit 40eeadf
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 10 deletions.
59 changes: 50 additions & 9 deletions src/apps/wall/l7fw.lua
@@ -1,22 +1,58 @@
module(..., package.seeall)

-- This module implements a level 7 firewall app that consumes the result
-- of DPI scanning done by l7spy.
--
-- The firewall rules are a table mapping protocol names to either
-- * a simple action ("drop", "reject", "accept")
-- * a pfmatch expression

local link = require("core.link")
local packet = require("core.packet")
local match = require("pf.match")

L7Fw = {}
L7Fw.__index = L7Fw

-- create a new firewall app object given an instance of Scanner
-- and firewall rules
-- FIXME: for now, the rules are just a Lua table mapping a
-- protocol name to a policy "accept" or "drop"
-- we may want to have a real rule language, plus pflua
-- integration(?)
function L7Fw:new(config)
local obj = { scanner = config.scanner, rules = config.rules }
local obj = { scanner = config.scanner }
local rules = {}

for protocol, action in pairs(config.rules) do
if action == "accept" or action == "drop" or action == "reject" then
rules[protocol] = action
else
rules[protocol] = "pfmatch"
-- TODO: this may be compiling too early for this to work
self["handle_" .. protocol] = match.compile(action)
end
end

obj.rules = rules

return setmetatable(obj, self)
end

-- called by pfmatch handlers, just drop the packet on the floor
function L7Fw:drop(pkt, len)
packet.free(self.current_packet)
return
end

-- called by pfmatch handler, handle rejection response
function L7Fw:reject(pkt, len)
-- TODO: implement ICMP/TCP RST response
packet.free(self.current_packet)
return
end

-- called by pfmatch handler, forward packet
function L7Fw:accept(pkt, len)
link.transmit(self.output.output, self.current_packet)
end

function L7Fw:push()
local i = assert(self.input.input, "input port not found")
local o = assert(self.output.output, "output port not found")
Expand All @@ -27,17 +63,22 @@ function L7Fw:push()
local pkt = link.receive(i)
local flow = scanner:get_flow(pkt)

-- so that pfmatch handler methods can access the original packet
self.current_packet = pkt

if flow then
local name = scanner:protocol_name(flow.protocol)
local policy = rules[name] or rules["default"]

if policy == "accept" then
link.transmit(o, pkt)
if policy == "pfmatch" then
self["handle_" .. name](self, pkt.data, pkt.length)
elseif policy == "accept" then
self:accept(pkt.data, pkt.length)
elseif policy == "drop" then
packet.free(pkt)
self:drop(pkt.data, pkt.length)
-- TODO: what should the default policy be if there is none specified?
else
link.transmit(o, pkt)
self:accept(pkt.data, pkt.length)
end
else
-- TODO: we may wish to have a default policy for packets
Expand Down
2 changes: 1 addition & 1 deletion src/program/wall/filter/filter.lua
Expand Up @@ -20,7 +20,7 @@ function run (args)
config.app(c, "l7spy", require("apps.wall.l7spy").L7Spy, { scanner = scanner })
config.app(c, "sink", pcap.PcapWriter, out_file)
-- TODO: hardcoded some rules here for this experiment
local rules = { RTP = "drop", default = "accept" }
local rules = { RTP = [[match { udp => accept; otherwise => drop }]], default = "drop" }
config.app(c, "l7fw", require("apps.wall.l7fw").L7Fw, { scanner = scanner, rules = rules })
config.link(c, "source.output -> l7spy.south")
config.link(c, "l7spy.north -> l7fw.input")
Expand Down

0 comments on commit 40eeadf

Please sign in to comment.