1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-20 02:07:23 +01:00

* PolicyCompiler_ipt.cpp (singleDstNegation::processNext): fixed

bug (no #): policy compiler for iptables did not handle correctly
rules where a host that has multiple addresses was a single object
in a rule element and had negation.

* NATCompiler_ipt.cpp (singleObjectNegation::processNext): added
support for single object negation in OSrc and ODst in NAT rules.
This provides for more compact iptables script in the often used
case where single object is used with negation in these elements
of a NAT rule. Other improvements in handling NAT rules with
negation.
This commit is contained in:
Vadim Kurland 2008-10-18 18:45:02 +00:00
parent c5e41ed161
commit ef3931f4da
10 changed files with 196 additions and 84 deletions

View File

@ -1 +1 @@
#define BUILD_NUM 615
#define BUILD_NUM 616

View File

@ -1,3 +1,17 @@
2008-10-18 vadim <vadim@vk.crocodile.org>
* PolicyCompiler_ipt.cpp (singleDstNegation::processNext): fixed
bug (no #): policy compiler for iptables did not handle correctly
rules where a host that has multiple addresses was a single object
in a rule element and had negation.
* NATCompiler_ipt.cpp (singleObjectNegation::processNext): added
support for single object negation in OSrc and ODst in NAT rules.
This provides for more compact iptables script in the often used
case where single object is used with negation in these elements
of a NAT rule. Other improvements in handling NAT rules with
negation.
2008-10-15 vadim <vadim@vk.crocodile.org>
* ipt.cpp (dumpScript): Explicitly use "\n" instead of endl to

View File

@ -452,7 +452,7 @@ string NATCompiler_ipt::PrintRule::_printDstService(RuleElementOSrv *rel)
// Note print_mask is true by default, print_range is false by default.
string NATCompiler_ipt::PrintRule::_printAddr(Address *o,
bool print_mask,
bool ,
bool print_range)
{
NATCompiler_ipt *ipt_comp=dynamic_cast<NATCompiler_ipt*>(compiler);
@ -525,6 +525,13 @@ string NATCompiler_ipt::PrintRule::_printAddr(Address *o,
return ostr.str();
}
string NATCompiler_ipt::PrintRule::_printSingleObjectNegation(
RuleElement *rel)
{
if (rel->getBool("single_object_negation")) return "! ";
else return "";
}
NATCompiler_ipt::PrintRule::PrintRule(const std::string &name) :
NATRuleProcessor(name)
{
@ -554,16 +561,16 @@ bool NATCompiler_ipt::PrintRule::processNext()
compiler->output << _createChain(rule->getStr("ipt_target"));
// RuleElementOSrc *osrcrel=rule->getOSrc();
Address *osrc=compiler->getFirstOSrc(rule); assert(osrc);
// RuleElementODst *odstrel=rule->getODst();
Address *odst=compiler->getFirstODst(rule); assert(odst);
RuleElementOSrc *osrcrel = rule->getOSrc();
Address *osrc = compiler->getFirstOSrc(rule); assert(osrc);
RuleElementODst *odstrel = rule->getODst();
Address *odst = compiler->getFirstODst(rule); assert(odst);
RuleElementOSrv *osrvrel=rule->getOSrv();
Service *osrv=compiler->getFirstOSrv(rule); assert(osrv);
Service *osrv = compiler->getFirstOSrv(rule); assert(osrv);
Address *tsrc=compiler->getFirstTSrc(rule); assert(tsrc);
Address *tdst=compiler->getFirstTDst(rule); assert(tdst);
Service *tsrv=compiler->getFirstTSrv(rule); assert(tsrv);
Address *tsrc = compiler->getFirstTSrc(rule); assert(tsrc);
Address *tdst = compiler->getFirstTDst(rule); assert(tdst);
Service *tsrv = compiler->getFirstTSrv(rule); assert(tsrv);
// Interface *iface=
// Interface::cast( rule->getRoot()->getById(rule->getInterfaceId() ,true) );
@ -598,7 +605,9 @@ bool NATCompiler_ipt::PrintRule::processNext()
if (osrc_addr==NULL || !osrc_addr->isAny())
{
string osrc_out = _printAddr(osrc);
if (!osrc_out.empty()) cmdout << " -s " << osrc_out;
if (!osrc_out.empty()) cmdout << " -s "
<< _printSingleObjectNegation(osrcrel)
<< osrc_out;
}
// cmdout << " -s ";
@ -611,8 +620,9 @@ bool NATCompiler_ipt::PrintRule::processNext()
}
if (!odst->isAny()) {
cmdout << " -d ";
cmdout << _printAddr(odst);
cmdout << " -d "
<< _printSingleObjectNegation(odstrel)
<< _printAddr(odst);
}
cmdout << " ";

View File

@ -920,25 +920,35 @@ bool NATCompiler_ipt::ReplaceFirewallObjectsTSrc::processNext()
if (obj->getId()==compiler->getFwId() )
{
Address *odst=compiler->getFirstODst(rule);
RuleElementODst *odstrel = rule->getODst();
Address *odst = compiler->getFirstODst(rule);
rel->clearChildren();
Interface *iface=compiler->findInterfaceFor(odst,compiler->fw);
Interface *odst_iface =
compiler->findInterfaceFor(odst, compiler->fw);
if (!odst->isAny() && iface!=NULL) rel->addRef(iface);
else // else use all interfaces except loopback and unnumbered ones
if (!odst->isAny() && odst_iface!=NULL &&
!odstrel->getBool("single_object_negation"))
rel->addRef(odst_iface);
else
{
// else use all interfaces except loopback and unnumbered ones
// also skip interface connected to ODst if single object
// negation was detected in ODst
list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
{
Interface *iface=Interface::cast(*i);
if (! iface->isLoopback() &&
! iface->isUnnumbered() &&
! iface->isBridgePort()
)
rel->addRef( *i );
Interface *iface = Interface::cast(*i);
if (iface->isLoopback() ||
iface->isUnnumbered() ||
iface->isBridgePort() ) continue;
if (odstrel->getBool("single_object_negation") &&
odst_iface->getId()==iface->getId()) continue;
rel->addRef( *i );
}
for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
rel->addRef( *i1 );
@ -1448,6 +1458,30 @@ bool NATCompiler_ipt::splitMultipleICMP::processNext()
return true;
}
bool NATCompiler_ipt::singleObjectNegation::processNext()
{
NATRule *rule=getNext(); if (rule==NULL) return false;
RuleElement *rel = RuleElement::cast(rule->getFirstByType(re_type));
assert(rel);
if (rel->getNeg() && rel->size()==1)
{
FWObject *o = rel->front();
if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
Address *reladdr = Address::cast(o);
if ( reladdr && reladdr->countInetAddresses()==1 &&
!compiler->complexMatch(reladdr, compiler->fw))
{
rel->setNeg(false);
rel->setBool("single_object_negation", true);
}
}
tmp_queue.push_back(rule);
return true;
}
bool NATCompiler_ipt::doOSrcNegation::processNext()
{
NATRule *rule=getNext(); if (rule==NULL) return false;
@ -1466,7 +1500,7 @@ bool NATCompiler_ipt::doOSrcNegation::processNext()
RuleElementTDst *ntdst;
RuleElementTSrv *ntsrv;
string new_chain=NATCompiler_ipt::getNewTmpChainName(rule);
string new_chain = NATCompiler_ipt::getNewTmpChainName(rule);
osrcrel->setNeg(false);
/*
* negation in OSrc :
@ -1728,8 +1762,8 @@ bool NATCompiler_ipt::localNATRule::processNext()
// if ( rule->getStr("ipt_chain").empty())
// {
Address *osrc=compiler->getFirstOSrc(rule);
bool osrcfw= compiler->complexMatch(osrc,compiler->fw);
Address *osrc = compiler->getFirstOSrc(rule);
bool osrcfw = compiler->complexMatch(osrc,compiler->fw);
switch( rule->getRuleType())
{
@ -1744,7 +1778,7 @@ bool NATCompiler_ipt::localNATRule::processNext()
*
* Can use OUTPUT chain only for DNAT rules and a like
*/
if (osrcfw) rule->setStr("ipt_chain","OUTPUT");
if (osrcfw) rule->setStr("ipt_chain", "OUTPUT");
if (osrcfw && osrc->getId()==compiler->fw->getId())
{
RuleElementOSrc *src;
@ -1778,15 +1812,17 @@ bool NATCompiler_ipt::splitIfOSrcAny::processNext()
if (rule->getRuleType()==NATRule::DNAT)
{
// RuleElementOSrc *osrcrel=rule->getOSrc();
Address *osrc=compiler->getFirstOSrc(rule);
RuleElementOSrc *osrcrel = rule->getOSrc();
Address *osrc = compiler->getFirstOSrc(rule);
if (osrc->isAny())
// split if osrc is any OR if it has a single object with negation
if (osrc->isAny() || osrcrel->getBool("single_object_negation"))
{
NATRule *r= NATRule::cast(compiler->dbcopy->create(NATRule::TYPENAME) );
NATRule *r = NATRule::cast(
compiler->dbcopy->create(NATRule::TYPENAME) );
compiler->temp_ruleset->add(r);
r->duplicate(rule);
RuleElementOSrc *nosrcrel=r->getOSrc();
RuleElementOSrc *nosrcrel = r->getOSrc();
nosrcrel->addRef(compiler->fw);
tmp_queue.push_back(r);
}
@ -2220,6 +2256,26 @@ void NATCompiler_ipt::compile()
add( new classifyNATRule( "reclassify rules" ));
add( new ConvertLoadBalancingRules( "convert load balancing rules"));
add( new VerifyRules( "verify rules" ));
#if 0
// ----------- 10/18/2008
add( new splitODstForSNAT(
"split rule if objects in ODst belong to different subnets") );
add( new ReplaceFirewallObjectsODst("replace firewall in ODst" ) );
add( new ReplaceFirewallObjectsTSrc("replace firewall in TSrc" ) );
add( new splitOnDynamicInterfaceInODst(
"split rule if ODst is dynamic interface" ) );
add( new splitOnDynamicInterfaceInTSrc(
"split rule if TSrc is dynamic interface" ) );
add( new ExpandMultipleAddresses("expand multiple addresses") );
add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
// -----------
#endif
add( new singleObjectNegationOSrc(
"negation in OSrc if it holds single object"));
add( new singleObjectNegationODst(
"negation in ODst if it holds single object"));
add( new doOSrcNegation( "process negation in OSrc" ));
add( new doODstNegation( "process negation in ODst" ));
@ -2245,6 +2301,8 @@ void NATCompiler_ipt::compile()
add( new decideOnChain( "decide on chain" ) );
add( new decideOnTarget( "decide on target" ) );
// ----------- 10/18/2008
add( new splitODstForSNAT(
"split rule if objects in ODst belong to different subnets") );
add( new ReplaceFirewallObjectsODst("replace firewall in ODst" ) );
@ -2257,6 +2315,7 @@ void NATCompiler_ipt::compile()
add( new ExpandMultipleAddresses("expand multiple addresses") );
add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
if (ipv6)
add( new DropIPv4Rules("drop ipv4 rules"));
else

View File

@ -304,6 +304,40 @@ namespace fwcompiler {
*/
DECLARE_NAT_RULE_PROCESSOR(splitMultipleICMP);
/**
* prepare for negation of single objects in rule elements
*/
class singleObjectNegation : public NATRuleProcessor
{
std::string re_type;
public:
singleObjectNegation(const std::string &n,std::string _type):
NATRuleProcessor(n) { re_type=_type; }
virtual bool processNext();
};
/**
* single object negation in OSrc
*/
class singleObjectNegationOSrc : public singleObjectNegation
{
public:
singleObjectNegationOSrc(const std::string &n):
singleObjectNegation(n,libfwbuilder::RuleElementOSrc::TYPENAME)
{}
};
/**
* single object negation in ODst
*/
class singleObjectNegationODst : public singleObjectNegation
{
public:
singleObjectNegationODst(const std::string &n):
singleObjectNegation(n,libfwbuilder::RuleElementODst::TYPENAME)
{}
};
/**
* deals with negation in OSrc
*/
@ -478,6 +512,7 @@ namespace fwcompiler {
bool print_mask=true,
bool print_range=false);
virtual std::string _printChainDirectionAndInterface(libfwbuilder::NATRule *r);
virtual std::string _printSingleObjectNegation(libfwbuilder::RuleElement *rel);
public:
PrintRule(const std::string &name);

View File

@ -1104,7 +1104,8 @@ string PolicyCompiler_ipt::PrintRule::_printAddr(Address *o)
}
string PolicyCompiler_ipt::PrintRule::_printSingleObjectNegation(RuleElement *rel)
string PolicyCompiler_ipt::PrintRule::_printSingleObjectNegation(
RuleElement *rel)
{
if (rel->getBool("single_object_negation")) return "! ";
else return "";

View File

@ -945,16 +945,21 @@ bool PolicyCompiler_ipt::printRuleElements::processNext()
bool PolicyCompiler_ipt::singleSrcNegation::processNext()
{
PolicyRule *rule=getNext(); if (rule==NULL) return false;
PolicyRule *rule = getNext(); if (rule==NULL) return false;
RuleElementSrc *srcrel = rule->getSrc();
Address *src = compiler->getFirstSrc(rule);
/* ! A B C ACTION */
if (srcrel->getNeg() && srcrel->size()==1 && src!=NULL &&
!compiler->complexMatch(src,compiler->fw))
if (srcrel->getNeg() && srcrel->size()==1)
{
srcrel->setNeg(false);
srcrel->setBool("single_object_negation",true);
Address *src = compiler->getFirstSrc(rule);
// note: src can be NULL if object in this rule element is a group
// or MultiAddress
if (src!=NULL && src->countInetAddresses()==1 &&
!compiler->complexMatch(src,compiler->fw))
{
srcrel->setNeg(false);
srcrel->setBool("single_object_negation",true);
}
}
tmp_queue.push_back(rule);
@ -963,17 +968,19 @@ bool PolicyCompiler_ipt::singleSrcNegation::processNext()
bool PolicyCompiler_ipt::singleDstNegation::processNext()
{
PolicyRule *rule=getNext(); if (rule==NULL) return false;
RuleElementDst *dstrel=rule->getDst();
Address *dst =compiler->getFirstDst(rule);
PolicyRule *rule = getNext(); if (rule==NULL) return false;
RuleElementDst *dstrel = rule->getDst();
/* A ! B C ACTION */
if (dstrel->getNeg() && dstrel->size()==1 && dst!=NULL &&
!compiler->complexMatch(dst,compiler->fw))
if (dstrel->getNeg() && dstrel->size()==1)
{
dstrel->setNeg(false);
dstrel->setBool("single_object_negation",true);
Address *dst = compiler->getFirstDst(rule);
if (dst!=NULL && dst->countInetAddresses()==1 &&
!compiler->complexMatch(dst,compiler->fw))
{
dstrel->setNeg(false);
dstrel->setBool("single_object_negation",true);
}
}
tmp_queue.push_back(rule);
@ -2596,8 +2603,9 @@ bool PolicyCompiler_ipt::checkForDynamicInterfacesOfOtherObjects::processNext()
bool PolicyCompiler_ipt::expandMultipleAddressesIfNotFWinSrc::processNext()
{
PolicyRule *rule=getNext(); if (rule==NULL) return false;
RuleElementSrc *srcrel=rule->getSrc();
Address *src =compiler->getFirstSrc(rule); assert(src);
RuleElementSrc *srcrel = rule->getSrc();
Address *src =compiler->getFirstSrc(rule);
assert(src);
if (Firewall::cast(src)==NULL) compiler->_expandAddr(rule, srcrel);
tmp_queue.push_back(rule);
return true;
@ -3906,13 +3914,11 @@ void PolicyCompiler_ipt::compile()
add( new fillActionOnReject("fill in action_on_reject 2" ) );
add( new splitServicesIfRejectWithTCPReset(
"split if action on reject is TCP reset 2"));
add( new singleSrcNegation("negation in Src if it holds single object"));
add( new singleDstNegation("negation in Dst if it holds single object"));
/*
* phased out these processors, they are not needed anymore because we use variable
* for dynamic interfaces.
*/
add( new splitIfSrcNegAndFw("split rule if src has negation and fw"));
add( new splitIfDstNegAndFw("split rule if dst has negation and fw"));
@ -3922,29 +3928,14 @@ void PolicyCompiler_ipt::compile()
add( new Logging2("process logging"));
/* this is just a patch for those who do not understand how does
/*
* this is just a patch for those who do not understand how does
* "assume firewall is part of any" work. It also eliminates redundant
* and useless rules in the FORWARD chain for rules assigned to a
* loopback interface.
*/
// add( new decideOnChainIfLoopback("any-any rule on loopback" ) );
#if 0
add( new splitIfSrcAny("split rule if src is any") );
add( new setChainForMangle("set chain for other rules in mangle"));
add( new setChainPreroutingForTag("chain PREROUTING for Tag"));
add( new splitIfDstAny("split rule if dst is any") );
add( new setChainPostroutingForTag("chain POSTROUTING for Tag"));
add( new ExpandGroups("expand all groups"));
add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
add( new eliminateDuplicatesInSRC("eliminate duplicates in SRC" ));
add( new eliminateDuplicatesInDST("eliminate duplicates in DST" ));
add( new eliminateDuplicatesInSRV("eliminate duplicates in SRV" ));
add( new swapMultiAddressObjectsInSrc(
" swap MultiAddress -> MultiAddressRunTime in Src"));
add( new swapMultiAddressObjectsInDst(
" swap MultiAddress -> MultiAddressRunTime in Dst"));
#endif
add( new ExpandGroups("expand all groups"));
add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));

View File

@ -1,15 +1,10 @@
#!/usr/bin/perl
#!/bin/sh
$XMLFILE=@ARGV[0];
$DIFFCMD="diff -C 1 -c -b -B -I \"# Generated\" -I 'Activating ' -I '# Firewall Builder fwb_ipt v' -I 'Can not find file' -I '====' -I 'log '";
XMLFILE=$1
DIFFCMD="diff -C 1 -c -b -B -I \"# Generated\" -I 'Activating ' -I '# Firewall Builder fwb_ipt v' -I 'Can not find file' -I '====' -I 'log '"
fwbedit list -f $XMLFILE -o /User/Firewalls -c -F%name% | sort | while read fwobj; do
echo "$DIFFCMD ${fwobj}.fw.orig ${fwobj}.fw"
done
while (<>) {
$str=$_;
while ( $str=~ /<Firewall / ) {
$str=~ /<Firewall [^>]+name="([^"]*).*$"/;
$fw=$1;
printf "$DIFFCMD %s.fw.orig %s.fw\n",$fw,$fw;
$str=~ s/^.*<Firewall [^>]+name="$fw"[^>]+>//;
}
}

View File

@ -1,7 +1,14 @@
#!/usr/bin/perl
#!/bin/sh
$XMLFILE=@ARGV[0];
XMLFILE=$1
fwbedit list -f $XMLFILE -o /User/Firewalls -c -F%name% | sort | while read fwobj; do
echo "echo"
echo "echo \"============================ $fwobj\""
echo "fwb_ipt -v -f $XMLFILE -xt $fwobj"
done
exit 0
while (<>) {
$str=$_;