IPFW How to allow TCP,UDP,ICMP traffic that's sent OUT to internet also return BACK IN but disallow traffic IN from internet that wasn't initiated

Hey everyone,

I'm struggling I'm new to FreeBSD and trying to get up and running an IPFW firewall on my FreeBSD VPS.

I don't want to setup any NAT but only firewall filter rules.

My /etc/rc.conf
Code:
firewall_enable="YES"
firewall_quiet="YES"
firewall_type="open"
firewall_myservices="any"
firewall_allowservices="any"
firewall_logdeny="YES"
firewall_script="/etc/ipfw.rules"
My /etc/ipfw.rules
Code:
#!/bin/sh
# Flush out the list before we begin.
ipfw -q -f flush

# Set rules command prefix
cmd="ipfw -q add"
pif="eth0" # interface name of NIC attached to Internet

# Change xl0 to LAN NIC interface name
# $cmd 00005 allow all from any to any via eth0

# No restrictions on Loopback Interface
$cmd 00010 allow all from any to any via lo0

$cmd 00101 check-state

# Outbound rules below

$cmd 00110 allow tcp from any to any out via $pif setup keep-state
$cmd 00111 allow udp from any to any out via $pif keep-state
$cmd 00112 allow icmp from any to any out via $pif keep-state

# Inbound rules below

# Deny all inbound traffic from non-routable reserved address spaces
$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif loopback
$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif loopback
$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif reserved for docs

# Deny public pings
# $cmd 00310 deny icmp from any to any in via $pif

# Deny ident
$cmd 00315 deny tcp from any to any 113 in via $pif

# Deny all Netbios services.
$cmd 00320 deny tcp from any to any 137 in via $pif
$cmd 00321 deny tcp from any to any 138 in via $pif
$cmd 00322 deny tcp from any to any 139 in via $pif
$cmd 00323 deny tcp from any to any 81 in via $pif

#Deny fragments
$cmd 00330 deny all from any to any frag in via $pif

#Deny ACK packets that did not match the dynamic rule table
$cmd 00332 deny tcp from any to any established in via $pif

#Allow inbound SSH connections
$cmd 00410 allow tcp from any to me 61748 in via $pif setup limit src-addr 2

#Reject and log all other incoming connections
$cmd 00499 deny log all from any to any in via $pif

#Everything else is denied and logged
$cmd 00999 deny log all from any to any


When I ping any host in internet packets are transmitted but no packets return back applies for both ping6 and ping,
However, my SSH-TCP communication on the custom port works fine also when I ping direct host in internet like 8.8.8.8 it works fine and packets return as it should.


What lines am I missing to allow both directional TCP, ICMP and UDP traffic that's initiated by the machine?

Currently ICMP packets gets out but can't return back in.

I guess it's same for some UDP and TCP packets, but SSH works fine.


Thank you
sysmaq
 
Last edited by a moderator:
Is it working without firewall enabled?

ipfw disable firewall
ping 8.8.8.8
ipfw enable firewall

When you use custom ipfw script you do not need the following in your /etc/rc.conf

firewall_quiet="YES"
firewall_type="open"
firewall_myservices="any"
firewall_allowservices="any"
firewall_logdeny="YES"
 
# Deny all inbound traffic from non-routable reserved address spaces
$cmd 00303 deny all from 127.0.0.0/8 to any in via $pif loopback
$cmd 00304 deny all from 0.0.0.0/8 to any in via $pif loopback
$cmd 00306 deny all from 192.0.2.0/24 to any in via $pif reserved for docs

Those rules are invalid; 'loopback' and 'reserved ...' should follow ' #' as they're comments. Use 'ipfw -t show' to list your rules with counters and timestamps to check status.

Where did you find this example ruleset? Listing specific ports and services to block is an endless task; better to allow traffic you want and just deny anything else, after logging anything of specific interest.

Looks like DNS issues, if IP addresses work but hostnames don't? Make sure to allow at least UDP 53 for ipv4, perhaps statelessly.

If you're using ipv6 you'll need other rules; see /etc/rc.firewall for well written and tested examples, like 'workstation'.
 
You need a stateful firewall. When you create your rules, allow all packets that go out, but split it in two rules for TCP and everything else.
In the TCP rule add "setup keep-state" at the end, and the other rule - just "keep-state" (because setup is related to initiating a TCP connection, while other packets are not connection based and lack that).

Here is an example from my notes (feel free to use in any form). This combines your requirement with some basic common sense protections of obvious hacking attacks. The example is borrowed heavily from the FreeBSD Handbook.
Bash:
firewall_enable: YES
firewall_logging: YES
firewall_script: /usr/local/etc/ipfw/ipfw.rules

And the rules file:
Bash:
externalInterface=vtnet0
ipfw=/sbin/ipfw

# localhost
${ipfw} add 1000 allow ip from any to any via lo0
${ipfw} add 1100 deny log ip from any to 127.0.0.1/8
${ipfw} add 1200 deny log ip from 127.0.0.1/8 to any

# Block some DOS attacks.
${ipfw} add 1300 deny log tcp from any to any tcpoptions !mss tcpflags syn,!ack

# Deny fragment attacks
${ipfw} add 1400 deny log icmp from any to any frag

# Deny icmp broadcasts
${ipfw} add 1500 deny log icmp from any to 255.255.255.255 in  via ${externalInterface}
${ipfw} add 1600 deny log icmp from any to 255.255.255.255 out via ${externalInterface}

# Reassemble fragmented packets
${ipfw} add 1700 reass all from any to any in

# Check state if the packet has already been allowed - stateful firewall
${ipfw} add 1800 check-state

# Established connections should always be allowed.
${ipfw} add 2000 allow tcp from any to any established


# Allow outgoing packets
${ipfw} add 3000 allow tcp from me to any out setup keep-state
${ipfw} add 3100 allow ip  from me to any out       keep-state

# Allow incoming ICMP 11, 3 (necessary if you use traceroute)
${ipfw} add 3200 allow icmp from any to me icmptypes 11 in  keep-state
${ipfw} add 3300 allow icmp from any to me icmptypes 3  in  keep-state


# Deny everything else, always last rule!
${ipfw} add 65530 deny log all from any to any
 
Back
Top