Question in short: How do I get traffic from a host on an internal network, using NAT behind a router, to use a VPN connection set up on the router?
I have a FreeBSD 9 router with 4 network interfaces. One external connected to my ISP and the others connected to internal subnets. The internal interfaces use NAT (by pf) to connect to the external world.
Now, I would like to have all traffic from a host on one of the subnets use a PPTP VPN connection set up on the FreeBSD machine. The end result would be that a host on the internal network uses a VPN without having to use a VPN client on the host itself.
I've managed to set up the VPN client with mpd5. Connecting from the router to the VPN server with mpd5, I get a new network interface — ng0 — with an ip address.
My problem is that I don't know where to go from here. There's just an interface (ng0) with an IP address. How do I make traffic from the internal, NATed, network use the VPN connection?
If you're trying to answer or point me in the right direction, you can start with the assumption I don't know or understand anything about VPNs, routing, NAT or pf — which I clearly almost don't. (Adding a route from where to where? Adding pf rules doing what to incoming and outgoing packets? etc.)
Configuration
This is right after connecting to the VPN server from the router.
My /etc/pf.conf:
ext_if = "em0"
local_if = "em1"
wifi_if = "em2"
misc_if = "em3"
localnet = "{" $local_if:network $wifi_if:network $misc_if:network "}"
nat on $ext_if from $localnet to any -> ($ext_if)
pass in all
pass out all keep state
Routing table:
Destination Gateway Flags Refs Use Netif Expire
default 188.60.52.1 UGS 0 998893 em0
10.0.1.0/24 link#10 U 0 159240 em1
10.0.1.1 link#10 UHS 0 358 lo0
10.0.2.0/24 link#11 U 0 503719 em2
10.0.2.1 link#11 UHS 0 0 lo0
10.0.3.0/24 link#12 U 0 3773731 em3
10.0.3.1 link#12 UHS 0 0 lo0
98.158.118.1 link#15 UH 0 0 ng0
98.158.118.63 link#15 UHS 0 0 lo0
127.0.0.1 link#13 UH 0 0 lo0
188.60.52.0/22 link#9 U 0 0 em0
188.60.55.17 link#9 UHS 0 0 lo0
To connect to the VPN server I have this in /usr/local/etc/mpd/mpd.conf:
strongvpn:
create bundle static B1
set bundle yes compression
set ipcp ranges 0.0.0.0/0 0.0.0.0/0
set ccp yes mppc
set mppc yes e128
set mppc yes stateless
# Not using these yet, as I don't know what to put in them ...
#set iface up-script /usr/local/etc/mpd5/ip-up.sh
#set iface down-script /usr/local/etc/mpd5/ip-down.sh
create link static L1 pptp
set link action bundle B1
set auth authname XXXXXXXXX
set auth password XXXXXXXXX
set link max-redial 0
set link mtu 1460
set link keep-alive 20 75
set pptp peer 98.158.112.17
set pptp disable windowing
open
The key question here is, "Did you try the VPN yet?" Everything seems fine. If your FreeBSD box can already route to the remote side of the VPN, your job is almost done. That means that the connection is valid and it is aware of the route to the remote network.
The host behind the router shouldn't require any changes at all to communicate "through the VPN." If it has the router set as its default gateway, then all traffic to remote networks (including the other side of the VPN) should go through the router, which as we stated, is already aware of the appropriate route. If you want to be very explicit, add a static route to the routing table of the host in question to ensure that it is aware of the correct route to the remote side of the VPN.
To check that your VPN is working as expected, you can start by pinging the other side of your VPN tunnel from your FreeBSD box.
The main issue once you are sure that your VPN is ok is "routing" all the traffic coming from your inside interfaces to the gn0 interface and doing NAT as well on this interface. You cannot do that by simply modifying the default router or you would shoot you in the foot, as the VPN requires its packets to route through your ISP ;)
The word here is "divert", but as far as I know (see " Does PF support divert like IPFW? "), this is not supported by the current FreeBSD "pf" port (this port is always older than the OpenBSD "pf", as being the original). Maybe in the future ...
Here are some hints for a solution which imply you changing from "pf" to "ipfw" which support "divert":
enable "ipfw" and set the "natd" out interface from your "/etc/rc.conf" file:
write your own "/etc/rc.firewall-myown" (you can use the default "/etc/rc.firewall" as a starting point):
The "natd" daemon configuration is quite straightforward and is mostly used to set port forwarding.
I did not check everything, especially the fact that you have 3 interfaces to NAT but I use "ipfw" for my own FreeBSD routing box and I did some VPN diverting in the past.
Enjoy !
I don't know if FreeBSD has
ip
command, but there most like is something similar to accomplish this.@see ip layer network admin guide (linux)