Solved ipfw share internet

hello,i'am a newbie in ipfw, the scenario is this:
i have a server that run 2 network interfaces,in the future it will be a squid proxy..but for now,
step by step....

the lan is 192.168.50.0 (bce1)
the wan if 200.xxx.xxx.xxx (bce0)

so far i got this

Code:
ipfw -f flush

ipfw add 497 check-state
ipfw add 498 divert natd via bce0

ipfw add 499 allow tcp from any to any established
ipfw add 500 allow tcp from any to any via bce1
ipfw add 501 allow tcp from any to any via lo0

#ssh access from outside
ipfw add 502 allow tcp from any to any 26971 in via bce0 keep-state

#web access
ipfw add 503 allow tcp from any to any 80 out via bce0 keep-state
ipfw add 504 allow tcp from any to any 443 out via bce0 keep-state


#icmp from lan
ipfw add 505 allow tcp from any to any 53 in via bce1 keep-state
ipfw add 506 allow udp from any to any 53 in via bce1 keep-state

#web access from lan
ipfw add 507 allow tcp from any to any 80 in via bce1 keep-state
ipfw add 508 allow tcp from any to any 443 in via bce1 keep-state

#this icmp only permits me ping from the LAN to the outside only with IP address
ipwd add 509 allow icmp from any to any

but from a notebook in the LAN i cant access nothing(ping to web address,etc)
rules #505 to 50

But if I use

Code:
ipfw add xxx allow ip from any to any keep-state
i got access to everything from the LAN, but i dont want this
is give access to everyone to all...

i only want to share internet with the local LAN
 
Have you enable routing on your system? See FreeBSD Handbook section 30.2.22.

You should include the gateway_enable="YES" directive in rc.conf, I believe. Have you done that?
 
Have you enable routing on your system? See FreeBSD Handbook section 30.2.22.

You should include the gateway_enable="YES" directive in rc.conf, I believe. Have you done that?

yes..forgot to tell, in rc.conf I have:
Code:
gateway_enable="YES"
firewall_enable="YES"
firewall_nat_enable="YES"
firewall_script="/root/fir"
natd_enable="YES"
natd_interface="bce0"
 
It's been a while for me but for starters...

Rules 505 and 506 are related to TCP and UDP, not ICMP. That disagrees with your comment, which states ICMP. Port 53 (as mentioned in the rules) is for DNS.

Rule 499 shouldn't be needed. Any established connections should be handled by the check-state in line 497.

The comment for line 509 is wrong. You are allowing all ICMP traffic, not just ping and not just from your lan.

Also, I think the command is probably wrong. Shouldn't it be "ipfw" just like all the other lines?


It's been so long that I can't remember the proper way to do NAT, so I haven't commented on any of your NAT rules.
 
I suggest you watch counters to all your rules so you can see which rules are (and are not) being used.

Back when I was running IPFW, I had a few extra rule at the bottom to help identify issues with above rules.
Code:
# count all traffic from the LAN that is going to hit the default deny rule
ipfw add 65000 count all from any to any in via bce1
# count all traffic that got blocked on the way out to the Internet
# (why did it get blocked going out instead of in?)
ipfw add 65001 count all from any to any out via bce0
# count all traffic destined for the LAN that got blocked as it entered the LAN
# (again, why didn't get get blocked on the inbound interface)
ipfw add 65002 count all from any to any out via bce1
 
It seems, that you are going to setup a stateful NAT'ting firewall. This is the best you can do, however, there are several obstacles to be taken, and unfortunately the respective chapter in the handbook is somewhat outdated.

  1. In the case of a stateful setup with ipfw(8), you need to place 2 NAT rules in your firewall script, one for incoming traffic via the WAN interface and another one for outgoing traffic via the WAN interface.

  2. The checkstate rule must come directly after the incoming NAT rule.

  3. Packets must be able to pass more than once over the ruleset, therefore the sysctl variable net.inet.ip.fw.one_pass must be set to 0.

  4. You place all rules concerning LAN-only traffic before the first incoming NAT rule, and without the keep-state directive.

  5. All rules concerning traffic from/to the WAN must be placed between the 2 NAT-rules, and final processing of outgoing traffic must be deferred until all NAT has been done.

  6. Finally, you want to use the built-in NAT facility instead of the old divert-type NAT daemon.

Here comes a template of an ipfw script for setting up a stateful NAT'ting firewall:
Code:
#!/bin/sh
WAN="bce0"
LAN="bce1"

