I have one FreeBSD machine that I use as a playbox/server/torrentbox. It's part of my LAN. Here is the semantics (altered from an example on the OpenBSD website):

[ desktop ]    [ laptop ]
    |            |                               
 ---+------+-----+------- [switch] -------- ( DSL modem )
       [ FreeBSD playbox ]

I have set static IPs in all devices in the range. So my DSL modem is, my desktop is, and the FreeBSD box is There is also DHCP enabled, so every machine that doesn't have a static IP (a friend brings a laptop) gets assigned one by the DSL modem, in the range -

I have only one Ethernet card (em0) and I want to open a port on WAN but not on LAN. Doing this:

block in all
pass out all keep state
pass in proto tcp from any to any port 22

Will open the port on LAN too.

In all the examples I've seen that separated WAN and LAN, it was with two NICs and FreeBSD played the role of an intermediate (a firewall).

So, how do I open a port only on WAN?

This question has a follow up. There will be some ports that I want open in both, LAN and WAN, but I want to impose some limits on WAN. Here is an example I found online:

# Setup a table and ruleset that prevents excessive abuse by hosts
# that attempt to brute force the ssh daemon with repeated requests.
# any host that hammers more than 3 connections in 5 seconds gets
# all their packet states killed and dropped into a blackhole table.
table <wan_abuse> persist
block in quick from <wan_abuse>
pass in on $eth proto tcp to any port $wan_servers_tcp flags S/SA keep \
state (max-src-conn 10, max-src-conn-rate 3/5, overload <wan_abuse> flush)

Blocking LAN access: If pf.conf knows what your LAN subnet is, you can selectively block traffic from it. Using your example:

block in all
pass out all keep state

lan_subnet = ""
block in quick proto tcp from $lan_subnet to any port 22
pass in proto tcp from any to any port 22

Rate-limiting WAN but not LAN: Say for example you want to rate-limit traffic from the internet on ports 80 and 8080, but impose no rate limiting from the LAN on those ports. This snippet would track and block abusive WAN hosts while permitting access from the LAN:

table <http_abuse> persist
http_ports = "{ 80 8080 }"

pass in quick proto tcp from $lan_subnet to any port $http_ports
block in quick proto tcp from <http_abuse> to any port $http_ports

pass in proto tcp from any to any port $http_ports \
    flags S/SA keep state \
    (source-track rule, max-src-conn 50, max-src-conn-rate 25/2, \
     overload <http_abuse> flush)

For more flexible rate-limiting and blocking, you can use a tool like sshguard, which is conveniently available from ports and packages.

  • Whoohoo! You answered my question in full and went even beyond that (sshguard)! Thanks! If I had points, I would award them. I have one more question. Can the <http_abuse> contain those IPs that abuse any port from a list of ports (open to the WAN)? The reason being that I use 6 ports for FTP (vsftpd allows you to do this) and it would be much neater to have one rule instead of 6. I hinted something like that in my example, with $wan_servers_tcp, and I understand that if I put in that list 80, 22, and 21, someone who abuses 22 will also get blocked in 80. – swapjim Aug 24 '15 at 21:00
  • @swapjim: Conveniently, yes! I'll edit the example in my answer to make that more clear. – longb4 Aug 25 '15 at 0:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.