# securing a server with iptables [SOLVED]

## BlinkEye

it all started here: https://forums.gentoo.org/viewtopic.php?p=1151158#1151158

now i got my server up and running (dhcp, apache, apache ssl, tomcat, mailserver (imap), webmail, mysql). 

9ust00 provided me with the following firewall script:

```
#!/bin/bash 

 

 IPTABLES="/sbin/iptables" 

 

 EXT_NIC="eth1" 

 INT_NIC="eth0" 

 INT_IP="10.10.10.0/255.255.255.0" 

                                                                                                                                                                           

 echo "starting firewall..." 

                                                                                                                                                                           

     ###  set default rules (DENY, ACCEPT)  ### 

     ${IPTABLES} -P INPUT DROP 

     ${IPTABLES} -P FORWARD ACCEPT 

     ${IPTABLES} -P OUTPUT ACCEPT 

                                                                                                                                                                           

     ###  allow all incoming packets from internal net  ### 

     ${IPTABLES} -A INPUT -i ! ${EXT_NIC} -j ACCEPT 

     ###  allow incoming realated packets on external NIC  ### 

     ${IPTABLES} -A INPUT -i ${EXT_NIC} -m state --state ESTABLISHED,RELATED -j ACCEPT 

                                                                                                                                                                           

     ###  enables masquerading of internal hosts  ### 

     echo "* enabling ip forwarding in kernel" 

     echo 1 > /proc/sys/net/ipv4/ip_forward 

                                                                                                                                                                           

     echo "* enabling masquerading of internal hosts" 

     ${IPTABLES} -t nat -P PREROUTING ACCEPT 

     ${IPTABLES} -t nat -P POSTROUTING ACCEPT 

     ${IPTABLES} -t nat -P OUTPUT ACCEPT 

     ${IPTABLES} -t nat -A POSTROUTING -o ${EXT_NIC} -j MASQUERADE 
```

as i'm now running several services (i.e. apache, tomcat, ssh, imap) which should be available from the outside i have to adjust "my" script (i can't drop all input anymore).

adaptr provided me the following rules:

```
iptables -A INPUT -i ${EXT_NIC} -p tcp -d ${EXT_IP} --dport 22 -j ACCEPT 

 iptables -A INPUT -i ${EXT_NIC} -p tcp -d ${EXT_IP} --dport 80 -j ACCEPT 

 iptables -A INPUT -i ${EXT_NIC} -m state --state ESTABLISHED,RELATED -j ACCEPT
```

to open port 22 and 80. i'll add some more but this isn't the issue. the problem is, that i get errors when executing these rules. 

to open some ports i hence added these two lines to my firewall script which looks now like that:

```
 #!/bin/bash

 IPTABLES="/sbin/iptables"

#EXT_NIC="eth1"

 EXT_NIC="ppp0"

 INT_NIC="eth0"

 INT_IP="10.10.10.0/255.255.255.0"

 echo "starting firewall..."

     ###  set default rules (DENY, ACCEPT)  ###

     ${IPTABLES} -P INPUT DROP

     ${IPTABLES} -P FORWARD ACCEPT

     ${IPTABLES} -P OUTPUT ACCEPT

     ###  allow all incoming packets from internal net  ###

     ${IPTABLES} -A INPUT -i ! ${EXT_NIC} -j ACCEPT

     ###  allow incoming realated packets on external NIC  ###

     ${IPTABLES} -A INPUT -i ${EXT_NIC} -m state --state ESTABLISHED,RELATED -j ACCEPT

     ###  enables masquerading of internal hosts  ###

     echo "* enabling ip forwarding in kernel"

     echo 1 > /proc/sys/net/ipv4/ip_forward

     echo "* enabling masquerading of internal hosts"

     ${IPTABLES} -t nat -P PREROUTING ACCEPT

     ${IPTABLES} -t nat -P POSTROUTING ACCEPT

     ${IPTABLES} -t nat -P OUTPUT ACCEPT

     ${IPTABLES} -t nat -A POSTROUTING -o ${EXT_NIC} -j MASQUERADE

iptables -A INPUT -i ${EXT_NIC} -p tcp -d ${EXT_IP} --destination-port 22 -j ACCEPT

iptables -A INPUT -i ${EXT_NIC} -p tcp -d ${EXT_IP} --destination-port 80 -j ACCEPT

```

if executed i get these errors:

```
# start_routing_bridge_secure

starting firewall...

Bad argument `22'

Try `iptables -h' or 'iptables --help' for more information.

Bad argument `80'

Try `iptables -h' or 'iptables --help' for more information.

* enabling ip forwarding in kernel

* enabling masquerading of internal hosts

Bad argument `22'

Try `iptables -h' or 'iptables --help' for more information.

Bad argument `80'

Try `iptables -h' or 'iptables --help' for more information.
```

i've changed the iptables options from built in to modules, here's my current list of loaded modules:

```
# lsmod

Module                  Size  Used by

ipt_MASQUERADE          3968  1

iptable_nat            24748  2 ipt_MASQUERADE

ipt_state               2176  1

iptable_filter          3072  1

ip_tables              17536  4 ipt_MASQUERADE,iptable_nat,ipt_state,iptable_filter

ppp_synctty             9472  0

ppp_async              12160  1

ppp_generic            29460  6 ppp_synctty,ppp_async

slhc                    8192  1 ppp_generic

uhci_hcd               31388  0

ehci_hcd               27400  0

ohci_hcd               19996  0

usbcore               106548  5 uhci_hcd,ehci_hcd,ohci_hcd

```

these are my available modules:

```
# ls /lib/modules/2.6.5-mm6/kernel/net/ipv4/netfilter/

arp_tables.ko           ip_tables.ko       ipt_ULOG.ko       ipt_owner.ko

arpt_mangle.ko          ipt_CLASSIFY.ko    ipt_ah.ko         ipt_pkttype.ko

arptable_filter.ko      ipt_DSCP.ko        ipt_conntrack.ko  ipt_recent.ko

ip_conntrack_amanda.ko  ipt_ECN.ko         ipt_dscp.ko       ipt_state.ko

ip_conntrack_ftp.ko     ipt_LOG.ko         ipt_ecn.ko        ipt_tcpmss.ko

ip_conntrack_irc.ko     ipt_MARK.ko        ipt_esp.ko        ipt_tos.ko

ip_conntrack_tftp.ko    ipt_MASQUERADE.ko  ipt_helper.ko     ipt_ttl.ko

ip_nat_amanda.ko        ipt_NETMAP.ko      ipt_iprange.ko    iptable_filter.ko

ip_nat_ftp.ko           ipt_REDIRECT.ko    ipt_length.ko     iptable_mangle.ko

ip_nat_irc.ko           ipt_REJECT.ko      ipt_limit.ko      iptable_nat.ko

ip_nat_snmp_basic.ko    ipt_SAME.ko        ipt_mac.ko

ip_nat_tftp.ko          ipt_TCPMSS.ko      ipt_mark.ko

ip_queue.ko             ipt_TOS.ko         ipt_multiport.ko
```

what am i missing or what am i doing wrong? any help is truly appreciated as i don't want to run my server with 

```
${IPTABLES} -P INPUT ACCEPT
```

----------

## zerb

possible that you haven't set ${EXT_IP} in your script?

----------

## BlinkEye

absolutely. this was the problem! thanks a lot. 

any suggestion on how i should do this with dynamic ip's? it works if i put in my current ip but i can't to that all the time my ip changes 

 :Wink: 

----------

## adaptr

Well - if you use either dhcpcd or a dyndns client you can execute a script when your IP changes and modify the firewall rules that contain your $EXT_IP.

Google for it, or search the forums.

----------

## BlinkEye

 *adaptr wrote:*   

> Well - if you use either dhcpcd or a dyndns client you can execute a script when your IP changes and modify the firewall rules that contain your $EXT_IP.
> 
> Google for it, or search the forums.

 

