Load balancing with iptables in "nth" mode - iptables

Here is my iptables script, it does not work. Port 9000 is closed, opened ports are 9001-9003. I want to balance loadage between three services located at these ports on localhost. What am I doing wrong?
#!/bin/bash
start()
{
echo -e "\e[32mStarting firewall ...\e[m"
iptables -F
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination 127.0.0.1:9001 -m statistic --mode nth --every 3 --packet 0
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination 127.0.0.1:9002 -m statistic --mode nth --every 2 --packet 0
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination 127.0.0.1:9003 -m statistic --mode nth --every 1 --packet 0
}
stop()
{
echo -e "\e[31mStoping firewall ...\e[m"
iptables -F
}
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
*)
echo -e "\e[36mUsage:\e[m {start|stop|restart}"
esac
Thank you.

Here is solution:
#!/bin/bash
start()
{
echo -e "\e[32mStarting firewall ...\e[m"
iptables -t nat -F
iptables -t nat -A OUTPUT -p tcp --dport 9000 -m state --state NEW -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination :9001
iptables -t nat -A OUTPUT -p tcp --dport 9000 -m state --state NEW -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination :9002
iptables -t nat -A OUTPUT -p tcp --dport 9000 -m state --state NEW -m statistic --mode nth --every 1 --packet 0 -j DNAT --to-destination :9003
}
stop()
{
echo -e "\e[31mStoping firewall ...\e[m"
iptables -t nat -F
}
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
*)
echo -e "\e[36mUsage:\e[m {start|stop|restart}"
esac

This will send one package to 9001, the next to 9002 and so on...
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination 127.0.0.1:9001 -m nth --every 3 --packet 0
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination 127.0.0.1:9002 -m nth --every 3 --packet 1
iptables -t nat -A PREROUTING -p tcp --dport 9000 -j DNAT --to-destination 127.0.0.1:9003 -m nth --every 3 --packet 2
You specified the mode parameter twice, -m and --mode.

Related

Iptables setting seem to block all traffic

I am trying to set up iptables to allow SSH port only from outside and all traffic from inside. Also, I'm trying to set some rules to prevent some basic DOS attacks. How do I manage the iptables rules properly?
I installed a Debian VM on VirtualBox where I set up a local static ip such as 10.0.2.3/30. I changed the SSH default port from 22 to 2222. I can connect to SSH from outside after setting up port forwarding on VirtualBox using NAT with 127.0.0.1 port 2222 on Host and 10.0.2.3 port 2222 on Client. So far so good.
Now I tried to set up firewall and DOS protection with iptables using the help of this guide such as I wrote the following script also using the kernel settings as described in the article.
sudo iptables -P INPUT DROP
### 1: Drop invalid packets ###
#sudo iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
### 2: Drop TCP packets that are new and are not SYN ###
#sudo iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
### 3: Drop SYN packets with suspicious MSS value ###
sudo iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
### 4: Block packets with bogus TCP flags ###
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
### 6: Drop ICMP (you usually don't need this protocol) ###
sudo iptables -t mangle -A PREROUTING -p icmp -j DROP
### 7: Drop fragments in all chains ###
sudo iptables -t mangle -A PREROUTING -f -j DROP
### 8: Limit connections per source IP ###
sudo iptables -A INPUT -p tcp -m connlimit --connlimit-above 111 -j REJECT --reject-with tcp-reset
### 9: Limit RST packets ###
sudo iptables -A INPUT -p tcp --tcp-flags RST RST -m limit --limit 2/s --limit-burst 2 -j ACCEPT
sudo iptables -A INPUT -p tcp --tcp-flags RST RST -j DROP
### 10: Limit new TCP connections per second per source IP ###
sudo iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m limit --limit 60/s --limit-burst 20 -j ACCEPT
sudo iptables -A INPUT -p tcp -m conntrack --ctstate NEW -j DROP
### 11: Use SYNPROXY on port 2222 (SSH) (disables connection limiting rule) ###
#sudo iptables -t raw -A PREROUTING -p tcp --dport 2222 -m tcp --syn -j CT --notrack
#sudo iptables -A INPUT -p tcp --dport 2222 -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
sudo iptables -A INPUT -p tcp --dport 2222 -m conntrack --ctstate INVALID -j DROP
### SSH brute-force protection ###
sudo iptables -A INPUT -p tcp --dport 2222 -m conntrack --ctstate NEW -m recent --set
sudo iptables -A INPUT -p tcp --dport 2222 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP
### Protection against port scanning ###
sudo iptables -N port-scanning
sudo iptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
sudo iptables -A port-scanning -j DROP
echo "Allowing traffic from SSH port 2222 and Internet traffic
# Allowing SSH connection from LAN
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
# Allowing Internet traffic
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
### Make the iptables rules persistent after reboot
sudo bash -c "iptables-save > /etc/iptables/rules.v4"
I identified these lines to have an impact on SSH connection from my LAN:
### 1: Drop invalid packets ###
#sudo iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
I cannot connect to SSH when I uncomment these, and I don't understand why.
I figured out that my #1 rule was simply invalid #11 rule. I either had to use one or the other.

Port load balance with IPTables

If my clients connect to my server on port 5000, how would I set IPTables, to split them evenly between 5001 and 5002?
All of this must be done with caution and make sure you have serial/terminal access because there is a chance of you losing your network connection
First enable ipV4 forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -P INPUT ACCEPT
iptables -t nat -A PREROUTING -p tcp --dport 5000 -m statistic --mode nth --every 3 --packet 0 -j REDIRECT --to-port 5000
iptables -t nat -A PREROUTING -p tcp --dport 5000 -m statistic --mode nth --every 2 --packet 0 -j REDIRECT --to-port 5001
iptables -t nat -A PREROUTING -p tcp --dport 5000 -j REDIRECT --to-port 5002

