# Firewall

## karl420

I'm planning on putting a firewall in front of my 2 DNS servers, and my web/mysql/mail server. I've never dealt with firewalls before, but it is certainly time. I have experience with linux and freebsd, but I'm hoping to be able to use gentoo on all of my servers from now on.

What should I look into when planning to make a firewall? What kind of software is available for gentoo that would benefit a firewall? I've heard a lot about NAT and IPTABLES, but it all gets so jumbled in my memory (I wish the human brain had a defrag program!). I really need some tips about what I'm actually going to need to do, so I can fully plan this addition to my network, and plan the things I will need to change on my existing servers to make them work behind the firewall.

Thanks,

Karl Haines

----------

## NeddySeagoon

karl420, 

I use Smoothwall as a firewall. Its a cut down RedHat with nothing that a firewall doesn't need. SW is only about 20Mb of a download for the *.ISO. 

If you try it, be sure to get all the patches and apply them sequentially.

Smoothwall wants a whole PC to itself. Thats part of the security. If theres nothing else there you *know* nothing nasty was added or left behind when you installed it.

You shouldn't need to change much on your servers to make them work behiind a firewall.

A Gentoo installed system will have a lot of things on it a firewall doesn't need. e.g. build tools.

Regards,

NeddySeagoon

----------

## karl420

I dont think that matters to me. I'm interested in gentoo for portage. I like how packages are ALL installed in a uniform manner, which makes it easy for me to find configuration files, etc.

Karl   :Cool: 

----------

## padukes

I use iptables. It's pretty easy and flexible.  Here's a good but somewhat old how to: http://www.linuxguruz.com/iptables/howto/iptables-HOWTO.html

It's all command line stuff though, so if you prefer a GUI I heard firestarter is pretty good or you can try gtk-iptables

If command line is ok here are some quick tips (but read the howto):

First shut everything down.

These lines set the default to drop every packet (that is nothing comes in or goes out)

iptables -P INPUT DROP

iptables -P FORWARD DROP

iptables -P OUTPUT DROP

Then only open up stuff you actually need.

This line will do network address translation (NAT) assuming that eth0 is your connection to the internet and your lan is on some other card (say eth1)

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

After that you just open holes for the various services you want to let in.

This lets SSH connections start

iptables -A INPUT -p tcp --dport 22 --syn -j ACCEPT

This lets any connection that has been started stay connected

$iptables -A INPUT -i $ext_dev -m state --state ESTABLISHED,RELATED -j ACCEPT

-P

----------

## karl420

R0ck!   :Twisted Evil: 

Thanks a lot for your help, I think I now understand. IPTABLES and NAT work together to create the firewall. I will certainly read the howto.

I've been thinking about my mysql server too. Is there a way to only let it accept connections from certain hosts? (like ONLY the webserver?)

Karl

----------

## padukes

Yup,

You can setup a rule in iptables - something like only accept connections to port 1234 from machine 12.34.56.78. 

$iptables -A INPUT -p tcp --dport 1234 -s 12.34.56.78 -j ACCEPT

Or you can use the hosts.allow & hosts.deny files.  You should check the man for hosts.allow but a quick answer is you can put something like:

mysqld : ALL

in your hosts.deny file which will deny all connections to the mysqld process.  Then you can put something like:

mysqld : 12.34.56.78

in your hosts.allow which will allow connections to that process from that machine ip.

I think the main advantage of the hosts.* files is that you can have rules at a process level where iptables is for manipulating at a packet level.  Maybe someone else can give a better distinction between the two. 

-P

----------

## devon

 *padukes wrote:*   

> I think the main advantage of the hosts.* files is that you can have rules at a process level where iptables is for manipulating at a packet level. Maybe someone else can give a better distinction between the two.

 

AFAIK tcpwrapper (aka hosts.* files) will allow a TCP connection to be established before disconnecting. A iptables rule will drop the packet before connecting to the TCP socket.

BTW, MySQL does have it own's auth table.  :Smile: 

----------

## karl420

Thanks devon.

----------

## cdunham

Defense in depth. Install the firewall AND firewall each server with iptables AND use tcpwrapper AND application access control, etc, etc.

Right up until it's so much of a pain that you are tempted to put in a back door. Then back off exactly ONE notch.   :Razz: 

Oh, and Snort to smell trouble.

----------

## markkuk

 *karl420 wrote:*   

> 
> 
> I've been thinking about my mysql server too. Is there a way to only let it accept connections from certain hosts? (like ONLY the webserver?)
> 
> 

 

Yes, MySQL has internal access control mechanisms : http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Connection_access

Additionally you can use iptables to limit connections to TCP port 3306.

----------

## To

I usuall reject everything unless what I want to allow NOT reject what I don't want too... to work properly you must add a rule to accept rleated connections:

```
$IPTABLES -A INPUT -m state --state NEW,ESTABLISHED,RELATED --jump ACCEPT

$IPTABLES -A INPUT -i eth1 -p tcp -j DROP
```

You can allways use shorewall, it uses iptables and the configuration is real simple.

Tó

----------

## uzik

 *karl420 wrote:*   

> I'm planning on putting a firewall in front of my 2 DNS servers, and my web/mysql/mail server. I've never dealt with firewalls before, but it is certainly time. I have experience with linux and freebsd, but I'm hoping to be able to use gentoo on all of my servers from now on.
> 
> What should I look into when planning to make a firewall? What kind of software is available for gentoo that would benefit a firewall? I've heard a lot about NAT and IPTABLES, but it all gets so jumbled in my memory (I wish the human brain had a defrag program!).
> 
> Thanks,
> ...

 

Hi Karl,

NAT = Network Address Translation. This allows you to have more than

one computer share an IP address. Your DNS servers MUST have different

IP addresses so you really don't want NAT for them. NAT is a way to

save money by paying for one IP address but still use many computers.

Firewall = a filtering program to prevent unwanted access to your

computer. This might be useful for you.

Having been down the having my box hacked repeatedly road

I recommend you put DNS on a couple of junky old machines.

I built one for myself using a floppy and a pentium 2-133 mhz.

Since I don't run the DNS for Google it worked just great.

Since the machine didn't even have a hard disk and it ran

from a write protected floppy it didn't matter if anyone cracked

the box. They couldn't do anything to it anyhow!

Better yet, just pay someone $20/year to run your DNS for you.

----------

## karl420

OK, I've gotten IPTABLES & NAT going. When I boot w/o changing any of the tables it works fine (all the computers on the lan can can surf the internet, so the masq is working).

