Removing DROP from nat table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Through recent upgrades I've learned that the nat table no longer allows DROP as a target.  I've done googling to try to find reasons why this was removed, and hopefully find workarounds.  I may have work arounds (using the raw or mangle tables to do the DROP?).  I'm still interested in the reason why this was changed, other than "it wasn't intended to be used that way."

I'd also like to try to describe my use case, and why using DROP from nat seemed appropriate for it.

I have 200+ users connecting to an OpenVPN server to reach services that are not public.  Each user is assigned an IP address unique to that user.  The router (OpenVPN server) uses primarily the nat table's PREROUTING chain to control access and do port forwarding.

"Hold on, that's your problem right there, you should use filter instead," someone will say.  Maybe, but I'll describe why I didn't.

The router uses port forwarding based on the users source IP and the destinations they are trying to reach in order to allow the connection (meaning, DNAT) or deny the connection (meaning, DROP).


Lets say the users VPN clients have addresses in the range 10.0.0.2 to 10.0.0.250, and 10.0.0.1 being the VPN router.  The router is the single destination address that users "see" and "connect" to.  In actuality, connections to its IP does port forwarding to other machines scattered throughout multiple 192.168.*.* subnets and other non-public subnet ranges.  This arrangement of using 10.0.0.0/24 as the only range clients "see" was to minimize possible IP range conflicts between our users' local networks and our physical server destinations.  Instead it made sense for the users to "connect" to a single fixed destination, and let port forwarding handle the rest.


So the VPN router has a lot of port forwards, of the form (skipping some obvious steps):
iptables -t nat -A nat_fwd_srvc -p tcp --dport 8001 -j DNAT --to 192.168.10.23:80

iptables -t nat -A nat_fwd_srvc -p tcp --dport 8002 -j DNAT --to 192.168.11.19:8080

iptables -t nat -A nat_fwd_srvc -p tcp --dport 8003 -j DNAT --to 192.168.190.5:80

iptables -t nat -A nat_fwd_srvc -p tcp --dport 8004 -j DNAT --to 192.168.190.5:443
..etc, for about 20 hosts.


If a particular service moves to a different host or port number, a single line DNAT can be changed (which does happen).


Access was controlled by tables called from PREROUTING for new connections, that checked the source and destination to see if that user was allowed to reach the given service.  That table was basicly like this (skipping some obvious steps):
iptables -t nat -A natclnt_10_0_0_1 -p tcp --dport 8001 -j nat_fwd_srvc
iptables -t nat -A natclnt_10_0_0_1 -j LOG --log-prefix NatClnt_1=

iptables -t nat -A natclnt_10_0_0_1 -j DROP

iptables -t nat -A natclnt_10_0_0_2 -p tcp --dport 8001 -j nat_fwd_srvc
iptables -t nat -A natclnt_10_0_0_2 -p tcp --dport 8003 -j nat_fwd_srvc
iptables -t nat -A natclnt_10_0_0_2 -p tcp --dport 8004 -j nat_fwd_srvciptables  -t nat -A natclnt_10_0_0_2 -j LOG --log-prefix NatClnt_2=

iptables -t nat -A natclnt_10_0_0_2 -j DROP
...etc
iptables -t nat -A nat_clnt_new -p tcp -s 10.0.0.1 -j natclnt_10_0_0_1 
iptables -t nat -A nat_clnt_new -p tcp -s 10.0.0.2 -j natclnt_10_0_0_2

...etc
iptables -t nat -A nat_clnt_new -j LOG --log-prefix UsrUnk=

iptables -t nat -A nat_clnt_new -j DROP
iptables -t nat -A PREROUTING -p tcp -m state --state NEW -s 10.0.0.0/24 -d 10.0.0.1 -j nat_clnt_new
These chains above would be called when new TCP connections come in from VPN clients trying to reach 10.0.0.1.  The filter table only needs a single "blind" ACCEPT for all new TCP connections from 10.0.0.0/8.


On average, each user is allowed to 5 different services (some just one, some 12 or more).  At 200 such users, that's over 1000 rules just to control access.


The major advantage to this setup was that if a service moved to a different host (say, going from dev/test to production DMZ), only the DNAT line for that one service needed to change.


However, if this setup gets rebuilt using the filter table in the 'intended' way, the rules would have to be like:iptables -t filter -A fwdclnt_10_0_0_1 -p tcp -d  192.168.10.23 --dport 80 -j ACCEPT
iptables -t filter -A fwdclnt_10_0_0_1 -j LOG --log-prefix FwdClnt_1=

iptables -t filter -A fwdclnt_10_0_0_1 -j DROP

iptables -t filter -A fwdclnt_10_0_0_2 -p tcp -d  192.168.10.23 --dport 80 -j ACCEPT
iptables -t filter -A fwdclnt_10_0_0_2 -p tcp -d 192.168.190.5 --dport 80 -j ACCEPT
iptables -t filter -A fwdclnt_10_0_0_2 -p tcp -d 192.168.190.5 --dport 443 -j ACCEPTiptables  -t filter -A fwdclnt_10_0_0_2 -j LOG --log-prefix FwdClnt_2=

iptables -t filter -A fwdclnt_10_0_0_2 -j DROP
...etc

iptables -t filter -A fwdclnt_new -p tcp -s 10.0.0.1 -j fwdclnt_10_0_0_1 
iptables -t filter -A fwdclnt_new -p tcp -s 10.0.0.2 -j fwdclnt_10_0_0_2

...etc

iptables -t filter -A fwdclnt_new -j LOG --log-prefix UsrUnk=

iptables -t filter -A fwdclnt_new -j DROP
iptables -t filter -A FORWARD -p tcp -m state --state NEW -s 10.0.0.0/24 -d 10.0.0.1 -j fwdclnt_new

Notice that in this setup, if a service gets moved to another host or port, potentially hundreds of filter rules also have to be changed to reflect that.  Much more laborious and error prone.



Comments welcome.
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux