Commit fc670b19 authored by Ted Trask's avatar Ted Trask

Created iptables ACF to directly view / edit rules. Status, view, and expert...

Created iptables ACF to directly view / edit rules.  Status, view, and expert work.  Form to edit / create rules not functional yet.

git-svn-id: svn://svn.alpinelinux.org/acf/iptables/trunk@1575 ab2d0c66-481e-0410-8bed-d214d4d58bed
parents
APP_NAME=iptables
PACKAGE=acf-$(APP_NAME)
VERSION=0.0.1
APP_DIST=\
iptables* \
EXTRA_DIST=README Makefile config.mk
DISTFILES=$(APP_DIST) $(EXTRA_DIST)
TAR=tar
P=$(PACKAGE)-$(VERSION)
tarball=$(P).tar.bz2
install_dir=$(DESTDIR)/$(appdir)/$(APP_NAME)
all:
clean:
rm -rf $(tarball) $(P)
dist: $(tarball)
install:
mkdir -p "$(install_dir)"
cp -a $(APP_DIST) "$(install_dir)"
$(tarball): $(DISTFILES)
rm -rf $(P)
mkdir -p $(P)
cp -a $(DISTFILES) $(P)
$(TAR) -jcf $@ $(P)
rm -rf $(P)
# target that creates a tar package, unpacks is and install from package
dist-install: $(tarball)
$(TAR) -jxf $(tarball)
$(MAKE) -C $(P) install DESTDIR=$(DESTDIR)
rm -rf $(P)
include config.mk
.PHONY: all clean dist install dist-install
ACF for iptables
prefix=/usr
datadir=${prefix}/share
sysconfdir=${prefix}/etc
localstatedir=${prefix}/var
acfdir=${datadir}/acf
wwwdir=${acfdir}/www
cgibindir=${acfdir}/cgi-bin
appdir=${acfdir}/app
acflibdir=${acfdir}/lib
sessionsdir=${localstatedir}/lib/acf/sessions
module(..., package.seeall)
-- Load libraries
require("controllerfunctions")
-- ################################################################################
-- LOCAL FUNCTIONS
-- ################################################################################
-- PUBLIC FUNCTIONS
default_action = "status"
function status(self)
return self.model.getstatus()
end
function details(self)
return self.model.getstatusdetails()
end
function filterrules(self)
return self.model.getrules("filter")
end
function natrules(self)
return self.model.getrules("nat")
end
function manglerules(self)
return self.model.getrules("mangle")
end
function editchain(self)
return controllerfunctions.handle_form(self, function() return self.model.read_chain(self.clientdata.table, self.clientdata.chain or "") end, self.model.update_chain, self.clientdata, "Save", "Edit Chain", "Chain saved")
end
function createchain(self)
return controllerfunctions.handle_form(self, function() return self.model.read_chain(self.clientdata.table) end, self.model.create_chain, self.clientdata, "Create", "Create New Chain", "Chain created")
end
function deletechain(self)
return self:redirect_to_referrer(self.model.delete_chain(self.clientdata.table, self.clientdata.chain))
end
function editrule(self)
return controllerfunctions.handle_form(self, function() return self.model.read_rule(self.clientdata.table, self.clientdata.chain or "", self.clientdata.position or "") end, self.model.update_rule, self.clientdata, "Save", "Edit Rule", "Rule saved")
end
function createrule(self)
return controllerfunctions.handle_form(self, function() return self.model.read_rule(self.clientdata.table, self.clientdata.chain, self.clientdata.position) end, self.model.create_rule, self.clientdata, "Create", "Create New Rule", "Rule created")
end
function deleterule(self)
return self:redirect_to_referrer(self.model.delete_rule(self.clientdata.table, self.clientdata.chain, self.clientdata.position))
end
function expert(self)
return controllerfunctions.handle_form(self, self.model.readrulesfile, self.model.updaterulesfile, self.clientdata, "Save", "Edit Rules File", "Rules File Saved")
end
function startstop(self)
return controllerfunctions.handle_startstop(self, self.model.startstop_service, self.model.getstatus, self.clientdata)
end
iptables-editchain-html.lsp
\ No newline at end of file
iptables-editrule-html.lsp
\ No newline at end of file
<% local data, viewlibrary = ...
require("viewfunctions")
--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
io.write(html.cfe_unpack(data))
io.write("</span>")
--]]
%>
<% viewlibrary.dispatch_component("status") %>
<H2><%= data.label %></H2>
<DL>
<% for i,tab in ipairs({"filter", "nat", "mangle"}) do %>
<H3><%= tab %></H3>
<TABLE>
<TR><%= data.value[tab].chains %> Chains</TR>
<TR><%= data.value[tab].rules %> Rules</TR>
</TABLE>
<% end %>
</DL>
<% local form, viewlibrary, page_info = ...
require("viewfunctions")
%>
<H1><%= form.label %></H1>
<%
form.action = page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action
if page_info.action == "editchain" then
form.value.table.contenteditable = false
form.value.table.type = "text"
form.value.chain.contenteditable = false
end
local order = {"table", "chain", "policy"}
displayform(form, order)
%>
<% local form, viewlibrary, page_info = ...
require("viewfunctions")
%>
<H1><%= form.label %></H1>
<%
for name,val in pairs(form.value) do val.name = name end
form.value.table.contenteditable = false
form.value.table.type = "text"
form.value.chain.contenteditable = false
form.value.position.contenteditable = false
form.action = page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action
displayformstart(form)
%>
<H2>Rule Identification</H2><DL>
<%
displayformitem(form.value.table)
displayformitem(form.value.chain)
displayformitem(form.value.position)
%>
</DL><H2>Basic Parameters</H2><DL>
<%
displayformitem(form.value.protocol)
displayformitem(form.value.source)
displayformitem(form.value.destination)
displayformitem(form.value.jump)
displayformitem(form.value.goto)
displayformitem(form.value.in_interface)
displayformitem(form.value.out_interface)
displayformitem(form.value.fragment)
displayformitem(form.value.set_counters)
%>
</DL><H2>Save</H2>
<% displayformend(form) %>
../expert-html.lsp
\ No newline at end of file
<% local data, viewlibrary, page_info, session = ... %>
<% require("viewfunctions") %>
<% displaycommandresults({"editchain", "deletechain", "createrule", "deleterule", "editrule", "createchain"}, session) %>
<H1><%= data.label %></H1>
<DL>
<TABLE>
<% local tab = data.value.table %>
<% for j,chain in ipairs(data.value) do %>
<TR><TD>
<% if chain.policy then %>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/editchain?chain="..chain.name.."&table="..tab.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/document-properties.png' width='16' height='16' title="Edit Chain"></a>
<% else %>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/deletechain?chain="..chain.name.."&table="..tab.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-remove.png' width='16' height='16' title="Delete Chain"></a>
<% end %>
<%= chain.name %>
<% if chain.policy then io.write(" ("..chain.policy..")\n") end %>
<% if chain.references then io.write(" ("..chain.references.." references)\n") end %>
</TD></TR>
<% for j,line in ipairs(chain) do %>
<TR><TD STYLE='padding-left:40px'>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/createrule?table="..tab.."&chain="..chain.name.."&position="..j.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-add.png' width='16' height='16' title="Insert Rule"></a>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/deleterule?table="..tab.."&chain="..chain.name.."&position="..j.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-remove.png' width='16' height='16' title="Delete Rule"></a>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/editrule?table="..tab.."&chain="..chain.name.."&position="..j.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/document-properties.png' width='16' height='16' title="Edit Rule"></a>
</TD><TD><%= line %></TD>
</TR>
<% end %>
<TR><TD STYLE='padding-left:40px'>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/createrule?table="..tab.."&chain="..chain.name.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-add.png' width='16' height='16' title="Append Rule"></a>
</TD></TR>
<% end %>
<TR><TD><a href="<%= page_info.script..page_info.prefix..page_info.controller.."/createchain?table="..tab.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-add.png' width='16' height='16' title="Create Chain"></a></TD></TR>
</TABLE>
</DL>
module(..., package.seeall)
-- Load libraries
require("modelfunctions")
require("fs")
require("format")
-- Set variables
local packagename = "iptables"
local servicename = "iptables"
local rulesfile = "/var/lib/iptables/rules-save"
local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin "
local tables = {"filter", "nat", "mangle"}
local details
-- ################################################################################
-- LOCAL FUNCTIONS
local getdetails = function()
if not details then
details = {}
local cmd = path .. "iptables -t filter -n -L"
for i,tab in ipairs(tables) do
local f = io.popen( (string.gsub(cmd, "filter", tab)) )
details[tab] = {table=tab}
local file = f:read("*a")
f:close()
for line in string.gmatch(file, "([^\n]+)") do
if string.match(line, "^Chain") then
local name = string.match(line, "^%w+%s+(%S+)")
local policy = string.match(line, "policy (%w+)")
local references = string.match(line, "(%d+) references")
table.insert(details[tab], {name=name, policy=policy, references=references})
elseif not string.match(line, "^target%s+prot") then
table.insert(details[tab][#details[tab]], line)
elseif not details[tab].header then
details[tab].header = line
end
end
end
end
end
local find_chain = function(tab, chain)
getdetails()
if details[tab] then
for i,chn in ipairs(details[tab]) do
if chain == chn.name then
return chn
end
end
end
return nil
end
local save = function()
local cmd = path .. "/etc/init.d/"..servicename.." save 2>&1"
local f = io.popen( cmd )
f:close()
details = nil
end
-- ################################################################################
-- PUBLIC FUNCTIONS
function getstatus()
local status = {}
local value, errtxt = processinfo.package_version(packagename)
status.version = cfe({
label="Program version",
value=value,
errtxt=errtxt,
})
return cfe({ type="group", value=status, label="IPtables Status" })
end
function getstatusdetails()
getdetails()
local retval = {}
for i,tab in ipairs(tables) do
local chains = 0
local rules = 0
for i,chain in ipairs(details[tab]) do
chains = chains + 1
rules = rules + #chain
end
retval[tab] = {chains=chains, rules=rules}
end
return cfe({ type="structure", value=retval, label="IPtables Status Details" })
end
function getrules(tab)
getdetails()
tab = tab or "filter"
return cfe({ type="structure", value=details[tab] or {}, label=string.gsub(tab, "^.", string.upper).." Rules" })
end
function read_chain(tab, chain)
local retval = {}
retval.table = cfe({ type="select", value=tab or "filter", label="Table", option=tables })
retval.chain = cfe({ value=chain or "", label="Chain" })
getdetails()
if tab and not details[tab] then
retval.table.errtxt = "Invalid table"
end
if chain then
local chn = find_chain(retval.table.value, chain)
if not chn then
retval.chain.errtxt = "Cannot find chain"
elseif chn.policy then
-- only built-in chains can have policies, and the target can only be DROP or ACCEPT
retval.policy = cfe({ type="select", value=chn.policy, label="Policy", option={"DROP", "ACCEPT"} })
end
end
return cfe({ type="group", value=retval, label="Chain" })
end
function update_chain(chain)
local success = true
getdetails()
if not details[chain.value.table.value] then
chain.value.table.errtxt = "Invalid table"
success = false
elseif not find_chain(chain.value.table.value, chain.value.chain.value) then
chain.value.chain.errtxt = "Invalid chain"
success = false
end
if success then
if chain.value.policy then
local cmd = path .. "iptables -t "..chain.value.table.value.." -P "..chain.value.chain.value.." "..chain.value.policy.value.." 2>&1"
local f = io.popen(cmd)
local errtxt = f:read("*a")
f:close()
if errtxt ~= "" then
chain.errtxt = errtxt
end
save()
end
else
chain.errtxt = "Failed to update chain"
end
return chain
end
function create_chain(chain)
local success = true
getdetails()
if not details[chain.value.table.value] then
chain.value.table.errtxt = "Invalid table"
success = false
elseif find_chain(chain.value.table.value, chain.value.chain.value) then
chain.value.chain.errtxt = "Chain already exists"
success = false
end
if string.find(chain.value.chain.value, "[%s\'\"]") then
chain.value.chain.errtxt = "Chain cannot contain spaces or quotes"
success = false
end
if success then
local cmd = path .. "iptables -t "..chain.value.table.value.." -N "..chain.value.chain.value.." 2>&1"
local f = io.popen(cmd)
local errtxt = f:read("*a")
if errtxt ~= "" then
chain.errtxt = errtxt
end
f:close()
save()
else
chain.errtxt = "Failed to create chain"
end
return chain
end
function delete_chain(tab, chain)
local retval = cfe({ label="Delete Chain result" })
tab = tab or "filter"
local chn = find_chain(tab, chain)
if not chn then
retval.errtxt = "Could not find chain"
elseif chn.policy then
retval.errtxt = "Cannot delete built-in chain"
elseif chn.references and tonumber(chn.references) > 0 then
retval.errtxt = "Cannot delete chain with references"
else
local cmd = path .. "iptables -t "..tab.." -X "..chain.." 2>&1"
local f = io.popen(cmd)
local errtxt = f:read("*a")
if errtxt ~= "" then
retval.errtxt = errtxt
else
retval.value = "Deleted Chain"
end
save()
end
return retval
end
function read_rule(tab, chain, pos)
local retval = {}
retval.table = cfe({ type="select", value=tab or "filter", label="Table", option=tables })
retval.chain = cfe({ value=chain or "", label="Chain" })
retval.position = cfe({ value=pos or "", label="Position" })
retval.protocol = cfe({ value="all", label="Protocol", descr="One of tcp, udp, icmp, or all, or a numeric value representing a protocol, or a protocol name from /etc/protocols. A '!' before the protocol inverts the test." })
retval.source = cfe({ label="Source", descr="A network name or IP address (may have mask of type /xxx.xxx.xxx.xxx or /xx). A '!' before the address spcification inverts the sense of the address." })
retval.destination = cfe({ label="Destination", descr="A network name or IP address (may have mask of type /xxx.xxx.xxx.xxx or /xx). A '!' before the address spcification inverts the sense of the address." })
retval.jump = cfe({ label="Target", descr="Specify the target of the rule - one of ACCEPT, DROP, QUEUE, or RETURN, or the name of a user-defined chain." })
retval.goto = cfe({ label="Goto", descr="Processing should continue in the specified chain" })
retval.in_interface = cfe({ label="In Interface", descr="Name of an interface via which a packet was received. A '!' before the interface inverts the sense. A '+' ending the interface will match any interface that begins with this name." })
retval.out_interface = cfe({ label="Out Interface", descr="Name of an interface via which a packet is going to be sent. A '!' before the interface inverts the sense. A '+' ending the interface will match any interface that begins with this name." })
retval.fragment = cfe({ label="Fragment", descr="A '+' specifies the second and further packets of fragmented packets. A '!' specifies only head fragments or unfragmented packets." })
retval.set_counters = cfe({ label="Set Counters", descr="'Number, number' to initialize the packet and byte counters."})
getdetails()
if tab and not details[tab] then
retval.table.errtxt = "Invalid table"
end
local chn
if chain then
chn = find_chain(retval.table.value, chain)
if not chn then
retval.chain.errtxt = "Cannot find chain"
end
end
if pos and chn then
if not chn[tonumber(pos)] then
retval.position.errtxt = "Cannot find rule"
else
-- We found the rule, update the settings
end
end
return cfe({ type="group", value=retval, label="Rule" })
end
function readrulesfile()
return modelfunctions.getfiledetails(rulesfile)
end
function updaterulesfile(filedetails)
return modelfunctions.setfiledetails(filedetails, {rulesfile})
end
-- local implementation to add save, reload, and panic actions
function startstop_service(action)
local cmdresult = cfe({ label="Start/Stop result" })
if (string.lower(action) == "start") or (string.lower(action) == "stop") or (string.lower(action) == "restart") or (string.lower(action) == "save") or (string.lower(action) == "reload") or (string.lower(action) == "panic") then
local file = io.popen( "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin /etc/init.d/" ..
servicename .. " " .. string.lower(action) .. " 2>&1" )
if file ~= nil then
cmdresult.value = file:read( "*a" )
file:close()
end
posix.sleep(2) -- Wait for the process to start|stop
else
cmdresult.errtxt = "Unknown command!"
end
return cmdresult
end
<% local data, viewlibrary, page_info = ... %>
<H1>Management</H1>
<DL>
<form action="<%= page_info.script .. page_info.prefix .. page_info.controller .. "/" .. page_info.action %>" method="POST">
<DT>Load rules from rules file</DT>
<DD>
<input class="submit" type="submit" name="action" value="Reload">
</DD>
<DT>Save current rules to rules file</DT>
<DD>
<input class="submit" type="submit" name="action" value="Save">
</DD>
</form>
<% if data.value.result then %>
<DT>Previous action result</DT>
<DD>
<% if data.value.result.value ~= "" then %>
<P CLASS='descr'><%= string.gsub(data.value.result.value, "\n", "<BR>") %></P>
<% end if data.value.result.errtxt then %>
<P CLASS='error'><%= string.gsub(data.value.result.errtxt, "\n", "<BR>") %></P>
<% end end %>
</DD>
</DL>
../status-html.lsp
\ No newline at end of file
#CAT GROUP/DESC TAB ACTION
Networking 45IPtables Status details
Networking 45IPtables Filter_Rules filterrules
Networking 45IPtables Nat_Rules natrules
Networking 45IPtables Mangle_Rules manglerules
Networking 45IPtables Expert expert
USER=iptables:status,iptables:details,iptables:startstop
EDITOR=iptables:filterrules,iptables:natrules,iptables:manglerules,iptables:editchain,iptables:createchain,iptables:deletechain,iptables:editrule,iptables:createrule,iptables:deleterule
EXPERT=iptables:expert
ADMIN=iptables:status,iptables:details,iptables:startstop,iptables:filterrules,iptables:natrules,iptables:manglerules,iptables:editchain,iptables:createchain,iptables:deletechain,iptables:editrule,iptables:createrule,iptables:deleterule,iptables:expert
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