iptables help with rules

Hi,

I've been struggling with this all morning and seem to have a blind spot on what the problem is. I'm trying to use iptables to block traffic on a little cluster of raspberry pi's but to allow ssh and ping traffic within it.

The cluster has a firewall server with a wifi card connecting to my home network and eth0 connection to a switch connecting the pi's within the cluster. All the other pi's just use the switch to talk to each on a network. They all use IP addresses in the range 10.10.1.2/5. The firewall pi uses 10.10.1.1 for eth0 and picks up a 192.168.1.122 address from my router on the wifi card.

I have this rule set that is currently preventing me from ssh'ing from the fwl to an internal pi on the cluster. I know that because if I clear the rules I can connect:

root@fwl:~# iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   70  5472 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh ctstate NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-request
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-reply
   59  8329 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
   40  3304 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp spt:ssh ctstate NEW,RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  any    lo      anywhere             anywhere
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:http state NEW
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:domain state NEW
    0     0 ACCEPT     udp  --  any    any     anywhere             anywhere             udp dpt:domain state NEW
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-reply
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-request
   14  1032 DROP       all  --  any    any     anywhere             anywhere

Here is the script I use to create the rules:

root@fwl:~# cat fwl.cfg
#!/bin/sh

# Flushing all rules
iptables -F
iptables -X

# Setting default filter policy
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

# Allow unlimited traffic on loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow ssh
iptables -I INPUT -p tcp  --dport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -I OUTPUT -p tcp --sport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT

iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT

# Setting default filter policy
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP

I'm no expert on firewalls but I've been reading a lot this morning about setting up ssh in iptables and think the idea is to allow what you want and then append a drop of everything else after those rules.

Most of the pages I've looked at suggest doing this at the start of the rules:

iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP

and then relaxing the rules for ssh and ping afterwards, but I couldn't get that to work either.

Like I said though, I can connect if I flush the rules out.

Can anyone suggest where I'm going wrong?

Thanks

Steady

Hi,

for debugging purposes I suggest you add some these logging rules

# Logging rules of what packages are dropped
iptables -A INPUT -j LOG
iptables -A OUTPUT -j LOG
iptables -A FORWARD -j LOG

Just before the Default-Drop-Rules

# Setting default filter policy 
iptables -A INPUT -j DROP 
iptables -A OUTPUT -j DROP 
iptables -A FORWARD -j DROP

You should find the messages of the drop rules somewhere within the /var/log directory - most likely in log file kern.log there.

As for a possible error I'm wondering if state NEW for dns is sufficient. I would add ESTABLISHED to.

What I'm wondering too ist that you use 2 different methods to define your state. You use conntrack/cstate for ssh and state for dns/http. I suggest to use the state method for ssh too. (Never used conntrack with this).

2 Likes

Thanks, stomp,

That logging tip is really useful. Looks like I'm sending a SYN but not allowing a SYN-ACK if I'm understanding it correctly:

Dec 31 22:39:44 fwl kernel: [ 5336.614582] IN= OUT=eth0 SRC=10.10.1.1 DST=10.10.1.2 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=48912 DF PROTO=TCP SPT=45562 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0
Dec 31 22:39:52 fwl kernel: [ 5344.634727] IN= OUT=eth0 SRC=10.10.1.1 DST=10.10.1.2 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=48913 DF PROTO=TCP SPT=45562 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0
Dec 31 22:40:08 fwl kernel: [ 5360.654968] IN= OUT=eth0 SRC=10.10.1.1 DST=10.10.1.2 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=48914 DF PROTO=TCP SPT=45562 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0

---------- Post updated at 04:05 PM ---------- Previous update was at 03:22 PM ----------

So my current set of rules is created like so:

root@fwl:~# cat fwl.cfg
#!/bin/sh

# Flushing all rules
#iptables -F
#iptables -X

# Logging rules
iptables -A INPUT -j LOG
iptables -A OUTPUT -j LOG
#iptables -A FORWARD -j LOG

# Setting default filter policy
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# Allow unlimited traffic on loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow ssh
iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT  -p tcp  --dport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT

#iptables -A INPUT  -p tcp  --dport 22  -j ACCEPT
#iptables -A OUTPUT -p tcp  --sport 22  -j ACCEPT

iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT

#iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
#iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow ping
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT

When trying to make a connection from the fwl pi into one of the others I see a SYN go out but nothing back in my post of the log as shown above.

For the life of name I can't understand why or how to progress with investigating, so all suggestions welcome folks.

Look at my other two advices above. The solution will most likely to change that conntrack thingy.

I've tried

iptables -A INPUT  -p tcp  --dport 22  -j ACCEPT
iptables -A OUTPUT -p tcp  --sport 22  -j ACCEPT

But that makes no difference. It seems to be the port that is causing the issue as this works fine:

iptables -A INPUT  -p tcp  -j ACCEPT
iptables -A OUTPUT -p tcp  -j ACCEPT

Combined, these allow me to log in via the wlan0 interface and go onto the inner pi's via eth0:

# Allow ssh
iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT  -p tcp  --dport 22 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp  -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp  -j ACCEPT

But I can't define port 22 on the eth0 interface without it failing... Weird! I wonder if it could be related to my interfaces file:

root@fwl:~# cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback
auto eth0

iface eth0 inet static
    address 10.10.1.1
    netmask 255.255.255.0
    network 10.10.1.0

allow-hotplug wlan0
iface wlan0 inet dhcp
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf