ipfw FWD with generic kernel

Hello, all!

Is there a way to realize ipfw FWD with a generic kernel? And if it's not possible, what solution should I use instead?

Problem is this: I have a running FreeBSD box with ipfw, and I want to implement transparent proxy functionality on it. I suppose, one way is to use pf RDR in parallel with ipfw, and another is to use something like rinetd.

Which is better? And maybe there is a more appropriate way I don't know about.

Please help me with this issue.
Thanks in advance.
 
kilgor said:
...Is there a way to realize ipfw FWD with generic kernel?

Yes, it is possible, see below.

kilgor said:
Problem is this: I have running FreeBSD box with ipfw, and I want to implement transparent proxy functionality on it.

I suppose, one way is to use pf RDR in parallel with ipfw, and another is to use something like rinetd.

Note, that pf redirect rules are equivalent to ipfw(8)() nat redirect rules, i.e. also pf redirect involves a working NAT.

And this cannot be achieved by ipfw fwd rules, this doesn't usually do what people think it would do. ipfw fwd forwards a packet as is to another machine, and in most cases the other machine cannot recognize or handle this correctly because it does not know to whom to respond.

So again, most probably, you need ipfw nat redirect. For setting up this, do:

  1. add to /etc/rc.conf
    Code:
    gateway_enable="YES"
    firewall_enable="YES"
    firewall_nat_enable="YES"
    firewall_script="/etc/ipfw.conf"
  2. create the firewall configuration file /etc/ipfw.conf, replacing LAN by the ID of your LAN interface, for example em0 and WAN by the ID of your WAN interface, for example em1.
    Code:
    #!/bin/sh
    ipfw -q flush
    ipfw -q nat 1 config if WAN unreg_only reset \
                                redirect_port tcp 192.168.0.111:80 80 \
                                redirect_port tcp 192.168.0.111:443 443 \
                                redirect_port udp 192.168.0.111:53 53
    
    # Allow everything within the LAN
    ipfw -q add 10 allow ip from any to any via LAN
    ipfw -q add 20 allow ip from any to any via lo0
    
    ipfw -q add 90 deny ip from any to any not antispoof in
    
    ipfw -q add nat 1 ip from any to any via WAN
    
    # Rules for outgoing traffic - allow everything that is not explicitely denied
    ipfw -q add 1000 deny ip from not me to any 25 via WAN
    ipfw -q add 1001 deny ip from any to any 5353 via WAN
    
    # Rules for incomming traffic - deny everything that is not explicitely allowed
    ipfw -q add 5000 allow tcp from any to me 22,25,80,443,587 via WAN
    
    # Catch all other tcp/udp packets, but don't touch other packets, e.g. gre, esp, icmp
    ipfw -q add 9998 deny tcp from any to any via WAN
    ipfw -q add 9999 deny udp from any to any via WAN
    
    ipfw -q add 65534 allow ip from any to any
The above is an example of a traditional (stateless) rule set. A similar stateful ruleset would look like the following:

Code:
#!/bin/sh
ipfw -q flush
ipfw -q nat 1 config if WAN unreg_only reset \
                            redirect_port tcp 192.168.0.111:80 80 \
                            redirect_port tcp 192.168.0.111:443 443 \
                            redirect_port udp 192.168.0.111:53 53

# Allow everything within the LAN
ipfw -q add 10 allow ip from any to any via LAN
ipfw -q add 20 allow ip from any to any via lo0

ipfw -q add 90 deny ip from any to any not antispoof in

ipfw -q add 100 nat 1 ip from any to any via WAN in
ipfw -q add 101 check-state

# Rules for outgoing traffic - allow everything that is not explicitely denied
ipfw -q add 1000 deny ip from not me to any 25 via WAN out
ipfw -q add 1001 deny ip from any to any 5353 via WAN out

# Allow all other outgoing connections
ipfw -q add 2000 skipto 10000 tcp from any to any via WAN out setup keep-state
ipfw -q add 2010 skipto 10000 udp from any to any via WAN out keep-state

# Rules for incomming traffic - deny everything that is not explicitely allowed
ipfw -q add 5000 allow tcp from any to me 22,25,80,443,587 via WAN in setup keep-state

# Catch all other tcp/udp packets, but don't touch other packets, e.g. gre, esp, icmp
ipfw -q add 9998 deny tcp from any to any via WAN
ipfw -q add 9999 deny udp from any to any via WAN

ipfw -q add 10000 nat 1 ip from any to any via WAN out

ipfw -q add 65534 allow ip from any to any

Replace 192.168.0.111 with the actual IP address of the machine, to which the traffic should be redirected. Also, please take the given port numbers as examples only, and adapt it to your requirements. See, ipfw(8) - EXAMPLES for more redirection examples.

Note, that there are two NAT rules in the stateful case, one for incoming and one for outgoing traffic. Furthermore, in the stateful case, the packets may pass more than once the ruleset, so you need to allow this by setting the respective sysctl variable, so add in /etc/sysctl.conf:

Code:
net.inet.ip.fw.one_pass=0

And once you are there anyway, add another useful one:

Code:
net.inet.ip.fastforwarding=1

Bottom line: There is no need to compile a custom kernel. You can do all this using the GENERIC one.
 
Except, you don't have a single forward rule (aka "ipfw add fwd blah blah blah") in any of your examples.

In order to use fwd rules, you need to compile a custom kernel with
Code:
options IPFIREWALL_FORWARD
included.

Code:
net.inet.ip.fastforwarding
has nothing to do with IPFW forwarding.

Note the OP wants to do transparent proxying, which means intercepting outgoing packets and forwarding them to a proxy daemon on the local host (aka "ipfw add fwd 127.0.0.1:8080 tcp from <localsubnet> to any 80")
 
It is not possible to compile a custom kernel with the forwarding option. I tested it with FreeBSD 10; When building the kernel, it returns an error about the unknown option. A search on Google indicates, that this option was removed from FreeBSD in 2012.
 
I believe it's now built into the ipfw.ko on 10.x, and enabled by default, so there's no need to compile a custom kernel. Just load the module at boot time via /boot/loader.conf:
Code:
ipfw_load="YES"         # Be sure to enable IPFW support
ipfw_nat_load="YES"     # Be sure to enable in-kernel NAT support

Note: the default rule for IPFW is "deny ip from any to any". You can change that, if desired, at module load time by adding the following to /boot/loader.conf:
Code:
net.inet.ip.fw.default_to_accept="1"	# Set default rule to "allow ip from any to any"

I'm running FreeBSD 10-RELEASE-p7 on my core firewalls now, with a GENERIC kernel, and IPFW fwd rules are working correctly (used to redirect outgoing SMTP and NTP to our local servers for better tracking).
 
I know this is an old thread but I'm curious as to why my internet doesn't work if I add the following:

sysctl net.inet.ip.fastforwarding=1

When I use the above command it shows the change from 0 to 1. I'm using FreeBSD 10.2 setup as a firewall with ipf(8) & ipfw(8). When I change the setting back my internet works like it should. Also I'm not using a VPN or IPSEC.
 
Back
Top