Iptables, NAT: avoiding limit on max number of requests per IP by using multiple IPs

connectionsiptablesnat;

In my network, there is a machine which has to make a http request towards a server which is beyond a firewall.

This machine's ip address (as seen from beyond the firewall) can be chosen from a pool of about 5 addresses.

Every ip can execute a maximum number of requests per day, after that, it can't be used again till the next day; the time interval between two requests doesn't matter, as long as the daily limit is not reached.

I would like to configure the firewall's routing table so that, from the client machine, I can make http requests without worrying about the time interval between them. My only concern should be the total daily limit (i.e. number of ips * max requests per ip).

I tried something like:

iptables -m hashlimit -m tcp -A POSTROUTING --syn --hashlimit-name x --hashlimit <MAX REQUESTS>/day -p tcp -s <CLIENT IP> -d <SERVER IP> --dports 80 --to-source <ONE OF THE IPs TO CHOOSE FROM>

And repeated that command for all of the five ips (with a final rule that drops further connection attempts).

But with this configuration I can't do requests in bursts. For example, if MAX_REQUESTS is 9000, i cannot make 9000 requests in the first two minutes, because the hashlimit module deals with averages, and stops matching a rule as soon as the packets' count is above the specified average. Therefore with this configuration I can use that ip only once every 9.6 seconds (=86400/9000): not what I want.

So I'm asking for suggestions about a possible iptables rule (or something else) which would allow me to perform requests in bursts and stay within the daily limit.

Thanks for your time

Silvio

EDIT: I have tried using --hashlimit-burst N, but this parameter only inserts a tolerance for the first N packets, i.e. adds N packets which can match the rule regardless of the average, after which the normal conditions apply. Again, not what I want.

UPDATE: The current candidate iptable command I'm using is

iptables -m hashlimit -m multiport -m tcp -A POSTROUTING -t nat --syn --hashlimit-name NAME --hashlimit MAX_REQUEST/day -p tcp -s SOURCE_IP -d DESTINATION_IP --dports 80 -j SNAT --to-source ONE_OF_THE IPs

It still has the above mentioned problem (can't send packets in bursts).

Best Answer

For tight control, I'd try something along the lines of:

iptables -t nat -A POSTROUTING -s INT_SRC -d EXT_SERVICE --syn --limit MAXREQ/day -j SNAT --to-source EXT_IP1
...

(then I find that's what you already tried :p)

How about using:

iptables -t nat -A POSTROUTING -s INT_SRC -d EXT_SERVICE --syn -j SNAT --to-source EXT_IP_RANGE

Apparently that variant uses a simple round-robin algorithm - I'd try that. I hope your external IPs are in a single range :)


Can't just let further requests fail on their own? Given that you have very specific requirements, I'd probably:

  • add a --log to the rule
  • write a daemon that keeps track of the number of service connections made that day and inserts a rule into the FORWARD that drops further connections to that service
  • have the daemon remove that rule (if present) at midnight and reset its connection count

There doesn't seem to be anything that already exists to handle exactly what you want to do.

Related Topic