Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Here's my iptables script:

#!/bin/sh
service iptables stop
iptables -F
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT
service iptables save
service iptables restart

It works fine on Centos 6.3, but on Centos 6.0 I can't establish outbound HTTP connections. (I probably can't establish any outbound TCP/IP connections.) DNS lookup, however, works just fine, as does apparently anything else based on UDP.

I'm guessing this has something to do with TCP's three-way handshake, of which I know almost nothing. That being the case, there must be a difference in the versions of one of the modules where the earlier version requires explicit specification of INPUT rules to allow the handshake. So, what rule(s) would I need to create to allow the TCP handshake and therefore receive data?

share|improve this question
    
If you set the policy in OUTPUT to ACCEPT, everything should go unless explicitly filtered, what you aren't doing. The last line is completely redundant. And unless you let inbound traffic for ESTABLISHED conections through, no answer will ever come back. You allow inbound connections only to the ports for services, not to the random ports used by clients to connect to the outside. –  vonbrand Feb 27 '13 at 12:50
    
Ah yes, I forgot to remove that last rule when posting the question. I added it out of desperation and before I knew about the TCP handshake. –  Steve Taylor Feb 27 '13 at 12:59
1  
Will the down-voter please speak up? –  Steve Taylor Feb 27 '13 at 13:46

2 Answers 2

Your system will initiate connections from ephemeral ports.

Generally speaking, don't try and be smarter than netfilter's conntrack.

the first rule in any decent ruleset should be iptables -m conntrack --ctstate ESTABLISHED -j ACCEPT (only use -m state if your distro lacks -m conntrack) - doing this will enable your system initiate outbound connections and successfully receive the replies.

Additionally, to save resources, iptables -t raw -A PREROUTING -i lo -j CT --notrack (or -j NOTRACK) and iptables -t raw -A OUTPUT -o lo -j CT --notrack along with appropriate rules in the INPUT and OUTPUT chains to allow --ctstate UNTRACKED will save unnecessarily consuming conntrack resources on loopback connections.

share|improve this answer
    
This distro does indeed lack the conntrack module. I tried iptables -A -m state --state ESTABLISHED -j ACCEPT, but I still can't establish an outbound connection. –  Steve Taylor Feb 27 '13 at 13:31
    
paste your entire iptables-save –  Olipro Feb 27 '13 at 14:22
    
pastebin.com/WZ5d1LtH –  Steve Taylor Feb 27 '13 at 14:29

This works (see comments):

#!/bin/sh
service iptables stop
iptables -F

# Unlike the script in the question, incoming TCP packets are allowed in by default.
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

# Allow all loopback
iptables -A INPUT -i lo -j ACCEPT

# Allow incoming SSH, HTTP and HTTPS
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT

# Allow DNS responses
iptables -A INPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT

# This is new: Drop all incoming TCP packets with the SYN bit set.
iptables -A INPUT -p tcp --syn -m state --state NEW -j DROP

service iptables save
service iptables restart

I tested this quite thoroughly with netcat.

share|improve this answer
    
You shouldn't restrict the destinations of DNS responses. Also, DNS uses TCP when the query/response is too large (rarely happens, but Murphy will ensure it happens when most damaging). Also, dropping all TCP syn is an awkward way of saying "no TCP". And if so, why not also "no UDP"? Or even better just drop everyhing that hasn't been allowed (i.e., policy)? –  vonbrand Feb 27 '13 at 14:00
    
Why not use the firewall configuration tool that comes with your distribution, system-config-firewall? –  vonbrand Feb 27 '13 at 14:01
    
I appreciate the awkwardness of the rules, but at the moment it's the only answer here that works. I'd gladly accept a better one. Thanks for the tip regarding DNS over TCP. I'm trying to find out more about that now. If the TCP connection is established by the client (i.e. my server), then no change needs to be made to these rules. Also, the server I'm renting didn't come with system-config-firewall. This is the first I have heard of it anyway. –  Steve Taylor Feb 27 '13 at 14:16
    
Are you aware of an example domain that is guaranteed to make DNS use TCP? –  Steve Taylor Feb 27 '13 at 14:31
    
I'd believe that if you ask for all records for Google.com it will overflow UDP... nope, 435 bytes only (probably tailored so they fit). –  vonbrand Feb 27 '13 at 14:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.