On Mon, Feb 23, 2009 at 05:58:20PM -0800, Hilco Wijbenga wrote: > Hi all, > > I've been trying to get a simple firewall system up-and-running in > OpenBSD. I have "The Book of PF" and "Secure Architectures > with OpenBSD" so I thought it would be very simple. Well, we're two > weeks later now and still no firewall. :-) The pf rules I found in > those books don't seem to work as I expected them to work. > > Before I list my current pf.conf, let me give a few more details. My > firewall will be running a few services for my network (DHCP, NTP, and > DNS). I need to use NAT to get my own network Internet access. DHCP > works. I seem to have managed to get DNS (maradns on lo0 and sk1) and > ICMP working.
Sounds like a very basic home setup. You want your firewall to handle DHCP, NTP and act as a DNS resolver for your local network. Easy enough. > /etc/pf.conf > 01 ext_if = "sk0" > 02 int_if = "sk1" > 03 localnet = $int_if:network > 04 internet = $ext_if:network > 05 udp_services = "{ domain, ntp }" > 06 icmp_types = "{ echoreq, unreach }" > 07 > 08 nat log on $ext_if from $localnet to any -> ($ext_if) > 09 > 10 block log all > 11 > 12 pass quick inet proto { tcp, udp } from $internet to any port $udp_services > 13 pass quick inet proto { tcp, udp } from $localnet to any port $udp_services > 14 pass quick inet proto { tcp, udp } from $lo0:network to any port > $udp_services > 15 > 16 pass inet proto icmp all icmp-type $icmp_types > 17 pass from { lo0, $localnet } to any keep state > > a. Why do I need 12? I had expected 13 (which I don't seem to need). > Wouldn't 12 be for incoming requests from the Internet? > b. Given that ping works from my network (so that presumably routing > is okay), why doesn't anything else work? HTTP seems blocked by the > firewall. > c. How can I get pflog to flush immediately? I noticed I have to wait > a minute or so before logged lines show up. > d. Any other pointers? Let's start off with your questions and then a working example below. a. If you're only intending to allow outbound traffic from your local network, you don't. That rule would be to allow inbound requests from the internet to your firewall (and optionally, other internal services if you had rdr or binat rules). By default, pf uses "keep state" on all pass rules, which means that it will track your connections outbound and allow the appropriate replies from external services. b. Because line 16 is allowing icmp outbound *and* inbound. You have no directional (or interface) qualifiers. c. I would need more details here to give you a qualified answer. As in, examples. You're only logging blocked traffic. d. Read the PF FAQ. Ok, here is a working example based on your description. Noticed the beauty in the simplicity. :) ########################################################## 00 ext_if = "sk0" 01 int_if = "sk1" 02 03 set skip on lo 04 05 scrub in 06 07 nat on $ext_if from $int_if:network to any -> ($ext_if:0) 08 09 block in log all 10 pass in on $int_if inet keep state ########################################################## The first two lines are obvious. Why did I remove "localnet" and "internet"? The first is truly unnecessary in a ruleset this small; it simply adds abstraction where none is needed. The "internet" is already provided via the "any" and "all" keywords. Line 3 allows us to skip state on loopback, nothing exciting there. Line 5 provides "scrubbing", also known as packet defragmentation. This helps pf by reassembling packet fragments before applying rules. In short, it's a safety mechanism. Line 7 allows outbound NAT to the internet. Line 9 provides a basic "block all" for inbound requests. This affects both inbound from the internet, as well as inbound (from the firewall's perspective) from the local network. Which requires... Line 10, which finishes our tidy ruleset by passing all traffic from the localnet to [the firewall and] the internet. The "inet" keyword tells pf that this covers IPv4 traffic including TCP, UDP and ICMP. P.S. Contrary to what someone else suggested, pf is a "last match" packet filter. That means that it will traverse the entire ruleset and apply the last matching rule... UNLESS you use the "quick" keyword. I highly recommend you AVOID using "quick" until you have a solid comprehension of pf and packet filtering in general. P.P.S. I have not actually tested this ruleset, but it should work fine. If I've missed something I'm sure sthen@ will point it out for me. ;) Hope this helps, -- Jason Dixon DixonGroup Consulting http://www.dixongroup.net/