Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Avoiding DROP in iptables nat.POSTROUTING when SNAT is involved (thanks to: The "nat" table is not intended for filtering, the use of DROP is therefore inhibited)

2,601 views
Skip to first unread message

Andrew Gideon

unread,
Feb 18, 2013, 7:00:40 PM2/18/13
to
In upgrading some boxes that are using iptables to SNAT routed traffic, I
am hitting the:

The "nat" table is not intended for filtering, the use of DROP is
therefore inhibited.

restriction. But I'm not sure how to achieve what I want w/o it.

The ruleset I want to implement prevents outbound traffic with an improper
source IP - one that doesn't belong to my network. As I understand it, I
am *supposed* to do this in the filter table. That would be fine
normally, but a check of the source IP cannot reliably be performed in the
filter table. The problem is that an invalid source IP as of filter can
be SNATed into validity by nat.POSTROUTING which runs after
filter.FORWARD.

So...how can one reliably filter packets for invalid source IPs without
checking after nat.POSTROUTING? Or is there some way to do additional
filtering after nat.POSTROUTING runs? I am currently under the impression
that nat.POSTROUTING is the final ruleset to run before a packet departs.

Thanks...

Andrew

Pascal Hambourg

unread,
Feb 21, 2013, 3:46:30 AM2/21/13
to
Hello,

Andrew Gideon a ᅵcrit :
> In upgrading some boxes that are using iptables to SNAT routed traffic, I
> am hitting the:
>
> The "nat" table is not intended for filtering, the use of DROP is
> therefore inhibited.
>
> restriction. But I'm not sure how to achieve what I want w/o it.
>
> The ruleset I want to implement prevents outbound traffic with an improper
> source IP - one that doesn't belong to my network. As I understand it, I
> am *supposed* to do this in the filter table.

Yes.

> That would be fine
> normally, but a check of the source IP cannot reliably be performed in the
> filter table. The problem is that an invalid source IP as of filter can
> be SNATed into validity by nat.POSTROUTING which runs after
> filter.FORWARD.
>
> So...how can one reliably filter packets for invalid source IPs without
> checking after nat.POSTROUTING?

You know what SNAT rules you have in nat.POSTROUTING. So you know what
packets in filter.FORWARD will be SNATed or already have a valid source
address. You can create filtering rules which match the same packets as
the SNAT rules but with the ACCEPT target instead of SNAT.

> Or is there some way to do additional
> filtering after nat.POSTROUTING runs? I am currently under the impression
> that nat.POSTROUTING is the final ruleset to run before a packet departs.

Correct.

Andrew Gideon

unread,
Feb 21, 2013, 3:08:39 PM2/21/13
to
On Thu, 21 Feb 2013 09:46:30 +0100, Pascal Hambourg wrote:

> You know what SNAT rules you have in nat.POSTROUTING. So you know what
> packets in filter.FORWARD will be SNATed or already have a valid source
> address. You can create filtering rules which match the same packets as
> the SNAT rules but with the ACCEPT target instead of SNAT.

I deliberately avoid this right now for a couple of reasons.

First, this means that any given expression that SNAT is occurring must be
implemented twice. Redundancy of this sort is never a good thing; it
means that two different but effectively identical sets of rules need to
be maintained.

[This might not be so bad were there a way to share rulesets over tables,
but - at least as far as I know - there is not.]

