Problems with inward PPTP tunnel
Brett Glass
brett at lariat.net
Sun Mar 22 12:27:45 PDT 2009
Everyone:
I've routinely used FreeBSD to create firewall routers which
protect the machines inside the firewall from attempted connections
from the outside world, but allow an administrator to "tunnel into"
the LAN using PPTP to do maintenance. I've done this by making the
firewall into a PPTP server using the PoPToP PPTP daemon. To tunnel
into the LAN (which, in the example below, is the subnet
172.17/16), I connect to the router using PPTP, and it establishes
an encrypted tunnel into the LAN.
This worked well on FreeBSD versions up to 6.x, but has abruptly
stopped working on 7.1. I could establish a PPTP connection, but
couldn't reach hosts inside the LAN! I investigated, and here's
what I found. First, using tcpdump(8), I saw that when I tried to
ping hosts inside the LAN from the computer that was tunneling in,
the packets were reaching them and they were responding. However,
the responses were not being returned over the VPN connection. I
needed to understand why.
I knew that the PPTP daemon invokes FreeBSD's userland PPP program,
which creates the routing table entries that make the tunnel work.
The PPP configuration contains (among other things) the following lines:
set ifaddr 172.17.0.1/32
set mtu maximum 1496
enable proxy
enable mschapv2 mppe
set mppe * stateless
The external machine's address is specified in the ppp.secret file.
In the examples below, it was 172.17.0.7.
Because of the "enable proxy" command, the PPP program does proxy
arp for the inward-tunneling machine. The server is also SUPPOSED
to route packets from the LAN which are destined for the
inward-tunneling machine to the PPP tunnel. The result is that the
machine that's tunneling in is, for all practical purposes, on the
internal LAN. It looks, to machines on the LAN, as if it is at the
same MAC address as the router but has a unique IP address that's
different from the router's.
On FreeBSD 6.x and prior, the routing table looks like this once
the connection is established:
FreeBSD 6.x
172.17 link#1 UC 0 0 fxp0
172.17.0.1 00:50:8b:xx:xx:xx UHLW 1 190427 lo0
172.17.0.7 172.17.0.1 UH 0 8 tun0
172.17.0.7 00:50:8b:xx:xx:xx UHLS2 1 0 fxp0
Note that packets destined for 172.17.0.7 are correctly routed out
through the tun0 interface.
On FreeBSD 7.1, however, we see:
FreeBSD 7.1
172.17.0.0/16 link#2 UC 0 0 dc0
172.17.0.1 00:50:8b:xx:xx:xx UHLW 2 0 lo0
172.17.0.7 172.17.0.1 UGH 0 0 dc0
172.17.0.7 00:50:8b:xx:xx:xx UHLS2 1 0 dc0
Note that the "tun" interface through which the packets are
supposed to be routed does not appear where it should; in fact, it
does not appear ANYWHERE IN THE ROUTING TABLE. This is obviously an
error, because without such an entry no packets can ever be sent
back to the host which is tunneling in! (It occurs to me that this
could affect not only a VPN server but any PPP server, including
one that answered calls on dialup modems.)
I tried to work around the problem by adding the lines
shell route delete HISADDR
shell route add -host HISADDR MYADDR -ifp INTERFACE
to the ppp.linkup file, but to no avail. However, executing the command
route add 172.17.0.7 172.17.0.1 -ifp tun0
from the shell, as root, after the link was fully established DID
work, suggesting that PPP was somehow interfering with my attempts
to fix the routing table in the ppp.linkup file. Adding "disable
sroutes" to the configuration didn't solve this.
It seems to me that the root (route?) cause of the problem is that
the PPP program isn't correctly specifying the "tun" interface when
it sets up routes.
What's the best solution to this problem? This problem clearly
would affect anyone who wanted to set up a similar tunneling
arrangement using userland PPP, and may also cause problems in dialup servers.
--Brett Glass
More information about the freebsd-net
mailing list