#!/usr/bin/env ruby # a script to convert _currently_ active iptables rules as dumped by # iptables-save into /etc/net "human readable" format as documented # in http://wiki.sisyphus.ru/admin/etcnet/firewall#h468-6 [ru] # [still requires additional fixes, on etcnet syntax side too] # Copyleft 2006 by Michael Shigorin module Ipt2etcnet require "iptables-save.rb" require "etcnet-fw-syntax.rb" DEBUG = true HUMAN_READABLE = false #IPT_SAVE = "/sbin/iptables-save" IPT_SAVE = "/bin/cat iptables" FWOUTDIR = "ifaces/default/fw/iptables" NEWTABLE = /^\*([a-z]+)$/ NEWCHAIN = /^:([A-Za-z0-9_-]+) ([A-Z-]+) \[(\d+):(\d+)\]$/ NEWRULE = /^-A ([A-Za-z0-9_-]+) (.*)$/ HEADER = /^(# Generated by .*)$/ COMMIT = /^COMMIT$/ tables = Iptables.new chains = Table.new(nil) # slurp existing rules # FIXME: exception handling IO.popen(IPT_SAVE) do |rules| rules.each do |line| case line when NEWTABLE then chains = Table.new($1) # see appropriate regexp when NEWCHAIN then chains.add(Chain.new($1,$2)) when NEWRULE then chains[$1].add(Rule.new($2, HUMAN_READABLE)) when COMMIT then tables.add(chains.commit) end end end # OK, now flush them out # FIXME: IO errors handling! tables.each do |table| tabledir = File.join(FWOUTDIR, table.name) # one dir per table `/bin/mkdir -p #{tabledir}` table.each do |chain| File.open(File.join(tabledir, chain.name), "w") do |f| chain.each do |rule| f.puts(rule) end end end end # FIXME: figure out what's up with other policies File.open(File.join(FWOUTDIR, "..", "options"), "w") do |f| tables["filter"].each do |chain| case chain.name when "INPUT", "OUTPUT", "FORWARD" f.puts("IPTABLES_#{chain.name}_POLICY=#{chain.policy}") end end end #p tables["filter"] end # module ### TODO: # - factor out extra complications with Rule when no # human-readability is requested? # - getopt # - package somewhat # - fix all FIXMEs :-)