Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Mar 2016 14:40:16 +0100 (CET)
From:      elof2@sentor.se
To:        Jan Bramkamp <crest@rlwinm.de>
Cc:        freebsd-net <freebsd-net@freebsd.org>
Subject:   Re: Source routing howto
Message-ID:  <alpine.BSF.2.00.1603091336380.3214@farmermaggot.shire.sentor.se>
In-Reply-To: <56E00A06.20700@rlwinm.de>
References:  <alpine.BSF.2.00.1603091119130.3214@farmermaggot.shire.sentor.se> <56E00A06.20700@rlwinm.de>

next in thread | previous in thread | raw e-mail | index | archive | help

On Wed, 9 Mar 2016, Jan Bramkamp wrote:
> On 09/03/16 11:29, elof2@sentor.se wrote:
>> I've been searching the internet but can't find any good
>> documentation/examples on how to setup source routing in my FreeBSD.
>> 
>> What I want to do:
>> 
>> Let internet clients connect their OpenVPN to a FreeBSD box. The
>> client's internet traffic should be routed to a separate firewall
>> dedicated for all client networks (VPN and physical), where all clients
>> then leave the network.
>> 
>> The FreeBSD box has its own normal default gateway to speak with the
>> internet.
>> This route is needed in order to be able to keep the OpenVPN-traffic
>> flowing.
>> 
>> How do I source route the tunneled traffic, coming from e.g. 10.10.10.x
>> to the "client firewall"?
>> 
>> Are there any good examples out there?
>> Do I have to compile a custom kernel?
>> 
>> (the responses back from that firewall use a normal static route,
>> pointing 10.10.10.0/24 to the FreeBSD box)
>
> Do I understand you correctly that you have a FreeBSD box acting as
>
> * OpenVPN endpoint
> * router
> * and firewall

The FreeBSD box is an OpenVPN server.
Naturally it is also a router (forwarding enabled).
It has local firewall rules (using pf), but when I talk about a firewall I 
mean a separate box (Juniper/Checkpoint/something).

> all in one system and you want use the OpenVPN tunnel as default route for 
> your *other* hosts?

Heh, my description was pretty bad.

New try:
100 clients around the world connect to an OpenVPN server called "SRV".
SRV has a default route, so incoming and outgoing VPN packets use 
internet connection A (router A).

So far everything is as normal it can be. A server, a default route and an 
internet connection.

Next, all the vpn clients' traffic is sucked into their VPN tunnels (no 
split tunneling allowed).
The clients can reach internal servers. Good.
But when the clients surf the web, their traffic originates from SRV, 
using its default route towards the internet.

This works but is no longer what I want.

I now want the client traffic, aimed for the internet, to be routed 
elsewhere. 
In my case, "elsewhere" is a firewall with its own internet connection 
(B). The firewall is equipped with extra functions/blades to inspect 
client traffic and have all the rules for client traffic.

So basically I want the remote VPN users' surf traffic to pass through 
firewall B.

(
In my example, the VPN clients will get IPs in the 10.10.10.0/24 range.

Firewall B only need to route 10.10.10.0/24 to SRV in order to 
forward the response surf traffic back to the VPN clients.
)


So on SRV I need:
* traffic from SRV itself (openvpn responses, freebsd-update, mail, dns 
and other stuff) to 'any' should be routed to router A. Currently my 
default route.
* traffic with src net 10.10.10.0/24 to 'any' should be routed to B.

So two destinations for 'any'. Hence the need for source routing.

PS: traffic with src net 10.10.10.0/24 to internal nets, like 
10.20.30.0/24, should still be routed normally and not be thrown onto 
router B.

Hope that description is better.


> In that case what you need is some kind of *policy* based 
> routing.
> One way to go about it with more than one FIB (aka kernel routing table). The 
> problem is that you have to decide on the routing table to use before 
> performing the route lookup. For packets forwarded through your FreeBSD 
> router you have to select a non default FIB during input filtering e.g.
>    # simple case
>    ipfw add setfib 1 all from any to any in via $lan_if
>    # complex case for multiple interfaces
>    # ipfw table <table_number> add <interface> <fib_number>
>    ipfw table 1 add $lan_if1 1
>    ipfw table 1 add $lan_if2 2
>    ipfw table 1 add $lan_if3 2
>    ipfw table 1 add $lan_if3 2
>    # ...
>    # lookup routing table number in a table
>    ipfw add setfib tablearg all from any to any via table(1)
> For traffic generated by your FreeBSD router you can't use the firewall to 
> set the routing table because locally generated traffic only passes through 
> output filtering by which time the routing decision has already happend. 
> Instead you can set a processes default routing table with the setfib(1) 
> utility or use a setsockopt(2) with SO_SETFIB for each socket. Jails can also 
> set default routing table for sockets created inside the jail.

Heh. Do you mind giving another example now with the above description of 
the setup?
PS: i already use pf, not ipfw, on SRV.


> Remember that your DNS resolver can leak a lot of information as well if it 
> uses the default routing table.

Thanks for the heads-up. No, it uses an internal DNS.


> I would avoid policies based on IP addresses and prefer to define policies 
> based on (pseudo-) interfaces e.g. route (and nat?) traffic from vlan123 
> through the VPN tunnel.

The only two things I have to play with here is:
* ip range 10.10.10.x
or
* tun0

Using 'tun0' might not be possible if it has to exist when ipfw/pf load 
at boot, 'cause tun0 is not created until the openvpn service has started.

/Elof



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.BSF.2.00.1603091336380.3214>