as i know now that i have to do it that way i google for it and/or search the forums (probably the latter first - this forum is so great i'm forgetting google...).

thanks a lot for any help, this firewall rocks!

----------

## BlinkEye

the problem is that i connect my server via pppoe. iptables doesn't accept anything like

```
iptables -A INPUT -i ${EXT_NIC} -p tcp -d $EXT_NIC --destination-port 22 -j ACCEPT

iptables -A INPUT -i ${EXT_NIC} -p tcp -d $EXT_NIC --destination-port 80 -j ACCEPT

iptables -A INPUT -i ${EXT_NIC} -p tcp -d $EXT_NIC --destination-port 443 -j ACCEPT

iptables -A INPUT -i ${EXT_NIC} -p tcp -d $EXT_NIC --destination-port 8080 -j ACCEPT
```

with EXT_NIC="ppp0"

----------

## DaveArb

 *BlinkEye wrote:*   

> the problem is that i connect my server via pppoe. iptables doesn't accept anything like
> 
> ```
> iptables -A INPUT -i ${EXT_NIC} -p tcp -d $EXT_NIC --destination-port 22 -j ACCEPT
> ```
> ...

 

The "-d" option takes an address, not a port device.

Dave

----------

## BlinkEye

yes, exactly. i'm on my way to understand iptables. thanks for this last but not least hint!

so, my script finally looks like that, everything's working now:

```
#!/bin/bash 

IPTABLES="/sbin/iptables" 

EXT_NIC="ppp0"

INT_NIC="eth0" 

INT_IP="10.10.10.0/255.255.255.0" 

                                                 

echo "starting firewall..." 

   # flush rules and delete chains 

   $IPTABLES -F 

   $IPTABLES -X 

   

   ###  set default rules (DENY, ACCEPT)  ### 

   ${IPTABLES} -P INPUT DROP

   ${IPTABLES} -P FORWARD ACCEPT 

   ${IPTABLES} -P OUTPUT ACCEPT 

   

   ###  allow all incoming packets from internal net  ### 

   ${IPTABLES} -A INPUT -i ! ${EXT_NIC} -j ACCEPT 

   ###  allow incoming realated packets on external NIC  ### 

   iptables -A INPUT -i ${EXT_NIC} -m state --state ESTABLISHED,RELATED -j ACCEPT 

   

   ###  enables masquerading of internal hosts  ### 

   echo "* enabling ip forwarding in kernel" 

   echo 1 > /proc/sys/net/ipv4/ip_forward 

   

   echo "* enabling masquerading of internal hosts" 

   # enable masquerading to allow LAN internet access     

   ${IPTABLES} -t nat -A POSTROUTING -o ${EXT_NIC} -j MASQUERADE 

   

   ${IPTABLES} -t nat -P PREROUTING ACCEPT 

   ${IPTABLES} -t nat -P POSTROUTING ACCEPT 

   ${IPTABLES} -t nat -P OUTPUT ACCEPT

   

   # open ports  to the outside

   echo "* open ports to the outside" 

   iptables -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 22 -j ACCEPT 

   iptables -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 80 -j ACCEPT  

   iptables -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 443 -j ACCEPT 

   iptables -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 8080 -j ACCEPT 

   #iptables -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 143 -j ACCEPT 

   iptables -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 993 -j ACCEPT 

      

   # block out all other Internet access on $EXT_NIC

   $IPTABLES -A INPUT -i $EXT_NIC -m state --state NEW,INVALID -j DROP 

   $IPTABLES -A FORWARD -i $EXT_NIC -m state --state NEW,INVALID -j DROP

```

----------

## adaptr

Excellent - except that those last two rules are rather useless.

If you want to drop everything by default then you set a chain's policy to drop - that's what the policy is for.

In your input chain, this is already the case - so the last input rule is superfluous anyway.

Just set the forward policy to drop as well, and drop (haha) the last two rules.

----------

## BlinkEye

your right. thanks for the hint

----------

## pharaoh

used this post to get my home router/server working...thanks!!   :Very Happy: 

----------

## BlinkEye

in case someone runs in the same problem as i did: if you want to run a ftp server you'll have to add one more line (altough i don't see the difference between a ssh and a ftp connection):

```
${IPTABLES} -A INPUT  -i ${EXT_NIC}  -m state --state NEW  -j ACCEPT
```

i don't see why it doesn't work with this setting:

```
echo "* enable incoming new connection on port 21"

${IPTABLES} -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 21 -m state --state NEW -j ACCEPT
```

i'm not at all satisfied with this solution. somebody may explain this behaviour?

----------

## BlinkEye

just for the record:

```
echo "* enable incoming new connection on port 21" 

${IPTABLES} -A INPUT -i ${EXT_NIC} --protocol  tcp --destination-port 21 -m state --state NEW -j ACCEPT
```

"works", but the only ftp client i found out that can make any changes to the chroot or read a file is pure simple console ftp. any other ftp client may log in but doesn't see a file/folder or can't make a file/folder even though it has the rights to do it. pretty strange, isnt' it? so i'm stuck with 

```
${IPTABLES} -A INPUT  -i ${EXT_NIC}  -m state --state NEW  -j ACCEPT
```

 which simply is stupid.

----------

## splooge

 *BlinkEye wrote:*   

> just for the record:
> 
> ```
> echo "* enable incoming new connection on port 21" 
> 
> ...

 

Well typically you need to open up 2 ports, one for ftp, and the other for FTP-data.

However, you have allowed RELATED connections, which normally takes care of the 2nd port.  In any case, I don't think it's good practice to state match and ip match all in the same line.  Change the line to this:

iptables -A INPUT -i ${EXT_NIC} -p tcp --dport 21 -j ACCEPT

and report back.

----------

## splooge

Actually I took the liberty of re-doing your script, chopping out the unnecessary and redundant flak, losing the variables (you weren't really using them anyways =p ) and shortening up the commands.  Hopefully this will make sense to you.

BTW good job so far on your "grasping" of iptables.  You'll have it soon.

#!/bin/bash 

iptables -F 

iptables -X 

iptables -P INPUT DROP

iptables -A INPUT -i ! ppp0 -j ACCEPT 

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

iptables -A INPUT -i ppp0 -p tcp --dport 22 -j ACCEPT 

iptables -A INPUT -i ppp0 -p tcp --dport 80 -j ACCEPT  

iptables -A INPUT -i ppp0 -p tcp --dport 443 -j ACCEPT 

iptables -A INPUT -i ppp0 -p tcp --dport 8080 -j ACCEPT 

iptables -A INPUT -i ppp0 -p tcp --dport 993 -j ACCEPT 

echo 1 > /proc/sys/net/ipv4/ip_forward 

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

----------

## BlinkEye

you're doing me a great favour helping me out! thank you very much for shortening and simplifying my script, looks a lot more readable now. i'm sure your solution will work - unfortunately nobody of my friends is awake anymore and could try accessing my ftp server  :Embarassed: 

i'll close this topic as soon as i have confirmation that it is working.

----------

## BlinkEye

oukei, it still doesn't work. 

```
iptables -L
```

shows me the same output as with my earlier script and users outside my local net still can't upload or download.

adding

```
 iptables -A INPUT -i ppp0 -p tcp --dport 20 -j ACCEPT
