Policy Routing Policy routing is the process of forcing packets to take a certain route, often different from the default route, based on certain packet attributes (source, type of packets, interface, etc.). The need for policy routing arises for multi-homed hosts (hosts having two network connections to different ISPs), that cannot use a single default route. Having a central Internet connection for multiple private networks can require policy routing. It is most useful in case you have multiple networks connected behind a FreeBSD host with more than one connection to the Internet, when each network needs to use a different outgoing route. Also, policy routing should be employed when you need to separate traffic by certain criteria, such as source, destination or protocol When Not to Use Policy Routing Policy routing can be extremely useful, but it is not always needed. A frequent case of misuse is when configuring a tunnel as a default route. Instead of using the first gateway as the default, then injecting all the other traffic in the tunnel, use more specific routes. For example, if the tunnel ends at 10.10.10.10, the ip of the other end inside the tunnel is 1.2.3.4, and the gateway your provider gave you (and don't actually want to use) is at 2.2.2.2, you can use these routes in /etc/rc.conf: static_routes=tunnel_end route_tunnel_end=-host 10.10.10.10 2.2.2.2 defaultrouter=1.2.3.4Since policy routing does involve a certain overhead on the system, do think of a different solution first. Specific routes can be very useful, but policy routing is the only solution for certain cases. Configuring Policy Routing The easiest way of doing policy routing with FreeBSD is by using IPFilter. It comes by default with all recent versions of FreeBSD, and it can be easily enabled by adding this line to /etc/rc.conf: ipfilter_enable=YESBe advised that the IP addresses used in this article are fictional, and I have mixed public IP addresses with private ones (see RFC1918). You might find those in private networks, but they will almost never be assigned to you by an ISP. Example 1 - Multi-homed Host Suppose you have a host that is connected to two networks, via two interfaces: fxp0, with an IP address of 192.168.100.100, and fxp1, with an IP address of 192.168.200.200, both with the default classful netmask of 255.255.255.0. On both those networks, the gateways are located at 192.168.*.1. I'll assume that the default route is out fxp0. Now suppose the host receives a ping (an ICMP echo request packet) from host 1.1.1.1, to its IP address 192.168.200.200. The reply will be generated with a source address of 192.168.200.200, and sent to 1.1.1.1. But if the host has no specific route to 1.1.1.1, it will use the default route out fxp0, and try to send the reply via the gateway at 192.168.100.1. If a stateful firewall is in place on the gateway, the packet will most probably be dropped, as the request came via the other gateway (in the 200 network). Also, if egress filtering (filtering of outbound traffic) is configured on the 100 network gateway, the reply will be blocked because it is coming from a different network (and possibly logged as a spoofing attempt). This will also affect other types of packets, like TCP and UDP. The solution for this problem is rather simple: use policy routing to force packets from the 192.168.200.200 address to leave via the network they belong to. This is line in /etc/ipf.rules will do just as I have described: pass out quick on fxp0 to fxp1:192.168.200.1 from 192.168.200.200 to any This rule says force packets from my fxp1 address to exit via the gateway on fxp1 (not my default gateway on fxp0). Example 2 - Asymmetric Traffic This is similar to Example 1, but with a different purpose. Let's assume that one of the links, fxp0, is an ADSL link with a static IP address. The fxp1 link is a cable modem, with a dynamic IP. You want to have a web server, so you put it on the static IP. But the cable link has better bandwidth, so you want to take advantantage of that. Web traffic in inherently asymmetric, with a small request from the client to the server, and a larger reply from the server to the client. So receiving the request on the ADSL link will not hurt, and it has the added benefit of having a static IP address. So you decide to send the replies via the bigger bandwidth link. What you need to do is allow requests to the web server on your static IP address to come in via the ADSL link, but policy route the reply, diverting it to the cable link. Here is a configuration that does that: pass in quick on fxp0 proto tcp from any to 192.168.100.100 pass out quick on fxp0 to fxp1:192.168.200.1 proto tcp from 192.168.100.100 port = 80 to any The gateway on fxp1 (192.168.200.1 in this example) is assigned by DHCP, and you can find it out by running this command: # grep routers /var/db/dhclient.leasesThis will not work if your ISP on the # cable link implements egress filtering. For a web request to complete # successfully, the reply must come from the host the request went to. Since # you will be sending the reply via another link (possibly belonging to a # different ISP than the one who owns the fixed IP address), the cable ISP # might choose not to forward your packets, and make this setup inoperable. Example 3 - Routing for Multiple Networks Another scenario is a network that has access to two different ISPs, and has assigned addresses from each of those. The interfaces connecting to those ISPs are fxp0 at 10.0.0.2, using the gateway at 10.0.0.1, and fxp1 at 20.0.0.2, using the gateway at 20.0.0.1. The networks assigned by those two ISPs are 192.168.100.0/24, and 192.168.200.0/24. Traffic originating from the 100 network belongs to the 10.0.0.1 ISP, and the other network to the 20.0.0.1 ISP. The interfaces connecting those two nets are de0 and de1. This needs a simple configuration in /etc/ipf.rules. But we do have to take care and not shoot packets out to the ISP that are intended for the FreeBSD machine (which we'll suppose is at .254 on both those networks). # accept packets to us, don't forward them pass in quick on de0 from 192.168.100.0/24 to 192.168.100.254 pass in quick on de1 from 192.168.200.0/24 to 192.168.200.254 # other packets should be handled by their respective ISP # ISP1 pass in quick on de0 to fxp0:10.0.0.1 from 192.168.100.0/24 to any # ISP2 pass in quick on de1 to fxp1:20.0.0.1 from 192.168.200.0/24 to any