# [solved] Iptables - how do you understand them?

## dalu

I'm serious  :Smile: 

I have a concrete problem, but as you know "give a man a fish, feed him for 1 day, teach a man to fish, feed him a lifetime"

The concrete problem is:

1 NIC

2 IPv4 IPs

- 1 public

- 1 private

a /64 IPv6 prefix

libreswan on the private IP

So let's say public IP is 5.5.5.5

and private IP is 10.0.0.1

I'd like to

- Allow from any on port 22, 25, 80, 443 TCP to 5.5.5.5

- Allow all from 10.0.0.2 and 10.0.0.3 to 10.0.0.1

- Allow from 6.6.6.6 and 7.7.7.7 to 5.5.5.5 on port 1500 and 4500 TCP and UDP

- Allow from 10.0.0.1 10.0.0.2 10.0.0.3 to 127.0.0.1

- Allow all outgoing (or better solution)

- Deny everything else

How do you even start with this?Last edited by dalu on Mon Sep 28, 2015 8:00 am; edited 1 time in total

----------

## Hu

I would do it all from memory, but for people who have not memorized the iptables manpage, starting there would be a good bet.

In iptables, rules are tested in order.  If a rule matches and has a terminating target, then processing stops and that target is the result.  Allowing traffic is done by the ACCEPT target.  Denying traffic is done by the DROP target.  You can set a policy to establish a default for packets which traverse the entire rule list without matching a terminating rule.  Traffic from the machine to itself is special and is handled over the interface lo, regardless of the IPs that would be in the packet headers for that traffic.  Use the table filter for accept/drop rules.  Use the filter chain INPUT for traffic arriving from the network and destined to your machine.  Use the filter table FORWARD for traffic traversing your machine, which neither originated from you nor is destined to you.  Use the filter table OUTPUT for traffic originating from your machine.

I could write the rules you need, but since you said you want to learn, that seems like it would spoil your process.  With what I have written so far, and the help of man iptables, can you write the rules you need or do you want more help?

----------

## szatox

 *Quote:*   

> I have a concrete problem

 good it's not a concrete boots (+10 diving, -5 swimming)

 *Quote:*   

> but as you know "give a man a fish, feed him for 1 day 

 give a man a poisonous fish, feed him a lifetime

Ok, jokes aside now.

First things to know about iptables is that it's a set of rules.

Every packet seen  by kernel is being matched against those rules, and the first matching rule wins.

"Policy" is just another name for "Default"

Second thing to know is that those rules are organized into chains.

When you send something it's being matched against rules in "OUTPUT". Incoming stuff is being matched against "INPUT".

Packets on loopback will match BOTH those chains in the order above. (you send it first, and THEN you receive it)

So, let's start at the end with table filter:

 *Quote:*   

> Deny everything else

 

iptables -P INPUT  -j DROP # set policy (aka default) to drop all incoming traffic

Then, you want to keep loopback active:

iptables -A INPUT -i lo -j ACCEPT # accept everything incoming via interface lo

 *Quote:*   

> Allow from 10.0.0.1 10.0.0.2 10.0.0.3 to 127.0.0.1

  this is not going to happen.I mean, sure, you  can set this rule, but nothing would ever match it.

 *Quote:*   

> - Allow from 6.6.6.6 and 7.7.7.7 to 5.5.5.5 on port 1500 and 4500 TCP and UDP 

 

iptables -A FORWARD -s 6.6.6.6  -d 5.5.5.5 --dport 1500,4500 -j ACCEPT

The list goes on... You will definitely need this one too:

iptables -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED # it may or may not be a good idea to replace state with conntrack. Either way it will let you receive answers to whatever you send.

The above is enough to get started. Either way setting firewall is something you typically do once and forget. You can always check options in manual, writing rules doesn't really have much to do with understanding how it works.

----------

## dalu

```

-A INPUT -p tcp -m tcp  -d 5.5.5.5 --dport 80   -j ACCEPT

-A INPUT -p tcp -m tcp  -d 5.5.5.5 --dport 443   -j ACCEPT

-A INPUT -p tcp -m tcp  -d 5.5.5.5 --dport 25   -j ACCEPT

-A INPUT -p tcp -m tcp  -d 5.5.5.5 --dport 22122 -j ACCEPT

```

this is for the 1st part, accept inbound to various ports

szatox, why do you have FORWARD there, shouldn't it be INPUT?

----------

## dalu

Ok I tried fwbuilder but this here locks me out of my server  :Wink: 

my sshd is listening on port 22022

EDIT: correction, the script locks me out because it's reconfiguring interfaces, but those rules seem to work