Second, this presumes that the rules are perfect. That is, if I err
somehow in filter.FORWARD such that a packet that should be either blocked
or SNATed is not, then the duplicated logic in nat.POSTROUTING will have
the same error. Right now, I avoid this by having as final rules in the
nat.POSTROUTING ruleset some very simple (and therefore tough to get wrong
{8^) logic which blocks anything I might have previously missed.

I usually do pretty well by assuming that I'm less than perfect. It seems
like a mistake waiting to happen to depend upon always getting something -
even just a little complex - correct.

I'm thinking that the only solution that's really guaranteed to avoid
leaking packets with bad source IPs is to have nat.POSTROUTING SNAT
anything with a bad source IP. The presumption would be that
filter.FORWARD would have only permitted what's desired.

This avoids the possibility of leaking, but it doesn't provide any check
against errors on my part.

Am I missing something?

- Andrew

Ken Sims

unread,
Feb 21, 2013, 11:54:11 PM2/21/13
to
Hi Andrew -

On Thu, 21 Feb 2013 20:08:39 GMT, Andrew Gideon
<c182d...@gideon.org> wrote:

>I'm thinking that the only solution that's really guaranteed to avoid
>leaking packets with bad source IPs is to have nat.POSTROUTING SNAT
>anything with a bad source IP. The presumption would be that
>filter.FORWARD would have only permitted what's desired.

That's what I do.

In my nat.POSTROUTING, I have two rules. (Actually I have more, left
over from when I had multiple internet connections. But only two
matter.)

The first ... if the output interface is my internet interface and if
the destination IP address is 192.168.100.1 (the cablemodem's internal
IP address), SNAT to 192.168.100.2. This allows me to easily connect
into the cablemodem's software.

The second ... if the output interface is my internet interface, SNAT
to my static internet IP address.

--
Ken

Pascal Hambourg

unread,
Feb 23, 2013, 4:26:04 AM2/23/13
to
Andrew Gideon a ᅵcrit :
> On Thu, 21 Feb 2013 09:46:30 +0100, Pascal Hambourg wrote:
>
>> You know what SNAT rules you have in nat.POSTROUTING. So you know what
>> packets in filter.FORWARD will be SNATed or already have a valid source
>> address. You can create filtering rules which match the same packets as
>> the SNAT rules but with the ACCEPT target instead of SNAT.
>
> I deliberately avoid this right now for a couple of reasons.
>
> First, this means that any given expression that SNAT is occurring must be
> implemented twice. Redundancy of this sort is never a good thing; it
> means that two different but effectively identical sets of rules need to
> be maintained.

Redundancy of this sort is common with NAT however. For example when you
do port forwarding (destination NAT), you need one DNAT rule in
nat.PREROUTING and one ACCEPT rule in filter.FORWARD for the final
destination. Why would it be different with source NAT ?

You can make it easier by keeping the two rules together in the script,
or using functions which create both rules based on the same parameters.
Or you can mark packets and apply multiple operations in different
tables and chains to packets with a given mark.

> Second, this presumes that the rules are perfect. That is, if I err
> somehow in filter.FORWARD such that a packet that should be either blocked
> or SNATed is not, then the duplicated logic in nat.POSTROUTING will have
> the same error.

There is nothing specific in your case. Wrong rules always result in
packets being incorrectly processed... Deal with it, as all people who
write rulesets do. After writing or modifying a ruleset, you must test it.

> I'm thinking that the only solution that's really guaranteed to avoid
> leaking packets with bad source IPs is to have nat.POSTROUTING SNAT
> anything with a bad source IP.

That is not even true. Not all outgoing packets pass through
nat.POSTROUTING. The nat table chains see only (but not all) packets in
the state NEW. Packet is in any other state skip the nat table chains.
This the reason why filtering in this table is not reliable.

Ken Sims

unread,
Feb 23, 2013, 10:17:10 AM2/23/13
to
Hi Pascal -

On Sat, 23 Feb 2013 10:26:04 +0100, Pascal Hambourg
<boite-...@plouf.fr.eu.org> wrote:

>Redundancy of this sort is common with NAT however. For example when you
>do port forwarding (destination NAT), you need one DNAT rule in
>nat.PREROUTING and one ACCEPT rule in filter.FORWARD for the final
>destination. Why would it be different with source NAT ?

It wouldn't have to be that redundant. You can DNAT specific ports to
specific IP addresses (such as to different servers in a DMZ), but
ACCEPT everything being FORWARDed to those IP addresses.

--
Ken
0 new messages