Everybody, hello!
I'm trying to setup my server firewall using iptables (I have to admit that last time I used iptables was a year ago), but iptables acts contrary to what I ask.
Here is my test script :
#!/bin/sh
IPT="/sbin/iptables"
echo -n "Loading iptables rules..."
# Flush old rules
$IPT --flush
$IPT --delete-chain
# Allow incoming and outgoing for loopback interfaces
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Allow incoming traffic for HTTP(S), SSH and SMTP
$IPT -A INPUT -p tcp --dport 80 -i eth0 -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -i eth0 -j ACCEPT
$IPT -A INPUT -p tcp --dport 22 -j ACCEPT
$IPT -A INPUT -p tcp --dport 25 -i eth0 -j ACCEPT
# Allow ICMP requests
$IPT -A INPUT -p icmp -i eth0 -j ACCEPT
$IPT -A OUTPUT -p icmp -o eth0 -j ACCEPT
# Allow outgoing traffic for SMTP, DNS, NTP, PgSQL, SolR, and SSH
$IPT -A OUTPUT -p tcp --dport 25 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 53 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 53 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 123 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 5433 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 5433 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 8983 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 8983 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 22 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 22 -o eth0.2654 -j ACCEPT
# Deny web server user outgoing connections
$IPT -A OUTPUT -o eth0 -m owner --uid-owner www-data -j DROP
# Drop everything else
$IPT -A INPUT -j DROP
$IPT -A OUTPUT -j DROP
$IPT -A FORWARD -j DROP
echo "rules loaded."
# Print rules as understood, then flush to avoid lockout
sleep 10
$IPT -L
# Flush old rules
$IPT --flush
$IPT --delete-chain
With this script, the server no more aswers to any request but ping (ICMP), then, after 10 seconds, prints following text and exits :
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
100 5920 ACCEPT all -- lo any anywhere anywhere
0 0 ACCEPT tcp -- eth0 any anywhere anywhere tcp dpt:www
0 0 ACCEPT tcp -- eth0 any anywhere anywhere tcp dpt:https
1 52 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh
0 0 ACCEPT tcp -- eth0 any anywhere anywhere tcp dpt:smtp
0 0 ACCEPT icmp -- eth0 any anywhere anywhere
0 0 DROP all -- any any anywhere anywhere
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- any any anywhere anywhere
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
100 5920 ACCEPT all -- any lo anywhere anywhere
0 0 ACCEPT icmp -- any eth0 anywhere anywhere
0 0 ACCEPT tcp -- any eth0 anywhere anywhere tcp dpt:smtp
0 0 ACCEPT tcp -- any eth0 anywhere anywhere tcp dpt:domain
0 0 ACCEPT udp -- any eth0 anywhere anywhere udp dpt:domain
0 0 ACCEPT udp -- any eth0 anywhere anywhere udp dpt:ntp
0 0 ACCEPT tcp -- any eth0.2654 anywhere anywhere tcp dpt:5433
0 0 ACCEPT udp -- any eth0.2654 anywhere anywhere udp dpt:5433
0 0 ACCEPT tcp -- any eth0.2654 anywhere anywhere tcp dpt:8983
0 0 ACCEPT udp -- any eth0.2654 anywhere anywhere udp dpt:8983
0 0 ACCEPT tcp -- any eth0 anywhere anywhere tcp dpt:ssh
0 0 ACCEPT tcp -- any eth0.2654 anywhere anywhere tcp dpt:ssh
0 0 DROP all -- any eth0 anywhere anywhere owner UID match www-data
14 2061 DROP all -- any any anywhere anywhere
First disturbing element, I noticed that INPUT and OUTPUT first rules are ACCEPT all packets whereas I did not asked to do so. In addition, I tried to set policy of INPUT and OUTPUT to DROP (using $IPT -P INPUT DROP
and $IPT -P OUTPUT DROP
), but doing this definitively locked me out, even after the ten seconds timeout, and the server then only answers to ICMP, which force me to hard reboot the server. Same effect if I set policy settings at the beginning of the script.
I suspect my error to be obvious for regular iptables users, but I searched the solution for hours now, and, as always in this kind of situations, the answer will only be obvious to me when somebody will point it out. Please, any do-gooder to help me?
eth0.2654
is a VLAN used for communications with our PgSQL server. Concerning HTTP answers, I was under the impression that they use the connection the client opened, which is allowed by my rule. Was I wrong?