1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-21 02:37:16 +01:00

support for multiple rule sets in PF

This commit is contained in:
Vadim Kurland 2008-05-30 22:00:45 +00:00
parent 2f9e82c5ba
commit 0457709b97
8 changed files with 1903 additions and 1399 deletions

View File

@ -1,3 +1,15 @@
2008-05-30 Vadim Kurland <vadim@vk.crocodile.org>
* pf.cpp (main): Like compiler for iptables, compiler for PF now
supports multiple rule sets for policy and nat. Each rule set is
translated into corresponding anchor .conf file. If some rule in
another rule set references it via action Branch, corresponding
"anchor" configuration line is generated, but if it is not
references from any rule, the anchor .conf file is still
created. Rule sets "Policy" and "NAT" are configured "main" or
"root" and placed in the main .conf file with the name of the
firewall object.
2008-05-29 Vadim Kurland <vadim@vk.crocodile.org>
* ipt.cpp (main): Compiler for iptables processes all Policy and

View File

@ -596,14 +596,14 @@ _("Dynamic interface %s should not have an IP address object attached to it. Thi
n.setHaveDynamicInterfaces(have_dynamic_interfaces);
if (test_mode) n.setTestMode();
have_nat = (have_nat || ((nat_rules_count=n.prolog()) > 0));
if ( (nat_rules_count=n.prolog()) > 0 )
{
n.compile();
n.epilog();
}
have_nat = (have_nat || (nat_rules_count > 0));
if (n.getCompiledScriptLength() > 0)
{
n_str << "# ================ Table 'nat', rule set "

View File

@ -70,6 +70,7 @@
#include "fwbuilder/Firewall.h"
#include "fwbuilder/Interface.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/NAT.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
@ -102,8 +103,18 @@ static bool test_mode = false;
static bool ipv4_run = true;
static bool ipv6_run = true;
static map<string,RuleSet*> branches;
static map<string,string> anchor_files;
// Note that in the following maps ruleset name will be
// "__main__" for both main Policy and NAT rulesets.
// map ruleset_name -> conf file name
static map<string, string> conf_files;
// map ruleset_name -> generated script
static map<string, ostringstream*> generated_scripts;
// map ruleset_name -> TableFactory*
static map<string, TableFactory*> table_factories;
FWObjectDatabase *objdb = NULL;
@ -134,6 +145,30 @@ void join::operator()(std::string &s)
*result += s;
}
string getConfFileName(const string &ruleset_name,
const string &fwobjectname,
const string &fw_file_name)
{
string conf_file_name;
if (ruleset_name == "__main__")
conf_file_name = string(fwobjectname) + ".conf";
else
{
if (fw_file_name.empty())
{
conf_file_name = string(fwobjectname) + "-" +
ruleset_name + ".conf";
} else
{
string::size_type n = fw_file_name.rfind(".");
conf_file_name = fw_file_name;
conf_file_name.erase(n);
conf_file_name.append("-" + ruleset_name + ".conf");
}
}
return conf_file_name;
}
void usage(const char *name)
{
cout << _("Firewall Builder: policy compiler for OpenBSD PF") << endl;
@ -168,6 +203,191 @@ void printProlog(ofstream &file, const string &prolog_code)
file << "#" << endl;
}
void printStaticOptions(ofstream &file, Firewall* fw)
{
FWOptions* options = fw->getOptionsObject();
list<FWObject*> all_interfaces=fw->getByType(Interface::TYPENAME);
string prolog_place = options->getStr("prolog_place");
if (prolog_place.empty()) prolog_place = "fw_file"; // old default
string pre_hook = options->getStr("prolog_script");
if (prolog_place == "pf_file_top")
printProlog(file, pre_hook);
file << endl;
list<string> limits;
if (options->getBool("pf_do_limit_frags") &&
options->getInt("pf_limit_frags")>0 )
limits.push_back(string("frags ") +
options->getStr("pf_limit_frags"));
if (options->getBool("pf_do_limit_states") &&
options->getInt("pf_limit_states")>0 )
limits.push_back(string("states ") +
options->getStr("pf_limit_states"));
if (options->getBool("pf_do_limit_src_nodes") &&
options->getInt("pf_limit_src_nodes")>0 )
limits.push_back(string("src-nodes ") +
options->getStr("pf_limit_src_nodes"));
if (options->getBool("pf_do_limit_tables") &&
options->getInt("pf_limit_tables")>0 )
limits.push_back(string("tables ") +
options->getStr("pf_limit_tables"));
if (options->getBool("pf_do_limit_table_entries") &&
options->getInt("pf_limit_table_entries")>0 )
limits.push_back(string("table-entries ") +
options->getStr("pf_limit_table_entries"));
if (limits.size() > 0)
{
file << "set limit ";
if (limits.size() > 1 ) file << "{ ";
string all_limits;
for_each(limits.begin(), limits.end(), join( &all_limits, ", "));
file << all_limits;
if (limits.size() > 1 ) file << " }";
file << endl;
}
if ( ! options->getStr("pf_optimization").empty() )
file << "set optimization "
<< options->getStr("pf_optimization") << endl;
file << printTimeout(options,
"pf_do_timeout_interval","pf_timeout_interval",
"interval");
file << printTimeout(options,
"pf_do_timeout_frag","pf_timeout_frag",
"frag");
file << printTimeout(options,
"pf_set_tcp_first","pf_tcp_first",
"tcp.first" );
file << printTimeout(options,
"pf_set_tcp_opening","pf_tcp_opening",
"tcp.opening" );
file << printTimeout(options,
"pf_set_tcp_established","pf_tcp_established",
"tcp.established" );
file << printTimeout(options,
"pf_set_tcp_closing","pf_tcp_closing",
"tcp.closing" );
file << printTimeout(options,
"pf_set_tcp_finwait","pf_tcp_finwait",
"tcp.finwait" );
file << printTimeout(options,
"pf_set_tcp_closed","pf_tcp_closed",
"tcp.closed" );
file << printTimeout(options,
"pf_set_udp_first","pf_udp_first",
"udp.first" );
file << printTimeout(options,
"pf_set_udp_single","pf_udp_single",
"udp.single" );
file << printTimeout(options,
"pf_set_udp_multiple","pf_udp_multiple",
"udp.multiple" );
file << printTimeout(options,
"pf_set_icmp_first","pf_icmp_first",
"icmp.first" );
file << printTimeout(options,
"pf_set_icmp_error","pf_icmp_error",
"icmp.error" );
file << printTimeout(options,
"pf_set_other_first","pf_other_first",
"other.first" );
file << printTimeout(options,
"pf_set_other_single","pf_other_single",
"other.single" );
file << printTimeout(options,
"pf_set_other_multiple","pf_other_multiple",
"other.multiple" );
file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_start",
"adaptive.start" );
file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_end",
"adaptive.end");
// check if any interface is marked as 'unprotected'
// and generate 'set skip on <ifspec>' commands
if (fw->getStr("version")=="ge_3.7" ||
fw->getStr("version")=="4.x")
{
for (list<FWObject*>::iterator i=all_interfaces.begin();
i!=all_interfaces.end(); ++i)
{
Interface *iface=dynamic_cast<Interface*>(*i);
assert(iface);
if ( iface->isUnprotected())
file << "set skip on " << iface->getName() << endl;
}
}
file << endl;
if (prolog_place == "pf_file_after_set")
printProlog(file, pre_hook);
string scrub_options;
if (options->getBool("pf_do_scrub"))
{
if (options->getBool("pf_scrub_reassemble"))
scrub_options+="fragment reassemble ";
else
{
if (options->getBool("pf_scrub_fragm_crop"))
scrub_options+="fragment crop ";
else
{
if (options->getBool("pf_scrub_fragm_drop_ovl"))
scrub_options+="fragment drop-ovl ";
}
}
}
if (options->getBool("pf_scrub_no_df")) scrub_options+="no-df ";
if (!scrub_options.empty())
{
file << "#" << endl;
file << "# Scrub rules" << endl;
file << "#" << endl;
file << "scrub in all " << scrub_options << endl;
}
scrub_options="";
if (options->getBool("pf_scrub_random_id"))
scrub_options+="random-id ";
if (options->getBool("pf_scrub_use_minttl"))
scrub_options+="min-ttl " + options->getStr("pf_scrub_minttl") + " ";
if (options->getBool("pf_scrub_use_maxmss"))
scrub_options+="max-mss " + options->getStr("pf_scrub_maxmss") + " ";
if (!scrub_options.empty())
{
file << "scrub out all " << scrub_options << endl;
}
file << endl;
if (prolog_place == "pf_file_after_scrub")
printProlog(file, pre_hook);
//file << table_factory->PrintTables();
//file << endl;
if (prolog_place == "pf_file_after_tables")
printProlog(file, pre_hook);
}
int main(int argc, char * const *argv)
{
@ -416,9 +636,12 @@ int main(int argc, char * const *argv)
oscnf->prolog();
list<FWObject*> all_policies = fw->getByType(Policy::TYPENAME);
list<FWObject*> all_nat = fw->getByType(NAT::TYPENAME);
vector<bool> ipv4_6_runs;
string generated_script;
bool have_nat = false;
bool have_pf = false;
// command line options -4 and -6 control address family for which
// script will be generated. If "-4" is used, only ipv4 part will
@ -440,347 +663,153 @@ int main(int argc, char * const *argv)
if (ipv4_run) ipv4_6_runs.push_back(false);
}
ostringstream *main_str = new ostringstream();
for (vector<bool>::iterator i=ipv4_6_runs.begin();
i!=ipv4_6_runs.end(); ++i)
{
bool ipv6_policy = *i;
if (ipv6_policy)
{
generated_script += "\n\n";
generated_script += "#================ IPv6 ================\n";
generated_script += "\n\n";
} else
{
generated_script += "\n\n";
generated_script += "#================ IPv4 ================\n";
generated_script += "\n\n";
}
TableFactory *table_factory = new TableFactory();
Preprocessor_pf* prep = new Preprocessor_pf(
objdb , fwobjectname, ipv6_policy);
prep->compile();
// find branching rules and store names of the branches and
// pointers to corresponding rule sets
//
FWObject *policy = fw->getFirstByType(Policy::TYPENAME);
for (FWObject::iterator i=policy->begin(); i!=policy->end(); i++)
list<NATCompiler_pf::redirectRuleInfo> redirect_rules_info;
for (list<FWObject*>::iterator p=all_nat.begin();
p!=all_nat.end(); ++p )
{
PolicyRule *rule = PolicyRule::cast(*i);
if (rule->getAction()==PolicyRule::Branch)
NAT *nat = NAT::cast(*p);
string ruleset_name = nat->getName();
if (Compiler::isRootRuleSet(nat))
ruleset_name = "__main__";
if (!table_factories.count(ruleset_name))
table_factories[ruleset_name] = new TableFactory();
NATCompiler_pf n( objdb, fwobjectname, ipv6_policy, oscnf,
table_factories[ruleset_name] );
n.setSourceRuleSet( nat );
n.setRuleSetName(nat->getName());
n.setDebugLevel( dl );
n.setDebugRule( drn );
n.setVerbose( verbose );
if (test_mode) n.setTestMode();
int nat_rules_count = 0;
if ( (nat_rules_count=n.prolog()) > 0 )
{
int parentRuleNum = rule->getPosition();
RuleSet *subset = rule->getBranch();
if (subset==NULL)
{
throw FWException(
_("Action 'Branch' but no branch policy in policy rule ")
+rule->getLabel());
}
subset->setInt("parent_rule_num",parentRuleNum);
FWOptions *ropt = rule->getOptionsObject();
string branchName = ropt->getStr("branch_name");
branches[branchName] = subset;
subset->ref();
rule->remove(subset);
n.compile();
n.epilog();
}
have_nat = (have_nat || (nat_rules_count > 0));
if (Compiler::isRootRuleSet(nat))
{
generated_scripts[ruleset_name] = main_str;
} else
{
generated_scripts[ruleset_name] = new ostringstream();
}
if (n.getCompiledScriptLength() > 0)
{
*(generated_scripts[ruleset_name]) << n.getCompiledScript();
*(generated_scripts[ruleset_name]) << endl;
}
conf_files[ruleset_name] = getConfFileName(ruleset_name,
fwobjectname,
fw_file_name);
const list<NATCompiler_pf::redirectRuleInfo> lst =
n.getRedirRulesInfo();
redirect_rules_info.insert(redirect_rules_info.begin(),
lst.begin(), lst.end());
}
NATCompiler_pf n( objdb, fwobjectname, ipv6_policy, oscnf,
table_factory );
n.setDebugLevel( dl );
n.setDebugRule( drn );
n.setVerbose( verbose );
if (test_mode) n.setTestMode();
bool have_nat=false;
if ( n.prolog() > 0 )
for (list<FWObject*>::iterator p=all_policies.begin();
p!=all_policies.end(); ++p )
{
have_nat=true;
Policy *policy = Policy::cast(*p);
string ruleset_name = policy->getName();
if (Compiler::isRootRuleSet(policy))
ruleset_name = "__main__";
n.compile();
n.epilog();
}
if (!table_factories.count(ruleset_name))
table_factories[ruleset_name] = new TableFactory();
PolicyCompiler_pf c( objdb, fwobjectname, ipv6_policy, oscnf,
&n, table_factory );
PolicyCompiler_pf c( objdb, fwobjectname, ipv6_policy, oscnf,
&redirect_rules_info,
table_factories[ruleset_name] );
c.setDebugLevel( dl );
c.setDebugRule( drp );
c.setVerbose( verbose );
if (test_mode) c.setTestMode();
bool have_pf=false;
if ( c.prolog() > 0 )
{
have_pf=true;
cout << " Compiling policy rules for "
<< fwobjectname
<< " ..." << endl << flush;
c.compile();
c.epilog();
}
generated_script += table_factory->PrintTables();
generated_script += "\n";
if (have_nat) generated_script += n.getCompiledScript();
if (have_pf) generated_script += c.getCompiledScript();
// run policy compiler for each branch we have found in the
// ruleset and store the result in a separate .conf file
//
map<string,RuleSet*>::iterator bi;
for (bi=branches.begin(); bi!=branches.end(); ++bi)
{
table_factory = new TableFactory();
string branchName = bi->first;
RuleSet *subset = bi->second;
PolicyCompiler_pf c( objdb , fwobjectname, ipv6_policy,
oscnf, &n, table_factory );
c.setSourceRuleSet( subset );
c.setRuleSetName(branchName);
c.setSourceRuleSet( policy );
c.setRuleSetName(policy->getName());
c.setDebugLevel( dl );
c.setDebugRule( drp );
c.setVerbose( verbose );
if (test_mode) c.setTestMode();
if ( c.prolog() > 0 )
int pf_rules_count = 0;
if ( (pf_rules_count=c.prolog()) > 0 )
{
cout << " Compiling rules for anchor "
<< branchName
<< " ..." << endl << flush;
c.compile();
c.epilog();
string anchor_file_name;
if (fw_file_name.empty())
{
anchor_file_name=string(fwobjectname) + "-" + branchName + ".conf";
} else
{
string::size_type n = fw_file_name.rfind(".");
anchor_file_name = fw_file_name;
anchor_file_name.erase(n);
anchor_file_name.append("-" + branchName + ".conf");
}
anchor_files[branchName] = anchor_file_name;
ofstream pf_file;
pf_file.exceptions(ofstream::eofbit|ofstream::failbit|ofstream::badbit);
#ifdef _WIN32
pf_file.open(anchor_file_name.c_str(), ios::out|ios::binary);
#else
pf_file.open(anchor_file_name.c_str());
#endif
pf_file << endl;
pf_file << table_factory->PrintTables();
pf_file << endl;
pf_file << c.getCompiledScript();
pf_file.close();
}
have_pf = (have_pf || (pf_rules_count > 0));
if (Compiler::isRootRuleSet(policy))
{
generated_scripts[ruleset_name] = main_str;
} else
{
generated_scripts[ruleset_name] = new ostringstream();
}
if (c.getCompiledScriptLength() > 0)
{
*(generated_scripts[ruleset_name]) << c.getCompiledScript();
*(generated_scripts[ruleset_name]) << endl;
}
conf_files[ruleset_name] = getConfFileName(ruleset_name,
fwobjectname,
fw_file_name);
}
}
/*
* now write generated scripts to files
*/
for (map<string, ostringstream*>::iterator fi=generated_scripts.begin();
fi!=generated_scripts.end(); fi++)
{
string ruleset_name = fi->first;
string file_name = conf_files[ruleset_name];
ostringstream *strm = fi->second;
ofstream pf_file;
pf_file.exceptions(ofstream::eofbit|ofstream::failbit|ofstream::badbit);
ofstream pf_file;
pf_file.exceptions(
ofstream::eofbit|ofstream::failbit|ofstream::badbit);
#ifdef _WIN32
pf_file.open(pf_file_name.c_str(), ios::out|ios::binary);
pf_file.open(file_name.c_str(), ios::out|ios::binary);
#else
pf_file.open(pf_file_name.c_str());
pf_file.open(file_name.c_str());
#endif
if (prolog_place == "pf_file_top")
printProlog(pf_file, pre_hook);
pf_file << endl;
list<string> limits;
if (options->getBool("pf_do_limit_frags") &&
options->getInt("pf_limit_frags")>0 )
limits.push_back(string("frags ") +
options->getStr("pf_limit_frags"));
if (options->getBool("pf_do_limit_states") &&
options->getInt("pf_limit_states")>0 )
limits.push_back(string("states ") +
options->getStr("pf_limit_states"));
if (options->getBool("pf_do_limit_src_nodes") &&
options->getInt("pf_limit_src_nodes")>0 )
limits.push_back(string("src-nodes ") +
options->getStr("pf_limit_src_nodes"));
if (options->getBool("pf_do_limit_tables") &&
options->getInt("pf_limit_tables")>0 )
limits.push_back(string("tables ") +
options->getStr("pf_limit_tables"));
if (options->getBool("pf_do_limit_table_entries") &&
options->getInt("pf_limit_table_entries")>0 )
limits.push_back(string("table-entries ") +
options->getStr("pf_limit_table_entries"));
if (limits.size() > 0)
{
pf_file << "set limit ";
if (limits.size() > 1 ) pf_file << "{ ";
string all_limits;
for_each(limits.begin(), limits.end(), join( &all_limits, ", "));
pf_file << all_limits;
if (limits.size() > 1 ) pf_file << " }";
pf_file << endl;
}
if ( ! options->getStr("pf_optimization").empty() )
pf_file << "set optimization "
<< options->getStr("pf_optimization") << endl;
pf_file << printTimeout(options,
"pf_do_timeout_interval","pf_timeout_interval",
"interval");
pf_file << printTimeout(options,
"pf_do_timeout_frag","pf_timeout_frag",
"frag");
pf_file << printTimeout(options,
"pf_set_tcp_first","pf_tcp_first",
"tcp.first" );
pf_file << printTimeout(options,
"pf_set_tcp_opening","pf_tcp_opening",
"tcp.opening" );
pf_file << printTimeout(options,
"pf_set_tcp_established","pf_tcp_established",
"tcp.established" );
pf_file << printTimeout(options,
"pf_set_tcp_closing","pf_tcp_closing",
"tcp.closing" );
pf_file << printTimeout(options,
"pf_set_tcp_finwait","pf_tcp_finwait",
"tcp.finwait" );
pf_file << printTimeout(options,
"pf_set_tcp_closed","pf_tcp_closed",
"tcp.closed" );
pf_file << printTimeout(options,
"pf_set_udp_first","pf_udp_first",
"udp.first" );
pf_file << printTimeout(options,
"pf_set_udp_single","pf_udp_single",
"udp.single" );
pf_file << printTimeout(options,
"pf_set_udp_multiple","pf_udp_multiple",
"udp.multiple" );
pf_file << printTimeout(options,
"pf_set_icmp_first","pf_icmp_first",
"icmp.first" );
pf_file << printTimeout(options,
"pf_set_icmp_error","pf_icmp_error",
"icmp.error" );
pf_file << printTimeout(options,
"pf_set_other_first","pf_other_first",
"other.first" );
pf_file << printTimeout(options,
"pf_set_other_single","pf_other_single",
"other.single" );
pf_file << printTimeout(options,
"pf_set_other_multiple","pf_other_multiple",
"other.multiple" );
pf_file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_start",
"adaptive.start" );
pf_file << printTimeout(options,
"pf_set_adaptive","pf_adaptive_end",
"adaptive.end");
// check if any interface is marked as 'unprotected'
// and generate 'set skip on <ifspec>' commands
if (fw->getStr("version")=="ge_3.7" ||
fw->getStr("version")=="4.x")
{
for (list<FWObject*>::iterator i=all_interfaces.begin();
i!=all_interfaces.end(); ++i)
if (ruleset_name == "__main__")
{
Interface *iface=dynamic_cast<Interface*>(*i);
assert(iface);
if ( iface->isUnprotected())
pf_file << "set skip on " << iface->getName() << endl;
printStaticOptions(pf_file, fw);
}
pf_file << table_factories[ruleset_name]->PrintTables();
pf_file << strm->str();
pf_file.close();
}
pf_file << endl;
if (prolog_place == "pf_file_after_set")
printProlog(pf_file, pre_hook);
string scrub_options;
if (options->getBool("pf_do_scrub"))
{
if (options->getBool("pf_scrub_reassemble"))
scrub_options+="fragment reassemble ";
else
{
if (options->getBool("pf_scrub_fragm_crop"))
scrub_options+="fragment crop ";
else
{
if (options->getBool("pf_scrub_fragm_drop_ovl"))
scrub_options+="fragment drop-ovl ";
}
}
}
if (options->getBool("pf_scrub_no_df")) scrub_options+="no-df ";
if (!scrub_options.empty())
{
pf_file << "#" << endl;
pf_file << "# Scrub rules" << endl;
pf_file << "#" << endl;
pf_file << "scrub in all " << scrub_options << endl;
}
scrub_options="";
if (options->getBool("pf_scrub_random_id")) scrub_options+="random-id ";
if (options->getBool("pf_scrub_use_minttl")) scrub_options+="min-ttl " + options->getStr("pf_scrub_minttl") + " ";
if (options->getBool("pf_scrub_use_maxmss")) scrub_options+="max-mss " + options->getStr("pf_scrub_maxmss") + " ";
if (!scrub_options.empty())
{
pf_file << "scrub out all " << scrub_options << endl;
}
pf_file << endl;
if (prolog_place == "pf_file_after_scrub")
printProlog(pf_file, pre_hook);
//pf_file << table_factory->PrintTables();
//pf_file << endl;
if (prolog_place == "pf_file_after_tables")
printProlog(pf_file, pre_hook);
pf_file << generated_script;
pf_file.close();
char *timestr;
time_t tm;
struct tm *stm;
@ -826,9 +855,9 @@ int main(int argc, char * const *argv)
<< user_name << "\n#\n";
fw_file << MANIFEST_MARKER << "* " << fw_file_name << endl;
fw_file << MANIFEST_MARKER << " " << pf_file_name << endl;
for (map<string,string>::iterator i=anchor_files.begin();
i!=anchor_files.end(); ++i)
//fw_file << MANIFEST_MARKER << " " << pf_file_name << endl;
for (map<string,string>::iterator i=conf_files.begin();
i!=conf_files.end(); ++i)
fw_file << MANIFEST_MARKER << " " << i->second << endl;
fw_file << "#" << endl;
@ -869,15 +898,17 @@ int main(int argc, char * const *argv)
<< " || exit 1"
<< endl;
for (map<string,string>::iterator i=anchor_files.begin();
i!=anchor_files.end(); ++i)
fw_file << "$PFCTL " << pfctl_dbg
<< "-a " << i->first << " "
<< pfctl_f_option
<< "${FWDIR}/" << i->second
<< " || exit 1"
<< endl;
for (map<string,string>::iterator i=conf_files.begin();
i!=conf_files.end(); ++i)
{
if (i->first != "__main__")
fw_file << "$PFCTL " << pfctl_dbg
<< "-a " << i->first << " "
<< pfctl_f_option
<< "${FWDIR}/" << i->second
<< " || exit 1"
<< endl;
}
fw_file << endl;
fw_file << "#" << endl;
fw_file << "# Epilog script" << endl;