```

for ftp-data doesn't work. 

any idea?

----------

## splooge

This box doesn't sit behind any type of cable or dsl router does it?

In any case, this might not be the appropriate solution, but without knowing your network topology all I can really suggest is that you have the clients use PASV ftp.

----------

## BlinkEye

no, it doesn't. the cable modem is bridged and my server/gateway does the dialup. i just happened to find the setting for running vsftd in passiv mode - i admit i don't know the advantage/disadvantage of running an ftp server in active/passive mode   :Embarassed: 

----------

## splooge

It should work if both your ftp and ftp-data port are open.

Let's do something to see if we can rule out iptables being the source of the problem. Drop all your rules and set your default policies to accept.  Does it work then?

btw how did pasv mode work out for you?  afaik there is no disadvantage to using it, it just plays nicer with firewalls.

----------

## BlinkEye

this is a snippet from iptraf on the external device when accessing the ftp server from the lan:

```
  UDP (57 bytes) from serverIP:36891 to nameserverIP:53 on ppp0

  UDP (255 bytes) from nameserverIP:53 to serverIP:36891 on ppp0

  UDP (57 bytes) from serverIP:36891 to nameserverIP:53 on ppp0

  UDP (127 bytes) from nameserverIP:53 to serverIP:36891 on ppp0

  UDP (69 bytes) from serverIP:36891 to nameserverIP:53 on ppp0

  UDP (139 bytes) from nameserverIP:53 to serverIP:36891 on ppp0

  OSPF hlo (a=0 r=212.60.63.129) (76 bytes) from 212.60.35.31 to 224.0.0.5 on ppp0

  OSPF hlo (a=0 r=212.60.63.129) (76 bytes) from 212.60.35.31 to 224.0.0.5 on ppp0

  OSPF hlo (a=0 r=212.60.63.129) (76 bytes) from 212.60.35.31 to 224.0.0.5 on ppp0

  OSPF hlo (a=0 r=212.60.63.129) (76 bytes) from 212.60.35.31 to 224.0.0.5 on ppp0

  OSPF hlo (a=0 r=212.60.63.129) (76 bytes) from 212.60.35.31 to 224.0.0.5 on ppp0
```

it's not a ftp server problem, because if i put a rule

```
${IPTABLES} -A INPUT  -i ${EXT_NIC}  -m state --state NEW  -j ACCEPT
```

in my script anybody my access the ftp server (well, the problem isn't accessing or login, they are able to do that). i'm sure that the problem is the port 20. although i opened it it doesn't show up on a nmap of course, because no service is running on port 20. i think i need some rule that says: if related to port 21 permit access to port 20. any idea?

----------

## splooge

That iptraf info isn't showing anything related to ftp.  Although it is interesting seeing ospf in there ... ?  Ah well probably not related anyways.

Anywho, this:

${IPTABLES} -A INPUT  -i ${EXT_NIC}  -m state --state NEW  -j ACCEPT

is the same thing as doing this:

iptables -P INPUT ACCEPT

and

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

Is what does -- or should do -- as you say, "if related to port 21 permit access to port 20."

So to be quite honest I'm fairly stumped, maybe I don't know ftp as well as I thought I did =(  Did PASV mode end up helping you out?  (PASV is something you set on the client, not server, fyi)

Grasping at straws here: try loading the ip_conntrack_ftp module.  I'm fairly certain it's only used for helping NATted ftp connections, which isn't really our case here, but give it a shot anyways.  Who knows.  Like I said.  I'm grasping at straws.    :Confused:   We might have to bust out the big guns and ask Kashani.

----------

## BlinkEye

well, it works now. it turns out that the problem was my friend trying from work. my script seems to have a "bug" though, because it works now with yours. i don't have to open port 20, not even passiv mode. thanks again!

[EDIT]it's definitely the ip_contrack_ftp module that is needed. issue solved![/EDIT]

----------