```

    # ================ Table 'filter', automatic rules

    # accept established sessions

    $IPTABLES -A INPUT   -m state --state ESTABLISHED,RELATED -j ACCEPT 

    $IPTABLES -A OUTPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT 

    $IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

    # ================ Table 'filter', rule set Policy

    # 

    # Rule 0 (global)

    # 

    echo "Rule 0 (global)"

    # 

    $IPTABLES -A INPUT  -s 10.0.1.1   -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT  -s 6.6.6.6   -m state --state NEW  -j ACCEPT

    # 

    # Rule 1 (global)

    # 

    echo "Rule 1 (global)"

    # 

    $IPTABLES -A INPUT  -s 10.0.1.2   -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT  -s 7.7.7.7   -m state --state NEW  -j ACCEPT

    # 

    # Rule 2 (global)

    # 

    echo "Rule 2 (global)"

    # 

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 80  -d 5.5.5.5   --dport 80  -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 443  -d 5.5.5.5   --dport 443  -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 143  -d 5.5.5.5   --dport 143  -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 993  -d 5.5.5.5   --dport 993  -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 25  -d 5.5.5.5   --dport 25  -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 465  -d 5.5.5.5   --dport 465  -m state --state NEW  -j ACCEPT

    $IPTABLES -A INPUT -p tcp -m tcp  --sport 22022  -d 5.5.5.5   --dport 22022  -m state --state NEW  -j ACCEPT

    # 

    # Rule 3 (global)

    # 

    echo "Rule 3 (global)"

    # 

    $IPTABLES -A OUTPUT  -s 5.5.5.5   -m state --state NEW  -j ACCEPT

    # 

    # Rule 4 (global)

    # 

    echo "Rule 4 (global)"

    # 

    $IPTABLES -N Cid7324X3090.0

    $IPTABLES -A OUTPUT  -s 10.0.1.3   -m state --state NEW  -j Cid7324X3090.0

    $IPTABLES -A Cid7324X3090.0  -d 10.0.1.1   -j ACCEPT

    $IPTABLES -A Cid7324X3090.0  -d 10.0.1.2   -j ACCEPT

    # 

    # Rule 5 (global)

    # 

    echo "Rule 5 (global)"

    # 

    $IPTABLES -A INPUT  -d 5.5.5.5   -j DROP

}

```

----------

## gordonb3

Solved?

That listing looks like rubbish. Example: to connect to port 80 on your server it requires the request to come from port 80 as well, which typically never happens. The content of "Rule 4" is even utter nonsense because 10.0.1.3 is not a local address to your server. I'm also a bit puzzled about your physical setup which seems to indicate that you have two additional devices using RFC1918 addresses while being directly connected to the internet. You'd be better off adding a second NIC to this machine and let it act as router-firewall to the other two devices.

Below rules will match your original request

```

# This is okay, so keep it

    $IPTABLES -A INPUT   -m state --state ESTABLISHED,RELATED -j ACCEPT

    $IPTABLES -A OUTPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT

    $IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# Don't restrict localnet

    $IPTABLES -A INPUT -i lo -j ACCEPT

# standard bookkeeping - create separate chains for easy adding/deleting rules to the correct group of IPs

    $IPTABLES -N Private_in

    $IPTABLES -A INPUT -s 10.0.0.0/24 -d 10.0.0.1 -j Private_in

    $IPTABLES -N Public_in

    $IPTABLES -A INPUT -d 5.5.5.5 -j Public_in

# Rules for local net - does this even require restrictions?

    $IPTABLES -A Private_in -s 10.0.0.2 -j ACCEPT

    $IPTABLES -A Private_in -s 10.0.0.3 -j ACCEPT

    $IPTABLES -A Private_in -j REJECT

# Rules for external access

    $IPTABLES -A Public_in -p tcp -m multiport --dports 80,443,143,993,25,465,22022 -j ACCEPT

    $IPTABLES -A Public_in -p tcp -m multiport --dports 1500,4500 -s 6.6.6.6 -j ACCEPT

    $IPTABLES -A Public_in -p udp -m multiport --dports 1500,4500 -s 6.6.6.6 -j ACCEPT

    $IPTABLES -A Public_in -p tcp -m multiport --dports 1500,4500 -s 7.7.7.7 -j ACCEPT

    $IPTABLES -A Public_in -p udp -m multiport --dports 1500,4500 -s 7.7.7.7 -j ACCEPT

    $IPTABLES -A Public_in -j DROP

# Closing rule

    $IPTABLES -A INPUT -j DROP

# or (and)

    $IPTABLES -P INPUT DROP

```

----------

## dalu

sigh.. I hate PHP's session timeout

well here's the short version of my reply

```

#/bin/bash

IPTABLES=/sbin/iptables

$IPTABLES -A INPUT   -m state --state ESTABLISHED,RELATED -j ACCEPT 

$IPTABLES -A OUTPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT 

$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A INPUT -i lo -j ACCEPT 

$IPTABLES -N PUB_IN

$IPTABLES -A INPUT -d 5.5.5.5 -j PUB_IN

$IPTABLES -A PUB_IN  -s 6.6.6.6   -m state --state NEW  -j ACCEPT

$IPTABLES -A PUB_IN  -s 7.7.7.7   -m state --state NEW  -j ACCEPT

$IPTABLES -A PUB_IN -p tcp -m multiport --dports 25,80,143,443,465,993,22022 -j ACCEPT

$IPTABLES -A PUB_IN -j DROP 

$IPTABLES -N PRI_IN

$IPTABLES -A INPUT -d 10.0.1.1 -j PRI_IN

$IPTABLES -A PRI_IN -s 10.0.1.2   -m state --state NEW  -j ACCEPT

$IPTABLES -A PRI_IN -s 10.0.1.3   -m state --state NEW  -j ACCEPT

$IPTABLES -A PRI_IN -j REJECT 

$IPTABLES -A OUTPUT  -s 5.5.5.5   -m state --state NEW  -j ACCEPT

$IPTABLES -A INPUT -j DROP 

$IPTABLES -P INPUT DROP

```

----------

