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.

I've been struggling with a FORWARD policy that isn't working the way I'd like, and I can't figure out what is causing the session to fail. I hope someone can help.

My goal is to forward port 3000 from eth0 to an internal Windows machine port 3389 out eth2, so I can RDP into the Windows box. The below configuration script only works with iptables -P FORWARD ACCEPT, however I do not want that. I feel better having iptables -P FORWARD DROP, but this isn't working for me.

Here is the last version of the script I've been working with. Note that this is the entire script with all my commented stuff included, so you can check everything that's happening here, but keep in mind it's the FORWARD part I need help with.


echo "Flush firewall and setting default chain policies..."
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
#iptables --append FORWARD -p tcp --dport 3000 -d 192.168.1.2 -j ACCEPT

echo "Enabling firewall with new ruleset..."
# allow ssh to eth0
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

# allow http-https traffic
iptables -A INPUT -i eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT

# allow ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -t raw -A OUTPUT -p icmp -j TRACE

# full loopback access
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# minimize http-https DOS attack by limiting burst connections
# may need to adjust this later once web traffic is coming in
iptables -A INPUT -p tcp --dport 80 -m limit --limit 10/minute --limit-burst 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m limit --limit 10/minute --limit-burst 20 -j ACCEPT

# all rdp 3000 to jump box
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 3000 -j LOG --log-prefix "iptables-prerouting: " --log-level 7
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 3000 -j DNAT --to 192.168.1.2:3389
#iptables -A FORWARD -i eth0 -p tcp --dport 3389 -d 192.168.1.2 -j ACCEPT
#iptables -t raw -A PREROUTING -p tcp --dport 3389 -j TRACE
#iptables -t raw -A OUTPUT -p tcp --dport 3389 -j TRACE
iptables -A FORWARD -t filter -o eth0 -m state --state NEW,ESTABLISHED -d 192.168.1.2 -p tcp --dport 3389 -j LOG --log-prefix "iptables-forward: " --log-level 7
iptables -A FORWARD -t filter -o eth0 -m state --state NEW,ESTABLISHED -d 192.168.1.2 -p tcp --dport 3389 -j ACCEPT

# nat internal network to public interface
iptables -A POSTROUTING -o eth0 -t nat -j LOG --log-prefix "iptables-postrouting: " --log-level 7
iptables -A POSTROUTING -o eth0 -t nat -j MASQUERADE

# logging
#iptables -A INPUT -m limit --limit 2/min -j LOG --log-prefix "iptables-input: " --log-level 7
iptables -A FORWARD -j LOG --log-prefix "iptables-forward: " --log-level 7
#iptables -A OUTPUT -j LOG --log-prefix "iptables-output: " --log-level 7

# enable ipv4 forwardning for the system
echo 1 > /proc/sys/net/ipv4/ip_forward

# add route for private network internet access
ip route add 192.168.1.0/24 proto kernel scope link dev eth2

#List iptables ruleset
echo "-----------------------------------------------------------------------------"
echo "Listing iptables..."
iptables -L

echo "-----------------------------------------------------------------------------"
echo "Listing ip routes..."
ip route


I've traced the connections, enabled logging rules, etc, but am unable to determine what the issue is based on the information provided. I can spot differences in the traces between iptables -P FORWARD default actions, but still not finding the needle in the hay stack.

I'd appreciate any pointers I can get. Thanks!

Thanks for @HaukeLaging, I've got this working fine. Here is the final script.



echo "Flush firewall and setting default chain policies..."
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
iptables --append INPUT -t filter -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables --append FORWARD -t filter -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables --append OUTPUT -t filter -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

echo "Enabling firewall with new ruleset..."
# allow ssh to eth0
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# allow http-https traffic
iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
# ----from private network
iptables -A FORWARD -i eth2 -o eth0 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -i eth2 -o eth0 -p tcp --dport 443 -j ACCEPT