/sbin/ipfw -q flush
/sbin/ipfw -q table all flush
/sbin/ipfw -q nat 1 config if $WAN unreg_only reset

# Allow anything within the LAN - interface with heaviest traffic shall come first.
/sbin/ipfw -q add 10 allow ip from any to any via $LAN
/sbin/ipfw -q add 20 allow ip from any to any via lo0

# Catch spoofing from outside.
/sbin/ipfw -q add 70 deny ip from any to any not antispoof via $WAN

# NAT rule for incoming packets - IPv4 only, IPv6 ain't work with NAT.
/sbin/ipfw -q add 100 nat 1 ip4 from any to any in recv $WAN
/sbin/ipfw -q add 101 check-state

# Rules for outgoing traffic - allow everything that is not explicitely denied.
# /sbin/ipfw -q add 1000 deny ip from not me to any 25,53 out xmit $WAN
# /sbin/ipfw -q add 1001 deny ip from any to any 5353 out xmit $WAN

# Allow all other outgoing connections, i.e. skip processing to the outbound NAT rule #10000
/sbin/ipfw -q add 2000 skipto 10000 tcp from any to any out xmit $WAN setup keep-state
/sbin/ipfw -q add 2001 skipto 10000 udp from any to any out xmit $WAN keep-state

# Rules for incomming traffic - deny everything that is not explicitely allowed.
/sbin/ipfw -q add 5000 allow tcp from any to me 22,25,80,587,993,995 in recv $WAN setup keep-state
/sbin/ipfw -q add 5001 allow udp from any to me 500,4500 in recv $WAN keep-state
/sbin/ipfw -q add 5002 allow udp from any to me in recv $WAN frag

# Rules for allowing packets to services which are listening on a LAN interface behind the NAT
/sbin/ipfw -q add 6000 skipto 10000 tcp from any to any $pp1 in recv $WAN setup keep-state
/sbin/ipfw -q add 6001 skipto 10000 udp from any to any $pp1 in recv $WAN keep-state

# Catch any other tcp/udp packet, but don't touch gre, esp, icmp, etc...
/sbin/ipfw -q add 9998 deny tcp from any to any via $WAN
/sbin/ipfw -q add 9999 deny udp from any to any via $WAN

# NAT rule for outgoing packets.
/sbin/ipfw -q add 10000 nat 1 ip4 from any to any out xmit $WAN

# Allow anything else - just in case ipfw is not configured as open firewall.
/sbin/ipfw -q add 65534 allow ip from any to any
 
Last edited:
It's been a while for me but for starters...

Rules 505 and 506 are related to TCP and UDP, not ICMP. That disagrees with your comment, which states ICMP. Port 53 (as mentioned in the rules) is for DNS.

Rule 499 shouldn't be needed. Any established connections should be handled by the check-state in line 497.

The comment for line 509 is wrong. You are allowing all ICMP traffic, not just ping and not just from your lan.

Also, I think the command is probably wrong. Shouldn't it be "ipfw" just like all the other lines?


It's been so long that I can't remember the proper way to do NAT, so I haven't commented on any of your NAT rules.

yes,it was a grammatical error
 
It seems, that you are going to setup a stateful NAT'ting firewall. This is the best you can do, however, there are several obstacles to be taken, and unfortunately the respective chapter in the handbook is somewhat outdated.

  1. In the case of a stateful setup with ipfw(8), you need to place 2 NAT rules in your firewall script, one for incoming traffic via the WAN interface and another one for outgoing traffic via the WAN interface.

  2. The checkstate rule must come directly after the incoming NAT rule

  3. Packets must be able to pass more than once over the rulset, therefore the sysctl variable net.inet.ip.fw.one_pass must be set to 0.

  4. You place all rules concerning LAN-only traffic before the first incoming NAT rule, and without the keep-state directive

  5. All rules concerning traffic from/to the WAN must be placed between the 2 NAT-rules, and final processing of outgoing traffic must be deferred until all NAT has been done.

  6. Finally, you want to use the built-in NAT facility instead of the old divert-type NAT daemon.

Here comes a template of an ipfw script for setting up a stateful NAT'ting firewall:
Code:
#!/bin/sh
WAN="bce0"
LAN="bce1"

/sbin/ipfw -q flush
/sbin/ipfw -q table all flush
/sbin/ipfw -q nat 1 config if $WAN unreg_only reset

