dprovencher
asked on
IPTABLES router with traffic accounting
Hi everyone, I'm trying to build up a complete, stable, and working as expected router/firewall for my network. I've searched extensively and now I'm kinda stuck, as I think I understand how it works and I'm not sure if I do really, so here I am. The actual code running at system statup is included below. I'm running on the most recent debian release I installed not so long ago (linux-2.6.18-6-686) which includes iptables 1.3.6. I didn't recompile the kernel or anything. What I'm asking for is a simple check of my current scripts, and what must be changed, what should be changed, etc. I want a simple firewall behavior, nothing complicated, as you can see below, only a couple port forwardings, that's it. When this is done there is the accounting part, the goal is to know how much bandwidth which IPs used during a certain period of time (dumping values with iptables -L -v -n -x, this part of the accounting I can work on myself, I'm just asking for iptables related stuff), so the possibilities are, authorized MAC/IP combinations, traffic aimed at the firewall itself, and unknown traffic. I want to know exactly of much data pass through eth0, at all times, I don't want to skip unknown/dropped traffic as it passed through my modem and I'm billed for it. That's where I'm lost, when I forward ports with DNAT, do they still go through INPUT or they go through FORWARD as they should? I couldn't find any information on this anywhere.
Thanks for the help!
Thanks for the help!
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc
modprobe ip_nat_ftp
modprobe ip_nat_irc
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t raw -F
iptables -X
iptables -t nat -X
iptables -t mangle -X
iptables -t raw -X
# Disable traffic while making rules
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
iptables -A OUTPUT -j DROP
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.50
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.50
iptables -t nat -A PREROUTING -i eth0 -p 47 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.50
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1723 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.50
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 4422 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.75
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8880:8889 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.75
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 9990:9999 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.75
iptables -A FORWARD -o eth0 -m mac --mac-source XX:XX:XX:XX:XX:XX -s 10.25.50.75 -j ACCEPT
iptables -A FORWARD -o eth0 -m mac --mac-source XX:XX:XX:XX:XX:XX -s 10.25.50.50 -j ACCEPT
iptables -A FORWARD -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.50 -p tcp --dport 25 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.50 -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.50 -p 47 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.50 -p tcp --dport 1723 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.75 -p tcp --dport 4422 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.75 -p tcp --dport 8880:8889 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.75 -p udp --dport 9990:9999 -m state --state NEW -j ACCEPT
iptables -A FORWARD -j DROP
iptables -A INPUT -i eth0 -m state --state INVALID,NEW -j DROP
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# Accounting
iptables -I FORWARD 2 -s 10.25.50.50
iptables -I FORWARD 2 -d 10.25.50.50
iptables -I FORWARD 2 -s 10.25.50.75
iptables -I FORWARD 2 -d 10.25.50.75
iptables -I INPUT 2 -i eth0
iptables -I OUTPUT 2 -o eth0
# Enable traffic
iptables -D INPUT 1
iptables -D FORWARD 1
iptables -D OUTPUT 1
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'm just wondering why you delete some rules at the end
ASKER
I delete the first rule of each chain, that I added at the top of the script to stop all traffic.
Here's the code I speak of at the top and at the end.
Here's the code I speak of at the top and at the end.
# Disable traffic while making rules
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
iptables -A OUTPUT -j DROP
# Enable traffic
iptables -D INPUT 1
iptables -D FORWARD 1
iptables -D OUTPUT 1
hmm, the script then depends on the current configuration to work proper
To make it behave the same all times I'd change the DROP rules like:
iptables -I INPUT 1 -j DROP
depending on the usage of that script, for example as rc-script, I'd add a default policy for each chain at the beginning like:
iptables -P INPUT DROP
To make it behave the same all times I'd change the DROP rules like:
iptables -I INPUT 1 -j DROP
depending on the usage of that script, for example as rc-script, I'd add a default policy for each chain at the beginning like:
iptables -P INPUT DROP
ASKER
Thanks for the help I'll replace those lines with a policy oriented approach, can you provide insight on the rest of the scripts? Would it be working as expected, secure, etc?
> ... secure, etc?
hmm secure is a wide definition ...
What I see so far:
* if you trust all you clients, then MASQUERADE is ok, otherwise you open the door from inside to outside
* also I can't speak about the other open/DNATted ports
* if port 80 means a web server, HTTP protocol, then your network is wide, wide open unless you take addition care there
hmm secure is a wide definition ...
What I see so far:
* if you trust all you clients, then MASQUERADE is ok, otherwise you open the door from inside to outside
* also I can't speak about the other open/DNATted ports
* if port 80 means a web server, HTTP protocol, then your network is wide, wide open unless you take addition care there
ASKER
80 is a web server, IIS 6. Do you mean my forwarded port 80 is wide open on the destination internal host? If so, well that's what I want, I mean the outside being able to reach my web server. If you mean that the linux box is wide open can you give me some directions as to what is open and how?
Thanks!
Thanks!
I meant that most attack are against web servers today
a packetfilter won't detect much there
So my comment about port 80 might or might not be serious:)
a packetfilter won't detect much there
So my comment about port 80 might or might not be serious:)
ASKER
Ok yeah I know that, I even closed my FTP and SQL ports because I don't really need them, they were steadily brute-forced. I had no worries my passwords are strong but it was generating very unwanted traffic and clogging my old router sometimes.
Anyway, since nobody sees security risks in my script or things I could improve I guess I got it mostly right :)
Thanks for the help, I'll reward you 500 points in a few days for your first answer concerning DNAT going through INPUT or not as this was my big question.
Anyway, since nobody sees security risks in my script or things I could improve I guess I got it mostly right :)
Thanks for the help, I'll reward you 500 points in a few days for your first answer concerning DNAT going through INPUT or not as this was my big question.
ASKER
Ok I updated the points, I'll post my complete solution for others to use when I get some spare time in some days.
ASKER
So here are my scripts, the first is the firewall script, that you load at startup, and the second is the accounting data dumping (on a MSSQL server, I use isql for this) that you can run with cron, I run it every minute. I didn't comment the code cause I'm lazy but I'm sure you can figure it out as I'm myself a beginner with iptables. My lastest addition is the interface "lo" lines in the stop script cause at shutdown bind would hang for like 2 minutes.
Enjoy!
Enjoy!
#! /bin/sh
case "$1" in
start)
echo "Starting firewall"
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t raw -F
iptables -X
iptables -t nat -X
iptables -t mangle -X
iptables -t raw -X
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc
modprobe ip_nat_ftp
modprobe ip_nat_irc
echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
iptables -N ACCOUNTING
iptables -A ACCOUNTING -d 10.25.50.50 -j RETURN
iptables -A ACCOUNTING -s 10.25.50.50 -j RETURN
iptables -A ACCOUNTING -d 10.25.50.75 -j RETURN
iptables -A ACCOUNTING -s 10.25.50.75 -j RETURN
iptables -A ACCOUNTING -d 10.25.50.225 -j RETURN
iptables -A ACCOUNTING -s 10.25.50.225 -j RETURN
iptables -A ACCOUNTING -d 10.25.50.226 -j RETURN
iptables -A ACCOUNTING -s 10.25.50.226 -j RETURN
iptables -A ACCOUNTING -d 10.25.50.227 -j RETURN
iptables -A ACCOUNTING -s 10.25.50.227 -j RETURN
iptables -A ACCOUNTING -i eth0 -j RETURN
iptables -A ACCOUNTING -o eth0 -j RETURN
iptables -A FORWARD -j ACCOUNTING
iptables -A OUTPUT -o eth0 -j ACCOUNTING
iptables -A INPUT -i eth0 -j ACCOUNTING
iptables -A OUTPUT -j ACCEPT
iptables -A INPUT -i ! eth0 -j ACCEPT
iptables -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.50
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination 10.25.50.50
iptables -A FORWARD -o eth0 -m mac --mac-source 00:11:22:33:44:55 -s 10.25.50.50 -j ACCEPT
iptables -A FORWARD -o eth0 -m mac --mac-source 00:11:22:33:44:55 -s 10.25.50.75 -j ACCEPT
iptables -A FORWARD -o eth0 -m mac --mac-source 00:11:22:33:44:55 -s 10.25.50.225 -j ACCEPT
iptables -A FORWARD -o eth0 -m mac --mac-source 00:11:22:33:44:55 -s 10.25.50.226 -j ACCEPT
iptables -A FORWARD -o eth0 -m mac --mac-source 00:11:22:33:44:55 -s 10.25.50.227 -j ACCEPT
iptables -A FORWARD -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.50 -p tcp --dport 25 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -d 10.25.50.50 -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "Done"
;;
stop)
echo "Stopping firewall"
echo "0" > /proc/sys/net/ipv4/ip_forward
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t raw -F
iptables -X
iptables -t nat -X
iptables -t mangle -X
iptables -t raw -X
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
echo "Done"
;;
reload|restart|force-reload)
/etc/init.d/firewall stop
/etc/init.d/firewall start
;;
*)
echo "Usage: /etc/init.d/firewall {start|stop|reload|restart|force-reload}"
exit 1
;;
esac
exit 0
------------------------------------------------------------------------
#! /bin/sh
RAWDATA=`iptables -Z -x -v -n -L ACCOUNTING`
WHILEI=0
WHILERECORDI=0
SQLQUERIES=$(
echo "$RAWDATA" |
{
while read WHILECURRENTLINE; do
((WHILEI++));
if [ "$WHILEI" -gt 2 ]; then
if [ "$WHILERECORDI" -eq 0 ]; then
CURRENTDOWNBYTES=`echo "$WHILECURRENTLINE" | egrep -o "[0-9]{1,}" | head -n 2 | tail -n 1`;
CURRENTIP=`echo "$WHILECURRENTLINE" | egrep -o "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}" | tail -n 1`;
WHILERECORDI=1;
else
CURRENTUPBYTES=`echo "$WHILECURRENTLINE" | egrep -o "[0-9]{1,}" | head -n 2 | tail -n 1`;
if [ "$CURRENTUPBYTES" -gt 0 ] || [ "$CURRENTDOWNBYTES" -gt 0 ]; then
WHILESQLQUERIES=`echo "INSERT INTO tbl_data (ip, databytesup, databytesdown) VALUES ('$CURRENTIP', $CURRENTUPBYTES, $CURRENTDOWNBYTES)\r\n"$WHILESQLQUERIES`;
fi;
WHILERECORDI=0;
fi;
fi;
done
echo -e "$WHILESQLQUERIES"
}
)
INSERTRETURN=`echo "$SQLQUERIES" | isql SERVER_CONNECTION username password -b | grep -c -m 1 "1"`
if [ "$INSERTRETURN" != "1" ]; then
echo -e "`date +"%F %T"` SQL INSERT ERROR\r" > /dev/tty1;
fi
exit 0
ASKER
Thanks!
And sorry for the amount of points, a related question of mine did not get any answers, I requested a deletion yesterday, I will increase points in this one to 500 when it is deleted, which takes 4 days apparently.