Recently, I decided to DROP packets that want to go out through the port 80. It seams my configuration has a problem, because some unwanted packets are dropped.
Excerpt of my configuration:
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp -s [PUBLIC IP OF MY SERVER] --sport 80 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT
Question 1: isn't the second rule useless, since I already said in the first one that I accept all packets with "ESTABLISHED" state?
Question 2: Why aren't these two rules enough to accept the following dropped packets:
Jul 14 18:47:18 [HOSTNAME] kernel: iptables output: IN= OUT=eth0 SRC=[PUBLIC IP OF MY SERVER] DST=[A WWW CLIENT PUBLIC IP] LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=8408 DF PROTO=TCP SPT=80 DPT=50085 WINDOW=123 RES=0x00 ACK FIN URGP=0
Jul 14 18:47:53 [HOSTNAME] kernel: iptables output: IN= OUT=eth0 SRC=[PUBLIC IP OF MY SERVER] DST=[A WWW CLIENT PUBLIC IP] LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=8409 DF PROTO=TCP SPT=80 DPT=50085 WINDOW=123 RES=0x00 ACK FIN URGP=0
Jul 14 18:48:08 [HOSTNAME] kernel: iptables output: IN= OUT=eth0 SRC=[PUBLIC IP OF MY SERVER] DST=[A WWW CLIENT PUBLIC IP] LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=54091 DF PROTO=TCP SPT=80 DPT=25780 WINDOW=16616 RES=0x00 ACK FIN URGP=0
N.B:
- There is no rule above those in the chain that drops packets.
- The default policy is DROP.
EDIT I looked at this post, and also enabled logging of INVALID packets by the kernel:
echo 255 >/proc/sys/net/netfilter/nf_conntrack_log_invalid
Now it seams I have several kinds of errors:
Jul 14 22:00:40 [HOSTNAME] kernel: nf_ct_tcp: invalid RST IN= OUT= SRC=[ONE_CLIENT_IP] DST=[SERVER_IP] LEN=40 TOS=0x00 PREC=0x00 TTL=49 ID=47149 PROTO=TCP SPT=993 DPT=51364 SEQ=1043042446 ACK=0 WINDOW=0 RES=0x00 RST URGP=0
Jul 14 21:57:11 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state ESTABLISHED IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=3782 SEQ=474588492 ACK=2243291425 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
Jul 14 21:57:25 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state LAST_ACK IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=3782 SEQ=474588492 ACK=2243291425 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
Jul 14 21:57:41 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state TIME_WAIT IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=3782 SEQ=474588492 ACK=2243291425 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
Jul 14 21:58:52 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state SYN_RECV IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=50488 SEQ=3804975135 ACK=229029122 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
(actually I made this answer elsewhere, I thought it was the same site)
according to these:
http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
http://www.iptables.info/en/connection-state.html (not up to date)
It might be possible the (maybe mobile) client closed first, didn't wait for the final FIN/ACK and never sent its very final ACK, or perhaps the server answered too late and the client itself is firewalled or any other slow response case... So the server retries, beyond a timer (
sysctl net.netfilter.nf_conntrack_tcp_timeout_last_ack
) but the netfilter has dropped the state before the real tcp stack drops it.you should take traces and see if you have duplicates packets for example.
The 2nd rule is a subset of the first rule, so it is useless. Try increasing values of various tcp_timeout settings (
sysctl -w net.netfilter....
orecho XX > /proc/sys/net/netfilter/...
) and see if those logs disappear. I set this for similar reasons in the past and it "solved" some mysterious netfilter logs. This might increase conntrack memory usage.1) Second one seems to be useless if you have first one.
2) Now. Why would you have DROP by default on OUTPUT at all? You do not trust yourself? I would leave it ACCEPT by default. Just have your rules applied to INPUT chain with DROP by default. With proper rules in INPUT chain and DROP by default iptables will do great job on securing your server. Creating such policies for OUTPUT seems to be too much if you are not doing very special security set up.
Before the three-way TCP handshake is complete, the connection won't be "established" yet. The handshake requires that the client send a
SYN
packet, you return aSYN+ACK
packet, and the client then return anACK
packet. However, you are going to block theSYN+ACK
outgoing packet.A better thing to do would be to allow all packets in
OUTPUT
which match-p tcp --sport 80 --dport 1024:65535
. You could also limit the lower bound further; IANA recommends ports 41952 and above be used for random source ports, but as you may notice many clients are not compliant. A rule like this will allow any traffic that is a response to a port 80 connection where the port on the client is not a privileged port (and will prevent malware from calling home on 80 or 443).If you prefer to use connection states for your rules, you could also allow outgoing packets on source port 80 with states
ESTABLISHED,RELATED,SYN_RECV
(in your configuration, you can just useSYN_RECV
because the first rule will take care of it). This will allow the outgoingSYN+ACK
to set up the outgoing connection.The invalid packets seem to relate to the fact that they are
SYN+ACK
packets, but the connection isn't waiting to be established. Likely this is an artifact unrelated to the problem and nothing to worry about.