# Allow anything within the LAN - interface with heaviest traffic shall come first.
/sbin/ipfw -q add 10 allow ip from any to any via $LAN
/sbin/ipfw -q add 20 allow ip from any to any via lo0

# Catch spoofing from outside.
/sbin/ipfw -q add 70 deny ip from any to any not antispoof via $WAN

# NAT rule for incoming packets - IPv4 only, IPv6 ain't work with NAT.
/sbin/ipfw -q add 100 nat 1 ip4 from any to any in recv $WAN
/sbin/ipfw -q add 101 check-state

# Rules for outgoing traffic - allow everything that is not explicitely denied.
# /sbin/ipfw -q add 1000 deny ip from not me to any 25,53 out xmit $WAN
# /sbin/ipfw -q add 1001 deny ip from any to any 5353 out xmit $WAN

# Allow all other outgoing connections, i.e. skip processing to the outbound NAT rule #10000
/sbin/ipfw -q add 2000 skipto 10000 tcp from any to any out xmit $WAN setup keep-state
/sbin/ipfw -q add 2001 skipto 10000 udp from any to any out xmit $WAN keep-state

# Rules for incomming traffic - deny everything that is not explicitely allowed.
/sbin/ipfw -q add 5000 allow tcp from any to me 22,25,80,587,993,995 in recv $WAN setup keep-state
/sbin/ipfw -q add 5001 allow udp from any to me 500,4500 in recv $WAN keep-state
/sbin/ipfw -q add 5002 allow udp from any to me in recv $WAN frag

# Rules for allowing packets to services which are listening on a LAN interface behind the NAT
/sbin/ipfw -q add 6000 skipto 10000 tcp from any to any $pp1 in recv $WAN setup keep-state
/sbin/ipfw -q add 6001 skipto 10000 udp from any to any $pp1 in recv $WAN keep-state

# Catch any other tcp/udp packet, but don't touch gre, esp, icmp, etc...
/sbin/ipfw -q add 9998 deny tcp from any to any via $WAN
/sbin/ipfw -q add 9999 deny udp from any to any via $WAN

# NAT rule for outgoing packets.
/sbin/ipfw -q add 10000 nat 1 ip4 from any to any out xmit $WAN

# Allow anything else - just in case ipfw is not configured as open firewall.
/sbin/ipfw -q add 65534 allow ip from any to any

wow,this is really help..tomorrow i'l probe it in my work
 
I suggest you watch counters to all your rules so you can see which rules are (and are not) being used.

Back when I was running IPFW, I had a few extra rule at the bottom to help identify issues with above rules.

# count all traffic from the LAN that is going to hit the default deny rule
ipfw add 65000 count all from any to any in via bce1
# count all traffic that got blocked on the way out to the Internet
# (why did it get blocked going out instead of in?)
ipfw add 65001 count all from any to any out via bce0
# count all traffic destined for the LAN that got blocked as it entered the LAN
# (again, why didn't get get blocked on the inbound interface)
ipfw add 65002 count all from any to any out via bce1

thanks for the tips
 
I have been playing with jails lately and I couldn't seem to figure out how to allow redirected packets to reach my jails with IPFW. Until I found your specific rule and everything works. Looking at your rule:
Code:
# Rules for allowing packets to services which are listening on a LAN interface behind the NAT
/sbin/ipfw -q add 6000 skipto 10000 tcp from any to any $pp1 in recv $WAN setup keep-state
While I had:
Code:
/sbin/ipfw -q add 6000 allow tcp from any to any $pp1 in recv $WAN setup keep-state
Why do we need to skip incomming packets to the outbound nat rule immediately when comming in? I don't quite understand why my similar rule although different doesnt work. My rule also accepts incomming packets from a specific port ... Could you elaborate a bit about this obsigna? Because what I think happens is that your rule skips to the outbound nat rule (but wont match it) and then just gets allowed by the allow all rule. Is this correct? So my rule should do the same... accept the packet.
 
When setting up a stateful firewall, you create explicit rules for one direction only, which is usually the direction from the initiator to the responder. The difference to a non-stateful setup is that the reverse (responding) direction is handled implicitly. In a non-stateful setup you would just write another rule for the reverse direction.

You are correct, rule 6000 in the receiving direction won't hit the outgoing NAT rule. But the packets from the responder sitting behind the NAT, which are implicitly handled by the keep-state directive, MUST pass the outgoing NAT rule, or outgoing IPv4 packets won't even know where to go without being NAT´ted.
 
Back
Top