Ok, then I start to change the rules (I'm starting to understand it  :Wink: )

I change the default policy to DROP:

```
iptables -P INPUT DROP

iptables -P FORWARD DROP

iptables -P OUTPUT DROP
```

Now, as expected, the clients on the network don't get to surf. I figured that adding this rule to FORWARD would work:

```
iptables -A FORWARD -s 192.168.12.0/24 -j ACCEPT
```

But they still couldn't surf. I ended up adding that rule to OUTPUT, and INPUT also. Still no surfing.

192.168.12.* are the computers on my LAN, so why doesn't this work?

Thanks again,

Karl

----------

## padukes

I think about most of my rules in terms of interfaces as opposed to IP addresses.  For example, your firewall has two interaces - an internal one (that talks to the LAN) and an external one (that talk to the internet). I call the internal one $int (probably eth1) and the external one $ext (probably eth0).

I think you also need a few more rules:

1. Forward from internal to external (you pretty much already have this, but I prefer interfaces to IPs which can be spoofed)

```
iptables -A FORWARD -i $int -o $ext -j ACCEPT
```

2. Forward existing connections from the internet to the LAN

```
iptables -A FORWARD -i $ext -o $int -m state --state ESTABLISHED,RELATED -j ACCPET
```

3. Allow anything from the LAN to the firewall box

```
iptables -A INPUT -i $int -j ACCPET
```

4. Make sure the firewall can talk to itself

```
iptables -A INPUT -i lo -j ACCEPT
```

I also recently changed my default policy on OUTPUT to ACCEPT.  My rationale was that I only have one user using the box (me) and I don't really need to restrict myself from using any apps. Also, it makes my iptables rules a lot simpler.

Hope this helps,

P

----------

## karl420

When I do:

```
iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCPET
```

I get and error that says:

"No chain/target/match by that name."

Whats up with that?

Karl

----------

## padukes

Sorry, I spelled ACCEPT wrong. Looks like I did it on rule number 3 too.  

As a side, note if you don't set the OUTPUT policy to ACCEPT you will probably need corresponding OUTPUT rules for rules 3 and 4. That is:

3a. Allow anything from firewall box to lan

```
iptables -A OUTPUT -o $int -j ACCEPT
```

4a. Make sure the firewall can talk (out) to itself

```
iptables -A OUTPUT -o lo -j ACCEPT 
```

-P

----------

## karl420

I spelled it right on the firewall  :Wink: 

Just wrong on the forum. (Cause I copy/paste'ed it)

What do you think could be causing this error?

(BTW, I did change my OUTPUT to ACCEPT)

Karl

----------

## padukes

hmm... could be that the state match module isn't loaded. Try a:

```
modprobe ipt_state
```

If you don't have that module you'll need to add it in your kernel config and recompile.  I think that's the only module you'll need but for good measure here are all of the relevent ones that I have loaded:

```
pokey root # lsmod | grep ip

ipt_state                536   2  (autoclean)

iptable_filter          1612   1  (autoclean)

ipt_MASQUERADE          1176   1  (autoclean)

iptable_nat            15480   1  (autoclean) [ipt_MASQUERADE]

iptable_mangle          2040   0  (autoclean) (unused)

ip_tables              11392   7  [ipt_state iptable_filter ipt_MASQUERADE iptable_nat iptable_mangle]

ip_conntrack_irc        2992   0  (unused)

ip_conntrack_ftp        3888   0  (unused)

ip_conntrack           18624   4  [ipt_state ipt_MASQUERADE iptable_nat ip_conntrack_irc ip_conntrack_ftp]
```

P

----------

## anfpunk

You need to add...

#turns on forwarding

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

#source nats everything going out to the external ip.

$IPTABLES -t nat -A POSTROUTING -o $ext_iface -j SNAT --to-source $ext_ip

You will probably want to flush the rules everytime the script is ran.  So add somethign like this to the top of the script so only the rules after this is active at any time.

## Attempt to Flush All Rules in Filter Table

$IPTABLES -F

## Flush Built-in Rules

$IPTABLES -F INPUT

$IPTABLES -F OUTPUT

$IPTABLES -F FORWARD

$IPTABLES -t nat -F PREROUTING

$IPTABLES -t nat -F POSTROUTING

## Delete all user-defined chains.

$IPTABLES -X

I have my full script I can post if you would like an example.  It's nothing great but it's pretty configurable and werks.

----------

## DefconAlpha

Is to enable all the options for the netfilter and compile it into the kernel (if you don't like modules... *ahem*)

Then check out: http://www.cafes.net/mercury/stuff/firewall for a basic firewall starter... It's pretty straight forward. The division of protocols will make it easy to add specific services to a host. Just remember that iptables processes the rules in a top to bottom fashion. As far as getting *two* DNS servers running off *one* firewall... hafta keep working on that one.

----------

## To

karl420: I think you wont be disapointed if you check shorewall

 *Quote:*   

> *  net-firewall/shorewall
> 
>       Latest version available: 1.4.5-r1

 

Read the docs over http://www.shorewall.net and you should be able do what you need.

Tó

----------

## karl420

To:

I do appreciate the tip, but shorewall looks like overkill to me, and besides, I'm viewing this as a MAJOR learning experience. I will know my firewall very well, because I built it.  :Wink: 

Thanks

----------

## karl420

I don't know whats wrong, but I still can't connect to the internet once I change the rules to drop on INPUT and FORWARD, and add in the rules it doesn't work! 

here is the output of `iptables -L && iptables -t nat -L`:

(before I change the policy's of INPUT AND FORWARD)

```

Chain INPUT (policy ACCEPT) 

target     prot opt source               destination 

Chain FORWARD (policy ACCEPT) 

target     prot opt source               destination 

Chain OUTPUT (policy ACCEPT) 

target     prot opt source               destination 

Chain PREROUTING (policy ACCEPT) 

target     prot opt source               destination 

Chain POSTROUTING (policy ACCEPT) 

target     prot opt source               destination 

MASQUERADE  all  --  anywhere             anywhere 

Chain OUTPUT (policy ACCEPT) 

target     prot opt source               destination 

```

the rules i add each time are:

1. Forward from internal to external

```
$ iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
```

2. Forward existing connections from the internet to the LAN 

```
$ iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCPET
```

3. Allow anything from the LAN to the firewall box 

```
$ iptables -A INPUT -i eth1 -j ACCPET
```

4. Make sure the firewall can talk to itself 

```
$ iptables -A INPUT -i lo -j ACCEPT 
```

5. Change the default policy for INPUT and FORWARD to DROP

```
$ iptables -P INPUT DROP

$ iptables -P FORWARD DROP
```

Only 1 rule exists when it works, the MASQ rule. Then when I add the rules I want, change the policy from ACCEPT to DROP on INPUT and FORWARD, I can't pull up webpages on a client anymore. I'm struggling here, and once I get this to work, I need to set up port forwarding to my mail/web server, what a long day. Anyway, I hope you can make something out of this. Once again, I cannot thank you enough. 

Karl

----------

## Houdini

Can I offer the scripts I've used for this sort of thing?  I've got them in a usable fashion, even with a init.d script to run them.

Let me know if you'd like to see it.

----------

## karl420

Well posting the source might help me to see what I'm doing wrong. It seems like what I'm trying here should be simple. It works when it starts up, I all in rules to let everyone on the lan be accepted, then change the default policy to drop, so everyone else gets denied. What a day  :Wink: 

Anyway - post the source  :Wink: 

Karl

----------

## To

I'm not runing it now, but I got this from my old gateway backup:

eth0 -> intranet 10.10.10.0/24

eth1 -> connection to ISP cable dhcp

```
#!/bin/sh

ETH=eth1

ITH=eth0

export ETH0=`/sbin/ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | sed s/.*://`

export ETH1=`/sbin/ifconfig eth1 | grep 'inet addr' | awk '{print $2}' | sed s/.*://`

export PATH=$PATH:/sbin

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: firewall startup succeeded"

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: get ip adresses"

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: eth0 ip="$ETH0

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: eth1 ip="$ETH1

# Enable packet forwarding

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: enable forwarding"

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

# Flush Rules and set Policies

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: flush rulez"

iptables -F

iptables -X

iptables -F -t nat

iptables -X -t nat

iptables -P INPUT DROP

iptables -P OUTPUT ACCEPT

iptables -P FORWARD ACCEPT

# Enable the FTP PORT command

modprobe ip_conntrack_ftp

modprobe ip_nat_ftp

# Enable the IRC DCC protocol

modprobe ip_conntrack_irc

modprobe ip_nat_irc

modprobe ipt_state

# ***************************************

# *                INPUT                *

# ***************************************

## LOOPBACK 

iptables -A INPUT -i lo -j ACCEPT 

iptables -A INPUT -i $ITH -j ACCEPT  

iptables -N $ETH1

iptables -A INPUT -i eth1 -d $ETH1 -j $ETH1

iptables -A OUTPUT -o eth1 -s $ETH1 -j $ETH1

iptables -A $ETH1 -i eth1 -d $ETH1

iptables -A $ETH1 -o eth1 -s $ETH1

# FOWARD FOR INTERNAL IP's

iptables -N 10.10.10.9

iptables -A FORWARD -i eth0 -s 10.10.10.9 -j 10.10.10.9

iptables -A FORWARD -o eth0 -d 10.10.10.9 -j 10.10.10.9

iptables -N 10.10.10.10

iptables -A FORWARD -i eth0 -s 10.10.10.10 -j 10.10.10.10

iptables -A FORWARD -o eth0 -d 10.10.10.10 -j 10.10.10.10

iptables -N 10.10.10.20

iptables -A FORWARD -i eth0 -s 10.10.10.20 -j 10.10.10.20

iptables -A FORWARD -o eth0 -d 10.10.10.20 -j 10.10.10.20

iptables -N 10.10.10.40

iptables -A FORWARD -i eth0 -s 10.10.10.40 -j 10.10.10.40

iptables -A FORWARD -o eth0 -d 10.10.10.40 -j 10.10.10.40

# OPEN SERVICES

echo -n "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: open ports $ETH: ["

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

iptables -A INPUT -i $ETH -p tcp --dport 25 -j ACCEPT && echo -n "SMTP"

iptables -A INPUT -i $ETH -p tcp --dport 21 -j ACCEPT && echo -n " / FTP"

iptables -A INPUT -i $ETH -p tcp --dport 22 -j ACCEPT && echo -n " / SSH"

iptables -A INPUT -i $ETH -p tcp --dport 53 -j ACCEPT && echo -n " / NAMED"

iptables -A INPUT -i $ETH -p tcp --dport 80 -j ACCEPT && echo -n " / HTTP"

#iptables -A INPUT -i $ETH -p tcp --dport 110 -j ACCEPT && echo -n " / POP3"

#iptables -A INPUT -i $ETH -p tcp --dport 443 -j ACCEPT && echo -n " / SSL"

echo "]"

iptables -A INPUT -i eth1 -p tcp --dport 21 -j LOG --log-prefix "IPTABLES TCP-IN: " 

iptables -A INPUT -i eth1 -p tcp --dport 23 -j LOG --log-prefix "IPTABLES TCP-IN: " 

iptables -A INPUT -i eth1 -p tcp -j DROP 

# MASQUERADING

iptables -t nat -A POSTROUTING -o eth1 -s 10.10.10.0/24 -j MASQUERADE

iptables -t nat -A POSTROUTING -o eth1 -s 10.10.100.0/24 -j MASQUERADE

echo "`date +"%b %e %H:%M:%S"` `hostname -s` firewall: firewall over & out"
```

Hope it helps;)

Tó

----------

## karl420

Looks like I was leaving this out of my INPUT chain:

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

Works now with INPUT on DROP!

Now, I have a mail/web server running with a local static. How do I setup port forwarding so when someone for instance requests something from port 80 on the firewall, and it then forwards the request to 192.168.12.2 ?

Karl

----------

## anfpunk

iptables -t nat -A PREROUTING -p tcp --dport $PORT -j DNAT --to 192.168.x.x

----------

## karl420

Thanks! I had gotten that working last night, thanks to the help a padukes. Guess I forgot to come back and say that, ooops.

Thanks padukes, and everyone!

Karl Haines

----------

