Time to do a little network tweaking.
Increase our iptables connection tracking numbers:
ipt_recent parameters:
Note that by default these values are used by ipt_recent module:
ip_list_tot=100 Number of addresses remembered per table
ip_pkt_list_tot=20 Number of packets per address remembered
ip_list_hash_size=0 Hash table size. 0 means to calculate it based on ip_list_tot, default: 512
ip_list_perms=0644 Permissions for /proc/net/ipt_recent/* files
In some kernels, ipt_recent is xt_recent and ip_conntrack is nf_conntrack, so I've included them all. It won't hurt, but you may get a warning when your system is running about it.
Cool. It worked. Let's get to our iptables rules. Don't forget that your load balancer is a router, so we're going to start off with NAT. We assume that eth0 is our external interface.
Now, we create two new iptables tables. One to log and drop illegal packets and another for rate limiting purposes. The latter is especially useful if we have a webserver running.
Our "always accept from the loopback interface" and "always accept related and established connections" rules follow:
OK, time to separate the wheat from the chaff. Disallow any type of invalid packets by sending them to our new table, LOGDROP:
Following this, we should add any hosts we trust, such as incoming connections from your VPN and generally any incoming connections that you don't want to add to your rate limit:
Now, assuming that we have a webserver running, I am going to allow access to ports 80 (http) and 443 (https). This is not complete access as you can see, as any new connection goes to my RATELIMIT.
Next, we can add some new trusted connections but this time, not completely trusted. Say some partners. We want them to be actually rate limited, just in case.
Now, we'll add ports 80 and 443 once again. Why? Well, if our client hasn't hit our rate limit, they're going to return from our RATELIMIT chain, so we want to accept that.
And the obligatory "if it doesn't fit any of our aforementioned rules, kill it with fire":
Now, once again, our load balancer is a router so we need to enable IP forwarding on it. BUT, for security purposes what we'll do is that we'll only allow it to forward packets from our network to specific hosts, such as NTP, DNS, apt-get and yum update servers. In this example, we assume that the subnets behind our load balancer are the 172.16.104.0/22 and the 172.16.108/24 ones.
Anything that originates from our network should be allowed:
Our LOGDROP chain:
And finally our RATELIMIT chain:
As you can see, this is extremely liberal. It needs 80 new connections attempts every 5 seconds from the same IP address to start dropping packets. You need to tweak the values according to the needs of your webserver.
Let's make the changes permanent:
And finally, tell to the kernel that it should allow forwarding as well:
Increase our iptables connection tracking numbers:
ipt_recent parameters:
Note that by default these values are used by ipt_recent module:
ip_list_tot=100 Number of addresses remembered per table
ip_pkt_list_tot=20 Number of packets per address remembered
ip_list_hash_size=0 Hash table size. 0 means to calculate it based on ip_list_tot, default: 512
ip_list_perms=0644 Permissions for /proc/net/ipt_recent/* files
root@zen-lb:~# vi /etc/modprobe.d/ipt_recent.confoptions ipt_recent ip_list_tot=3000 ip_pkt_list_tot=100
options xt_recent ip_list_tot=3000 ip_pkt_list_tot=100
options ip_conntrack hashsize=25000
options nf_conntrack hashsize=25000
In some kernels, ipt_recent is xt_recent and ip_conntrack is nf_conntrack, so I've included them all. It won't hurt, but you may get a warning when your system is running about it.
root@zen-lb:~# iptables -F
root@zen-lb:~# modprobe -r ipt_recent
root@zen-lb:~# modprobe ipt_recent
root@zen-lb:~# modprobe -r xt_recent
root@zen-lb:~# modprobe xt_recent
root@zen-lb:~# modprobe xt_recent
root@zen-lb:~# cat /sys/module/xt_recent/parameters/ip_list_tot3000root@zen-lb:~# cat /sys/module/xt_recent/parameters/ip_pkt_list_tot100
Cool. It worked. Let's get to our iptables rules. Don't forget that your load balancer is a router, so we're going to start off with NAT. We assume that eth0 is our external interface.
root@zen-lb:~# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Now, we create two new iptables tables. One to log and drop illegal packets and another for rate limiting purposes. The latter is especially useful if we have a webserver running.
root@zen-lb:~# iptables -N LOGDROP
root@zen-lb:~# iptables -N RATELIMIT
Our "always accept from the loopback interface" and "always accept related and established connections" rules follow:
root@zen-lb:~# iptables -A INPUT -i lo -j ACCEPT
root@zen-lb:~# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
OK, time to separate the wheat from the chaff. Disallow any type of invalid packets by sending them to our new table, LOGDROP:
root@zen-lb:~# iptables -A INPUT -m state --state INVALID -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp ! --syn -m state --state NEW -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags ALL ALL -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags ALL NONE -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j LOGDROP
root@zen-lb:~# iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOGDROP
Following this, we should add any hosts we trust, such as incoming connections from your VPN and generally any incoming connections that you don't want to add to your rate limit:
root@zen-lb:~# iptables -A INPUT -s 172.16.200.0/24 -j ACCEPT
Now, assuming that we have a webserver running, I am going to allow access to ports 80 (http) and 443 (https). This is not complete access as you can see, as any new connection goes to my RATELIMIT.
root@zen-lb:~# iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -j RATELIMIT
Next, we can add some new trusted connections but this time, not completely trusted. Say some partners. We want them to be actually rate limited, just in case.
root@zen-lb:~# iptables -A INPUT -s 192.168.200.0/24 -j ACCEPT
Now, we'll add ports 80 and 443 once again. Why? Well, if our client hasn't hit our rate limit, they're going to return from our RATELIMIT chain, so we want to accept that.
root@zen:~# iptables -A INPUT -m tcp -p tcp --dport 80 -j ACCEPT
root@zen-lb:~# iptables -A INPUT -m tcp -p tcp --dport 443 -j ACCEPT
And the obligatory "if it doesn't fit any of our aforementioned rules, kill it with fire":
root@zen-lb:~# iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
Now, once again, our load balancer is a router so we need to enable IP forwarding on it. BUT, for security purposes what we'll do is that we'll only allow it to forward packets from our network to specific hosts, such as NTP, DNS, apt-get and yum update servers. In this example, we assume that the subnets behind our load balancer are the 172.16.104.0/22 and the 172.16.108/24 ones.
root@zen-lb:~# iptables -A FORWARD -s 172.16.104.0/22,172.16.108.0/24 -d 8.8.8.8,8.8.4.4 -j ACCEPT #DNS
root@zen-lb:~# iptables -A FORWARD -s 172.16.104.0/22,172.16.108.0/24 -d 62.1.38.19,62.1.38.25,140.211.169.197,152.19.134.146,66.35.62.166,66.135.62.201,209.132.181.16,67.203.2.67,85.236.55.6,213.175.193.206,195.154.241.117,74.121.199.234 -j ACCEPT #Oracle Linux, EPEL, Remi and Percona Update Servers
root@zen-lb:~# iptables -A FORWARD -s 172.16.104.0/22,172.16.108.0/24 -d 193.93.167.241,79.107.99.220,83.212.114.205,193.239.214.226,83.212.118.71,193.164.227.145,194.177.210.54,83.212.96.50 -j ACCEPT #Red Hat NTP Servers
root@zen-lb:~# iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
root@zen-lb:~# iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited
Anything that originates from our network should be allowed:
root@zen-lb:~# iptables -A OUTPUT -j ACCEPT
Our LOGDROP chain:
root@zen-lb:~# iptables -A LOGDROP -j LOG --log-prefix "INVALID PACKET:"
root@zen-lb:~# iptables -A LOGDROP -j DROP
And finally our RATELIMIT chain:
root@zen-lb:~# iptables -A RATELIMIT -m recent --set --name RATELIMIT --rsource
root@zen-lb:~# iptables -A RATELIMIT -m recent --rcheck --seconds 5 --hitcount 80 --name RATELIMIT --rsource -j LOG --log-prefix "EXCEEDED RATE:"
root@zen-lb:~# iptables -A RATELIMIT -m recent --rcheck --seconds 5 --hitcount 80 --name RATELIMIT --rsource -j DROP
As you can see, this is extremely liberal. It needs 80 new connections attempts every 5 seconds from the same IP address to start dropping packets. You need to tweak the values according to the needs of your webserver.
Let's make the changes permanent:
root@zen-lb:~# iptables-save > /etc/iptables.up.rules
root@zen-lb:~# vi /etc/init.d/iptables_fw#!/bin/sh
### BEGIN INIT INFO
# Provides: iptables_init
# Required-Start: $local_fs $network
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Firewall script
# Description: Start iptables-based firewall
### END INIT INFO
#
iptables-restore < /etc/iptables.up.rules
root@zen-lb:~# iptables-restore < /etc/iptables.up.rules
root@zen-lb:~# chmod 755 /etc/init.d/iptables_fw
root@zen-lb:~# iptables -F
root@zen-lb:~# service iptables_fw start
root@zen-lb:~# update-rc.d iptables_fw defaults
And finally, tell to the kernel that it should allow forwarding as well:
root@zen-lb:~# echo "1" > /proc/sys/net/ipv4/ip_forward
root@zen-lb:~# vi /etc/sysctl.conf# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
No comments:
Post a Comment