Solved Block all incoming, but allow all outgoing

Before anyone says it, I know I could do this differently, but I feel like I shouldn't have to.

I'm trying to block all incoming traffic (except, of course, for public ports; SMTP, HTTP, HTTPS), but still allow all outgoing traffic.
Tried something like this;

Code:
62000 allow tcp from any to  $ME  25,80,443
62001 allow tcp from  $ME  to any 25,53,80,443
64000 deny tcp from any to  $ME
65534 allow ip from any to any

...which does block all non-public incoming, *but* it prevents me from outgoing stuff like wget, lynx, etc.

I could swear something like this used to work in FreeBSD v.4.

{edit: SirDice pointed out DNS to me, so I changed 62001, above, to reflect this. Didn't work, but it was a keen observation. Thank you.}
 
Yes, I deleted my post, it wasn't actually correct. You have an allow from any to any at the end, so everything that hasn't been blocked by a previous rule would be allowed anyway. As the only deny rule you have deals with incoming TCP traffic everything else should simply be accepted.

I suck at IPFW but you do need to allow the return traffic, I think that's getting blocked right now. So traffic is allowed out but the response isn't allowed back in. I'm more used to PF where rules are stateful (keep state) by default. If I recall correctly that's not the case for IPFW.

Just have a look with tcpdump(1), that's the de facto standard tool to diagnose issues like this. It really helps if you can actually "see" the packets.
 
DNS uses udp too.
In my experience, DNS uses UDP 99.9% of the time.
I'm not dealing with UDP, at the moment, until I can get the TCP blocking figured out.


Yes, I deleted my post, it wasn't actually correct. You have an allow from any to any at the end, so everything that hasn't been blocked by a previous rule would be allowed anyway. As the only deny rule you have deals with incoming TCP traffic everything else should simply be accepted.
True, but it's embarrassing that I didn't think of DNS, in the first place. DNS issues end up being the #1 problem I find in folks who come to me with computer problems. I can't believe I forgot about it, this time (even though it wasn't the issue).



Now, before this thread gets too far off-track, to reiterate;
When I have an IPFW set that looks like this;
62000 allow tcp from any to $ME 25,80,443 62001 allow tcp from $ME to any 25,53,80,443 64000 deny tcp from any to $ME 65534 allow ip from any to any
...then I can't get any outbound traffic out.
I would have thought that 62001 would supersede 64000, and allow me outbound, while still blocking all non-public inbound TCP, but it's not working that way.
 
Have you taken a look at /etc/rc.firewall? It sets up rules for predefined configurations, what you are asking is very similar to the "workstation" configuration.
Basically it is default deny inbound, default pass outbound from the machine with state, pass inbound responses to outbound.
 
  • Thanks
Reactions: o23
To allow all outgoing use something like
Code:
cmd="/sbin/ipfw -q add"   # Set rules command prefix
pif="tun0"
# Allow access to outside
$cmd 04030 allow tcp  from any to any out via $pif setup keep-state
$cmd 04040 allow udp  from any to any out via $pif keep-state
$cmd 04040 allow icmp from any to any out via $pif keep-state

To block all incoming, just add at the end add something like,
Code:
$cmd 05000 reject log all from any to any
$cmd 06000 deny   log all from any to any
 
  • Thanks
Reactions: o23
Thank you, everyone, for pointing me in the right direction.
The answer was, simply, keep-state.
I would never have found that on my own. I know it's in the 'man', but I never woulda seen that it does what I wanted. In fact, it wasn't until I thoroughly stress-tested it (with a proxy) that I actually believed it'd work.
Frankly, I'm tempted to suggest that the 'man' page, while thorough, could emphasize its importance a bit better.

So anyway, from my example, the single change I needed was;
62001 allow ip from $ME to any keep-state :OUTBOUND
(Someone will, correctly, point out that "keep-state :default" will do the same thing, but I prefer the pedant of using ":OUTBOUND".)

Maybe I'm still amazed with this shiny new toy, but I think this feature is something FreeBSD should be quite proud of.
I know I'm impressed.



Thanks for cajoling me to read the man page more in depth. I learned a few other useful things, like the -q option - I can make good use of in scripting.

Let me return the favour. The "reject" opermand is deprecated. Now it's "unreach", but I'd disrecommend it for the same reason I don't use the "reset" opermand anymore; they both send back some kind of indication that the port is intentionally firewalled. ('reset' sends back an RST, for TCP blocks. 'unreach' send a whole ICMP notice packet.)
I'm trying to keep my servers as mysterious as possible to would-be hackers, so I don't want 'em to even know what ports are firewalled.

Food for thought.
 
Back
Top