View File

@ -102,7 +102,12 @@ int NATCompiler_pf::prolog()
dbcopy->add(loopback_address,false);
cacheObj(loopback_address);
if (tables) tables->init(dbcopy);
if (tables)
{
tables->init(dbcopy);
if (!isRootRuleSet(getSourceRuleSet()))
tables->setRuleSetName(getRuleSetName());
}
return n;
}
@ -906,8 +911,10 @@ void NATCompiler_pf::compile()
{
bool manage_virtual_addr=fwopt->getBool("manage_virtual_addr");
cout << _(" Compiling NAT rules for ") << fw->getName() << " ..." << endl << flush;
cout << " Compiling " << fw->getName();
if (!getRuleSetName().empty()) cout << " ruleset " << getRuleSetName();
if (ipv6) cout << ", IPv6";
cout << endl << flush;
try {

View File

@ -83,7 +83,8 @@ int PolicyCompiler_pf::prolog()
if (tables)
{
tables->init(dbcopy);
tables->setRuleSetName(getRuleSetName());
if (!isRootRuleSet(getSourceRuleSet()))
tables->setRuleSetName(getRuleSetName());
}
return PolicyCompiler::prolog();
@ -374,133 +375,138 @@ bool PolicyCompiler_pf::fillDirection::processNext()
*/
void PolicyCompiler_pf::addDefaultPolicyRule()
{
if (!getRuleSetName().empty()) return;
if ( getCachedFwOpt()->getBool("mgmt_ssh") &&
!getCachedFwOpt()->getStr("mgmt_addr").empty() )
if (isRootRuleSet(getSourceRuleSet()))
{
PolicyRule *r;
TCPService *ssh=TCPService::cast(dbcopy->create(TCPService::TYPENAME) );
ssh->setInt("dst_range_start",22);
ssh->setInt("dst_range_end",22);
ssh->setName("mgmt_ssh");
dbcopy->add(ssh,false);
cacheObj(ssh); // to keep cache consistent
string mgmt_addr = getCachedFwOpt()->getStr("mgmt_addr");
InetAddr addr;
InetAddr netmask(InetAddr::getAllOnes());
try
if ( getCachedFwOpt()->getBool("mgmt_ssh") &&
!getCachedFwOpt()->getStr("mgmt_addr").empty() )
{
addr = InetAddr(mgmt_addr);
string::size_type sep = mgmt_addr.find("/");
if (sep != string::npos)
PolicyRule *r;
TCPService *ssh =
TCPService::cast(dbcopy->create(TCPService::TYPENAME) );
ssh->setInt("dst_range_start",22);
ssh->setInt("dst_range_end",22);
ssh->setName("mgmt_ssh");
dbcopy->add(ssh,false);
cacheObj(ssh); // to keep cache consistent
string mgmt_addr = getCachedFwOpt()->getStr("mgmt_addr");
InetAddr addr;
InetAddr netmask(InetAddr::getAllOnes());
try
{
addr = InetAddr(mgmt_addr.substr(0,sep));
string nm = mgmt_addr.substr(sep+1);
int o1,o2,o3,o4;
if(sscanf(nm.c_str(), "%3u.%3u.%3u.%3u", &o1, &o2, &o3, &o4)==4)
addr = InetAddr(mgmt_addr);
string::size_type sep = mgmt_addr.find("/");
if (sep != string::npos)
{
netmask = InetAddr(nm);
} else
{
sscanf(nm.c_str(),"%u",&o1);
netmask = InetAddr(o1);
addr = InetAddr(mgmt_addr.substr(0,sep));
string nm = mgmt_addr.substr(sep+1);
int o1,o2,o3,o4;
if (sscanf(nm.c_str(),
"%3u.%3u.%3u.%3u", &o1, &o2, &o3, &o4)==4)
{
netmask = InetAddr(nm);
} else
{
sscanf(nm.c_str(),"%u",&o1);
netmask = InetAddr(o1);
}
}
} catch(FWException &ex)
{
char errstr[256];
sprintf(errstr,
_("Invalid address for the backup ssh access: '%s'"),
mgmt_addr.c_str() );
abort( errstr );
}
} catch(FWException &ex)
{
char errstr[256];
sprintf(errstr,
_("Invalid address for the backup ssh access: '%s'"),
mgmt_addr.c_str() );
abort( errstr );
}
Network *mgmt_workstation = Network::cast(dbcopy->create(Network::TYPENAME));
mgmt_workstation->setName("mgmt_addr");
mgmt_workstation->setAddress( addr );
mgmt_workstation->setNetmask( netmask );
Network *mgmt_workstation =
Network::cast(dbcopy->create(Network::TYPENAME));
mgmt_workstation->setName("mgmt_addr");
mgmt_workstation->setAddress( addr );
mgmt_workstation->setNetmask( netmask );
// IPv4 *mgmt_workstation = IPv4::cast(dbcopy->create(IPv4::TYPENAME));
// mgmt_workstation->setAddress( getCachedFwOpt()->getStr("mgmt_addr") );
dbcopy->add(mgmt_workstation,false);
cacheObj(mgmt_workstation); // to keep cache consistent
dbcopy->add(mgmt_workstation,false);
cacheObj(mgmt_workstation); // to keep cache consistent
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r);
r->setAction(PolicyRule::Accept);
r->setLogging(false);
r->setDirection(PolicyRule::Inbound);
r->setPosition(9999);
r->setComment(" backup ssh access rule ");
r->setHidden(true);
r->setFallback(false);
r->setLabel("backup ssh access rule");
r->setBool("needs_established",true); // supported in ipfw
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r);
r->setAction(PolicyRule::Accept);
r->setLogging(false);
r->setDirection(PolicyRule::Inbound);
r->setPosition(9999);
r->setComment(" backup ssh access rule ");
r->setHidden(true);
r->setFallback(false);
r->setLabel("backup ssh access rule");
r->setBool("needs_established",true); // supported in ipfw
RuleElement *src=r->getSrc();
assert(src!=NULL);
src->addRef(mgmt_workstation);
RuleElement *src=r->getSrc();
assert(src!=NULL);
src->addRef(mgmt_workstation);
RuleElement *dst=r->getDst();
assert(dst!=NULL);
dst->addRef(fw);
RuleElement *dst=r->getDst();
assert(dst!=NULL);
dst->addRef(fw);
RuleElement *srv=r->getSrv();
assert(srv!=NULL);
srv->addRef(ssh);
RuleElement *srv=r->getSrv();
assert(srv!=NULL);
srv->addRef(ssh);
combined_ruleset->push_front(r);
}
combined_ruleset->push_front(r);
}
if ( getCachedFwOpt()->getBool("pass_all_out") )
{
PolicyRule *r;
FWOptions *ruleopt;
if ( getCachedFwOpt()->getBool("pass_all_out") )
{
PolicyRule *r;
FWOptions *ruleopt;
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r);
r->setAction(PolicyRule::Accept);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Outbound);
r->setPosition(10000);
r->setComment(" fallback rule ");
r->setHidden(true);
r->setFallback(true);
r->setLabel("fallback rule");
combined_ruleset->push_back(r);
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r);
r->setAction(PolicyRule::Accept);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Outbound);
r->setPosition(10000);
r->setComment(" fallback rule ");
r->setHidden(true);
r->setFallback(true);
r->setLabel("fallback rule");
combined_ruleset->push_back(r);
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r);
r->setAction(PolicyRule::Deny);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Inbound);
r->setPosition(10001);
r->setComment(" fallback rule ");
r->setHidden(true);
r->setFallback(true);
r->setLabel("fallback rule");
ruleopt = r->getOptionsObject();
ruleopt->setBool("stateless", true);
combined_ruleset->push_back(r);
} else
{
PolicyRule *r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
FWOptions *ruleopt;
r= PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
temp_ruleset->add(r);
r->setAction(PolicyRule::Deny);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Inbound);
r->setPosition(10001);
r->setComment(" fallback rule ");
r->setHidden(true);
r->setFallback(true);
r->setLabel("fallback rule");
ruleopt = r->getOptionsObject();
ruleopt->setBool("stateless", true);
combined_ruleset->push_back(r);
} else
{
PolicyRule *r=
PolicyRule::cast(dbcopy->create(PolicyRule::TYPENAME) );
FWOptions *ruleopt;
temp_ruleset->add(r);
r->setAction(PolicyRule::Deny);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Both);
r->setPosition(10000);
r->setComment(" fallback rule ");
r->setHidden(true);
r->setFallback(true);
r->setLabel("fallback rule");
ruleopt = r->getOptionsObject();
ruleopt->setBool("stateless", true);
combined_ruleset->push_back(r);
temp_ruleset->add(r);
r->setAction(PolicyRule::Deny);
r->setLogging( getCachedFwOpt()->getBool("fallback_log") );
r->setDirection(PolicyRule::Both);
r->setPosition(10000);
r->setComment(" fallback rule ");
r->setHidden(true);
r->setFallback(true);
r->setLabel("fallback rule");
ruleopt = r->getOptionsObject();
ruleopt->setBool("stateless", true);
combined_ruleset->push_back(r);
}
}
}
@ -719,14 +725,17 @@ bool PolicyCompiler_pf::addLoopbackForRedirect::processNext()
RuleElementDst *dst=rule->getDst();
RuleElementSrv *srv=rule->getSrv();
if (pf_comp->natcmp==NULL)
compiler->abort("addLoopbackForRedirect needs a valid pointer to the NAT compiler object");
if (pf_comp->redirect_rules_info==NULL)
compiler->abort(
"addLoopbackForRedirect needs a valid pointer to "
"the list<NATCompiler_pf::redirectRuleInfo> object");
tmp_queue.push_back(rule);
const list<NATCompiler_pf::redirectRuleInfo> lst=pf_comp->natcmp->getRedirRulesInfo();
//const list<NATCompiler_pf::redirectRuleInfo> lst =
// pf_comp->natcmp->getRedirRulesInfo();
if (lst.empty()) return true;
if (pf_comp->redirect_rules_info->empty()) return true;
/*
* struct redirectRuleInfo {
@ -751,7 +760,8 @@ bool PolicyCompiler_pf::addLoopbackForRedirect::processNext()
assert(a);
list<NATCompiler_pf::redirectRuleInfo>::const_iterator k;
for (k=lst.begin(); k!=lst.end(); ++k)
for (k=pf_comp->redirect_rules_info->begin();
k!=pf_comp->redirect_rules_info->end(); ++k)
{
if ( *a == *(k->old_tdst) && *s == *(k->tsrv) )
{
@ -942,6 +952,11 @@ bool PolicyCompiler_pf::printScrubRule::processNext()
void PolicyCompiler_pf::compile()
{
cout << " Compiling " << fw->getName();
if (!getRuleSetName().empty()) cout << " ruleset " << getRuleSetName();
if (ipv6) cout << ", IPv6";
cout << endl << flush;
try
{
Compiler::compile();

View File

@ -29,6 +29,7 @@
#include <fwbuilder/libfwbuilder-config.h>
#include "fwcompiler/PolicyCompiler.h"
#include "NATCompiler_pf.h"
#include "TableFactory.h"
namespace libfwbuilder {
@ -45,8 +46,6 @@ namespace libfwbuilder {
namespace fwcompiler {
class NATCompiler_pf;
class PolicyCompiler_pf : public PolicyCompiler {
public:
@ -442,11 +441,11 @@ namespace fwcompiler {
const std::string &fwname,
bool ipv6_policy,
fwcompiler::OSConfigurator *_oscnf,
NATCompiler_pf *_natcmp,
const std::list<NATCompiler_pf::redirectRuleInfo> *rri,
TableFactory *tbf = NULL) :
PolicyCompiler(_db, fwname, ipv6_policy, _oscnf)
{
natcmp=_natcmp;
redirect_rules_info = rri;
tables = tbf;
}
@ -457,9 +456,8 @@ namespace fwcompiler {
protected:
TableFactory *tables;
NATCompiler_pf *natcmp;
libfwbuilder::IPv4 *loopback_address;
const std::list<NATCompiler_pf::redirectRuleInfo> *redirect_rules_info;
private:

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE FWObjectDatabase SYSTEM "fwbuilder.dtd">
<FWObjectDatabase xmlns="http://www.fwbuilder.org/1.0/" version="7" lastModified="1212115906" id="root">
<FWObjectDatabase xmlns="http://www.fwbuilder.org/1.0/" version="7" lastModified="1212118893" id="root">
<Library color="#d2ffd0" comment="User defined objects" id="syslib001" name="User">
<ObjectGroup id="stdid01_1" name="Objects">
<ObjectGroup id="stdid01_1_og_ats_1" name="Address Tables">
@ -27,6 +27,8 @@
<IPv4 comment="" id="id45D61A0923626" name="VRRP" address="224.0.0.18" netmask="255.255.255.255"/>
<IPv6 comment="" id="id483426D06131" name="ipv6-1" address="fe80::aaaa:bbbb:cccc:1" netmask="128"/>
<IPv6 comment="" id="id483426D16131" name="ipv6-2" address="fe80::aaaa:bbbb:cccc:2" netmask="128"/>
<IPv6 comment="" id="id48416A7116880" name="altavista" address="3ffe:1200:2001:1:8000::1" netmask="128"/>
<IPv6 comment="" id="id48416A7216880" name="6bone.net" address="2001:5c0:0:2::24" netmask="128"/>
</ObjectGroup>
<ObjectGroup id="stdid04_1" name="Groups">
<ObjectGroup id="id3B4572AF" name="group1">
@ -110,15 +112,15 @@
<ObjectRef ref="id4387287A18346"/>
</ObjectGroup>
<ObjectGroup comment="" id="id4834A2238571" name="ipv6 addresses">
<ObjectRef ref="id483426D06131"/>
<ObjectRef ref="id483426D16131"/>
<ObjectRef ref="id4834B9206131"/>
<ObjectRef ref="id48416A7016880"/>
<ObjectRef ref="id48416A7216880"/>
<ObjectRef ref="id48416A7116880"/>
</ObjectGroup>
<ObjectGroup comment="" id="id4834A2278571" name="ipv4 ipv6 addresses">
<ObjectRef ref="id417B3641"/>
<ObjectRef ref="id483426D06131"/>
<ObjectRef ref="id483426D16131"/>
<ObjectRef ref="id4388C37D674"/>
<ObjectRef ref="id48416A7216880"/>
<ObjectRef ref="id48416A7116880"/>
</ObjectGroup>
</ObjectGroup>
<ObjectGroup id="stdid02_1" name="Hosts">
@ -831,6 +833,8 @@
<Network comment="" id="id43913DEA25682" name="Internal_net_t" address="192.168.1.0" netmask="255.255.255.0"/>
<Network comment="" id="id4733FFE419714" name="n-192.168.2.0" address="192.168.2.0" netmask="255.255.255.0"/>
<NetworkIPv6 comment="" id="id4834B9206131" name="net-fe80" address="fe80::" netmask="64"/>
<NetworkIPv6 comment="" id="id48416A7016880" name="DIGITAL-CA-DEC" address="3ffe:1200:2000::" netmask="36"/>
<NetworkIPv6 comment="" id="id48416A7316880" name="HEXAGO-V6-NET1" address="2001:5c0::" netmask="32"/>
</ObjectGroup>
<ObjectGroup id="stdid15_1" name="Address Ranges">
<AddressRange comment="" id="id3CD8769F" name="test_range_1" start_address="192.168.1.11" end_address="192.168.1.15"/>
@ -24365,7 +24369,7 @@ echo '%FWBPROMPT%'; sh /tmp/%FWSCRIPT%
<Option name="verify_interfaces">False</Option>
</FirewallOptions>
</Firewall>
<Firewall comment="" host_OS="linux24" id="id4833F62B6131" inactive="False" lastCompiled="1211586650" lastInstalled="0" lastModified="1212115906" name="firewall-ipv6-1" platform="iptables" ro="False" version="">
<Firewall comment="" host_OS="linux24" id="id4833F62B6131" inactive="False" lastCompiled="1212115999" lastInstalled="0" lastModified="1212118783" name="firewall-ipv6-1" platform="iptables" ro="False" version="">
<NAT id="id4833F62F6131" name="NAT"/>
<Policy id="id483F5B7623190" name="Policy_ipv4"/>
<Policy id="id4833F62E6131" name="Policy">
@ -24391,7 +24395,7 @@ echo '%FWBPROMPT%'; sh /tmp/%FWSCRIPT%
</PolicyRule>
<PolicyRule action="Accept" comment="" direction="Both" disabled="False" id="id4834578B6131" log="False" position="1">
<Src neg="False">
<ObjectRef ref="id483426D06131"/>
<ObjectRef ref="id48416A7216880"/>
</Src>
<Dst neg="False">
<ObjectRef ref="id4833F6316131"/>
@ -24411,7 +24415,7 @@ echo '%FWBPROMPT%'; sh /tmp/%FWSCRIPT%
</PolicyRule>
<PolicyRule action="Accept" direction="Both" disabled="False" id="id4834577C6131" log="True" position="2">
<Src neg="False">
<ObjectRef ref="id483426D06131"/>
<ObjectRef ref="id48416A7116880"/>
</Src>
<Dst neg="False">
<ObjectRef ref="id4833F62B6131"/>

File diff suppressed because it is too large Load Diff