# IPFW all ports closed



## jamaroney (Jan 12, 2021)

I'm setting up a dedicated home webserver via lighttpd w/ FreeBSD 12.1.

I wanted a simple firewall that would allow entry only via SSH (port 22) and the web site access port (8080).

I thought this would work:

```
00100 allow ip from any to any via lo0
00200 allow ip from any to any 22
00300 allow ip from any to any 8080
00400 deny ip from any to any
65535 allow ip from any to any
```
But I can't access SSH or the web page. What should I change?


----------



## SirDice (Jan 12, 2021)

How did you enable it? What's in /etc/rc.conf?



jamaroney said:


> But I can't access SSH or the web page. What should I change?


It's stateless. You need to use statefull filtering. 









						Chapter 32. Firewalls
					

FreeBSD has three firewalls built into the base system: PF, IPFW, and IPFILTER. This chapter covers how to define packet filtering rules, the differences between the firewalls built into FreeBSD and how to use them




					www.freebsd.org


----------



## jamaroney (Jan 12, 2021)

SirDice said:


> How did you enable it? What's in /etc/rc.conf?
> 
> 
> It's stateless. You need to use statefull filtering.
> ...


in rc.conf, the only relevant settings I have are:
firewall_enable="yes"
firewall_script="/mnt/HDD/ipfw.rules"

I don't know what "stateful" means. The source cited uses the term quite often, but provides no definition. I have looked many places seeking clarity, but have not been successful.


----------



## xavi (Jan 12, 2021)

jamaroney said:


> I don't know what "stateful" means


You could start here: https://en.wikipedia.org/wiki/Stateful_firewall


----------



## monwarez (Jan 12, 2021)

I think that you need to add this kind of rule

```
00101 check-state
```
And then for SSH

```
00200 allow tcp from any to any 22 in via $interface setup keep-state
00200 allow tcp from any to any 22 out via $interface setup keep-state
```

The check-state rules will allow a packet that match the dynamic rules to pass


----------



## im (Jan 12, 2021)

jamaroney said:


> I thought this would work:
> Code:
> 00100 allow ip from any to any via lo0
> 00200 allow ip from any to any 22
> ...


Your ruleset have no rules for replies from your server. Try rules like this:

```
allow ip from any to any via lo0
allow ip from any to me 22
allow ip from me 22 to any
allow ip from any to me 8080
allow ip from me 8080 to any
deny ip from any to any
```

This ruleset does not allow traffic initiated by the server.
For example, OS update checks. It require traffic from server to 'any 80,443' and reverse traffic (replies from ports 80,443 to the server).

If you want a simple firewall - try to setup it without rule 'deny ip from any to any'.  At least during the testing time.

Your firewall_script "/mnt/HDD/ipfw.rules" needs to be executable shell script.
My own firewall_script looks like this:

```
#!/bin/sh
ipfw='/sbin/ipfw -q'
${ipfw} -f flush
#LOOPBACK
${ipfw} add pass all from any to any via lo0
#ssh
${ipfw} add allow tcp from 192.168.4.0/24 to me 22
${ipfw} add allow tcp from me 22 to 192.168.4.0/24
${ipfw} add deny log logamount 0 tcp from any to me 22
...other rules here...
```


----------



## jamaroney (Jan 13, 2021)

Thanks, im. Your suggestion worked just fine!


----------



## PMc (Jan 14, 2021)

monwarez said:


> I think that you need to add this kind of rule
> 
> ```
> 00101 check-state
> ...


Sorry, but this is a bit superfluous. The 'check-state'is not necessary in this example, because 'keep-state' implies check-state already. Also, the second 200 rule is for outgoing ssh sessions, from the machine to other hosts.

More in general:
With such an approach for a "simple" firewall one will usually run into a bunch of problems, in the line of:
* [admins: where is the unordered list gone?]
* almost everything that connects to the internet, relies on DNS. How is the machine going to resolve their nameserver queries?
* how is the machine going to adjust their machine time? (timed or NTP)
* the nightly `daily` script will usually download the port vulnerability lists from somewhere. How is this going to work?
* there may be more, this are just those I remember consciously.

So, usually you cannot live without outgoing requests, and you will start adding rules, and almost certainly this will produce a growing amount of spaghetti and finally end up unmaintainable. And, if the thing can be accessed from the internet, this is going to become dangerous.

For the given use-case of the OP we already have a solution in place, it is called the Workstation setup. This is taking care for the basic functionality, and can be configured in rc.conf. See /etc/rc.firewall for details. Here we have these options:

```
#  firewall_myservices:         List of ports/protocols on which this
        #                                host offers services.
        #  firewall_allowservices:      List of IPv4 and/or IPv6 addresses
        #                                that have access to
        #                                $firewall_myservices.
```
These could be configured to the required ports 22 and 8080.


----------