# allow ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
# ----from private network
iptables -A FORWARD -i eth2 -o eth0 -p icmp --icmp-type echo-request -j ACCEPT

# full loopback access
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# minimize http-https DOS attack by limiting burst connections
# may need to adjust this later once web traffic is coming in
iptables -A INPUT -p tcp --dport 80 -m limit --limit 10/minute --limit-burst 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m limit --limit 10/minute --limit-burst 20 -j ACCEPT

# rdp 3000 to jump box
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 3000 -j DNAT --to 192.168.1.2:3389
iptables -A FORWARD -i eth0 -p tcp --dport 3389 -d 192.168.1.2 -j ACCEPT

# nat on public interface
iptables -A POSTROUTING -o eth0 -t nat -j MASQUERADE

# logging
#iptables -A INPUT -m limit --limit 2/min -j LOG --log-prefix "iptables-input: " --log-level 7
#iptables -A FORWARD -j LOG --log-prefix "iptables-forward: " --log-level 7
#iptables -A OUTPUT -j LOG --log-prefix "iptables-output: " --log-level 7

# enable ipv4 forwardning for the system
echo 1 > /proc/sys/net/ipv4/ip_forward

# add route for private > public access
ip route add 192.168.1.0/24 proto kernel scope link dev eth2

#List iptables ruleset
echo "-----------------------------------------------------------------------------"
echo "Listing iptables..."
iptables -L

echo "-----------------------------------------------------------------------------"
echo "Listing ip routes..."
ip route

share|improve this question
    
A general recommendation: Always provide the output of ip addr when you want networking problems solved. –  Hauke Laging May 21 '13 at 17:41

1 Answer 1

up vote 1 down vote accepted

You have to activate your commented out rule

iptables -A FORWARD -i eth0 -p tcp --dport 3389 -d 192.168.1.2 -j ACCEPT

And you have to correct this one (and the logging rule above, of course):

iptables -A FORWARD -t filter -o eth0 -m state --state NEW,ESTABLISHED -d 192.168.1.2 -p tcp --dport 3389 -j ACCEPT

That is wrong. If eth0 is the output interface then 192.168.1.2 is the source and not the destination. But why allow state NEW? The easiest would be:

iptables -A FORWARD -t filter -m state --state ESTABLISHED,RELATED -j ACCEPT

That's a common rule. If you want to keep closer to your connection definition:

iptables -A FORWARD -t filter -o eth0 -m state --state ESTABLISHED -s 192.168.1.2 -p tcp --sport 3389 -j ACCEPT

Edit 1:

And you may need a rule that allows all(?) connections originating from the other system:

iptables -A FORWARD -t filter -o eth0 -m state --state NEW -s 192.168.1.2 -j ACCEPT

BTW, quoting the man page:

The "state" module is an obsolete version of "conntrack".

If you don't use the short rule to allow all established traffic then you also need something like this:

iptables -A FORWARD -t filter -i eth0 -m conntrack --ctstate ESTABLISHED -d 192.168.1.2 -j ACCEPT
share|improve this answer
    
I should have asked this question a lot sooner. Thanks for your help! –  Jonathan Almquist May 21 '13 at 17:55
    
I've lost the ability to reach the internet (http/https) from the Windows machine I am connected to. This did work with my original configuration script, with iptables -P FORWARD ACCEPT. Any clue as to why this isn't working now? –  Jonathan Almquist May 21 '13 at 18:20
    
I think I figured it out. iptables -A FORWARD -i eth2 -o eth0 -p tcp --dport 80 -j ACCEPT –  Jonathan Almquist May 21 '13 at 18:27
    
@JonathanAlmquist See my edit. –  Hauke Laging May 21 '13 at 18:29
    
Thanks. I used your uptaded conntrack. Just needed to edit like so iptables -A FORWARD -t filter -o eth0 -m conntrack --ctstate ESTABLISHED -s 192.168.1.2 -j ACCEPT –  Jonathan Almquist May 21 '13 at 18:41

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.