Setup iptable with preventing ab -n 1000 -c 100

I would like to setup basic firewall rules with iptables.
The goal is to reject flood requests per IP. Like "ab -n 100000 -c 1000 "
There are only 2 rules:
iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m limit --limit 100/s --limit-burst 10000 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -i eth0 -j LOG --log-prefix "__test__"
But I when grep iptables log with "sort" and "uniq -c" I see lot's of IPs like:
1 SRC=173.252.77.112
1 SRC=173.252.114.116
1 SRC=173.252.114.114
1 SRC=173.252.114.113
Is "-m state --state NEW" effect only new connections? Then why IPs with low requests count appeared in log?
Please advice.
Finally the solution is:
iptables -A INPUT -i eth0 -p tcp --dport 80 -m hashlimit --hashlimit 1000/sec --hashlimit-burst 5000 --hashlimit-mode dstip --hashlimit-name hosts -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 80 -j REJECT
Do not block SE-crawlers packets and resists against http-flood like: ab -n 1000 -c 100 http://{host}/

Why does the iptables connection limit not work?

this is my iptables, everything works fine, except that these IP's with more than 20 connection wont get blocked.
iptables -F
iptables -X
iptables -I INPUT 1 -i lo -j ACCEPT
iptables -I INPUT 2 -i eth0 -p tcp --dport 6606 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I INPUT 3 -i eth0 -p tcp --dport 6624 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I INPUT 4 -i eth0 -p tcp --dport 6610 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I INPUT 5 -i eth0 -p tcp --dport 6610 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I INPUT 6 -i eth0 -p icmp --icmp-type echo-request -j ACCEPT
iptables -I INPUT 7 -i eth0 -p icmp --icmp-type echo-reply -j ACCEPT
iptables -I INPUT 8 -i eth0 -m connlimit --connlimit-above 20 -j DROP
iptables -I OUTPUT 1 -o lo -j ACCEPT
iptables -I OUTPUT 2 -o eth0 -p tcp --sport 6606 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I OUTPUT 3 -o eth0 -p tcp --sport 6624 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I OUTPUT 4 -o eth0 -p tcp --sport 6610 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I OUTPUT 5 -o eth0 -p tcp --sport 6610 -m state --state NEW,RELATED,ESTABLISHED -m limit --limit 2/s --limit-burst 4 -j ACCEPT
iptables -I OUTPUT 6 -o eth0 -p icmp --icmp-type echo-reply -j ACCEPT
iptables -I OUTPUT 7 -o eth0 -p icmp --icmp-type echo-request -j ACCEPT
iptables -I OUTPUT 8 -o eth0 -m connlimit --connlimit-above 20 -j DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
What's wrong? Why does connection limit not work?
You're accepting connections without a connlimit specification before the connlimit DROP rule is set.
Try putting the DROP rule above all the others or specify a --connlimit-upto inside each one of your ACCEPT rules. e.g.
iptables -A INPUT -i eth0 -p tcp --dport 6606 \
-m state --state NEW,RELATED,ESTABLISHED \
-m connlimit --connlimit-upto 20 -m limit --limit 2/s --limit-burst 4 -j ACCEPT
Actually which connection you wanted to limit here. SSH or HTTP or HTTPS or TELNET.
In the below rule, just replace the port 80 with 22 for SSH and 23 for TELNET, so it should work.
iptables –I INPUT -p tcp --dport 80 -m state --state NEW -m
connlimit --connlimit-above 20 -j REJECT --reject-with
icmp-admin-prohibited
Also, in some of the recent kernel the connlimit module is removed, so either you have to patch up the module inside the kernel or use the hashlimit module for restricting the connections. Hashlimit module is more stronger and flexible that connlimit module.
The below rule will limit to the 20 connections per min for the corresponding destination ip.
iptables -A INPUT-p tcp --dport 80 -m state --state NEW -m hashlimit
--hashlimit-name \ HTTP_LIMIT –hashlimit 20/day--hashlimit-burst 1 --hashlimit-mode dstip -j ACCEPT
For more explanation, refer http://ipset.netfilter.org/iptables-extensions.man.html#lbAW.

IPtables used for load balancing

I am trying to use iptable for load balancing.
The rule I have set is as follows wherein I want to route requests coming to my server with ipaddress 10.x.x.4 to internal ips of the server 10.x.x.1:1010 , 10.x.x.2:1010 and 10.x.x.3:1010
iptables -t nat -A PREROUTING -p udp -d 10.x.x.4 --dport 1010 -m state --state NEW -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 10.x.x.1:1010
iptables -t nat -A PREROUTING -p udp -d 10.x.x.4 --dport 1010 -m state --state NEW -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 10.x.x.2:1010
iptables -t nat -A PREROUTING -p udp -d 10.x.x.4 --dport 1010 -m state --state NEW -m statistic --mode nth --every 3 --packet 0 -j DNAT --to-destination 10.x.x.3:1010
When I execute , the first 4 packets gets routed to each ipaddress correctly.
The 5th packet doesn't get routed and is getting dropped.
How do I debug this issue. Should I increment to value given to --packet ? What should be the correct rule?
You should increment --packet from 0 to n-1 in each command line. Where n is the number given as the parameter to --every.