OK, this question is asked over and over again over the Internet and most of the time there is a (semi-) incorrect answer that you cannot do what was described in the original post. Let me clarify it once and for all :)
The short answer is L2TP (and PPTP for that matter) do not have facilities to do route pushes inside the protocol, but it can be achieved outside the protocol.
Since L2TP is a Microsoft invention, the best source of information is their technical documentation (and they are quite good at it, by the way). The technical description of what I am going to explain down below can be found at VPN Addressing and Routing.
The keywords for setting everything up properly (if you are going to do your own research) are: DHCPINFORM and "classless static routes".
First of all, how it works:
- a client connects to the VPN server
- after successful authentication a secure tunnel is established
- the client uses a DHCPINFORM message after the connection to request the DHCP Classless Static Routes option. This DHCP option contains a set of routes that are automatically added to the routing table of the requesting client (I slavishly copy-and-pasted this line directly from Microsoft documentation :) )
- the VPN server replies to that message with appropriate set of routes
Well, there is a caveat:
- there is RFC-3442 describing "DHCP Classless Static Routes" and there it states that the code for this option is 121. Microsoft decided to re-invent the wheel (as always) and uses code 249 for this option. Hence, to support a wider range of clients we need to respond back with both codes
I am going to describe a typical configuration using Linux box as the VPN server (you can configure MS servers using the link to the Microsoft documentation).
To configure routes on the clients we will need the following ingredients:
- L2TP/IPSEC (or PPTP) = for example, accel-ppp is a nice open source L2TP/PPTP server
- DHCP server = there are many, but I am going to describe dnsmasq's configuration
The following is a dump of a working accel-ppp configuration. I am providing it in its entirety, otherwise it would be difficult to explain what goes where. If you already have your VPN working you may skip this configuration file and concentrate on the DHCP configuration described below.
[root@vpn ~]# cat /opt/accel-ppp/config/accel-ppp.conf
[modules]
log_syslog
pptp
l2tp
auth_mschap_v2
ippool
sigchld
chap-secrets
logwtmp
[core]
log-error=/var/log/accel-ppp/core.log
thread-count=4
[ppp]
verbose=1
min-mtu=1280
mtu=1400
mru=1400
check-ip=1
single-session=replace
mppe=require
ipv4=require
ipv6=deny
ipv6-intf-id=0:0:0:1
ipv6-peer-intf-id=0:0:0:2
ipv6-accept-peer-intf-id=1
[lcp]
lcp-echo-interval=30
lcp-echo-failure=3
[auth]
#any-login=0
#noauth=0
[pptp]
echo-interval=30
echo-failure=3
verbose=1
[l2tp]
host-name=access-vpn
verbose=1
[dns]
dns1=192.168.70.251
dns2=192.168.70.252
[client-ip-range]
disable
[ip-pool]
gw-ip-address=192.168.99.254
192.168.99.1-253
[log]
log-file=/var/log/accel-ppp/accel-ppp.log
log-emerg=/var/log/accel-ppp/emerg.log
log-fail-file=/var/log/accel-ppp/auth-fail.log
log-debug=/var/log/accel-ppp/debug.log
copy=1
level=3
[chap-secrets]
gw-ip-address=192.168.99.254
chap-secrets=/etc/ppp/chap-secrets
[cli]
telnet=127.0.0.1:2000
tcp=127.0.0.1:2001
[root@vpn ~]#
===
At this point our clients can connect via L2TP (or PPTP) and communicate with the VPN server. So, the only missing part is a DHCP server that is listening on the created tunnels and that responds back with the necessary information. Below is an excerpt from the dnsmasq configuration file (I am providing DHCP related options only):
[root@vpn ~]# grep -E '^dhcp' /etc/dnsmasq.conf
dhcp-range=192.168.99.254,static
dhcp-option=option:router
dhcp-option=121,192.168.70.0/24,192.168.99.254,192.168.75.0/24,192.168.99.254,10.0.0.0/24,192.168.99.254
dhcp-option=249,192.168.70.0/24,192.168.99.254,192.168.75.0/24,192.168.99.254,10.0.0.0/24,192.168.99.254
dhcp-option=vendor:MSFT,2,1i
[root@vpn ~]#
In the above excerpt we are pushing routes 192.168.70.0/24, 192.168.75.0/24, and 10.0.0.0/24 via 192.168.99.254 (the VPN server).
Finally, if you sniff the network traffic (e.g. on the VPN server) you will see something like the following for the response on the DHCPINFORM message:
19:54:46.716113 IP (tos 0x0, ttl 64, id 10142, offset 0, flags [none], proto UDP (17), length 333)
192.168.99.254.67 > 192.168.99.153.68: BOOTP/DHCP, Reply, length 305, htype 8, hlen 6, xid 0xa27cfc5f, secs 1536, Flags [none]
Client-IP 192.168.99.153
Vendor-rfc1048 Extensions
Magic Cookie 0x63825363
DHCP-Message Option 53, length 1: ACK
Server-ID Option 54, length 4: 192.168.99.254
Domain-Name Option 15, length 18: "vpn.server.tld"
Classless-Static-Route-Microsoft Option 249, length 24: (192.168.70.0/24:192.168.99.254),(192.168.75.0/24:192.168.99.254),(10.0.0.0/24:192.168.99.254)
Vendor-Option Option 43, length 7: 2.4.0.0.0.1.255
P.S. I almost forgot an essential part required for the successful use of the above configuration. Well, it was described in the Microsoft docs I referred to, but who read the documentation? :) OK, clients should be configured without 'Use default gateway' on the VPN connection (on Windows it is in connection's properties -> Networking -> Internet Protocol Version 4 (TCP/IPv4) -> Properties -> Advanced -> IP Settings). On some clients there is also an option called 'Disable class based route addition' - it must be unset since it explicitly disables the functionality we are trying to implement.
Best Answer
As I suspected the problem is that I'm a bit of a numpty. In case anyone finds this question and is wondering the same thing, these are the key things you should know:
nodefaultroute doesn't go in your VPN server config. It is something for a PPP client. PPP clients are responsible for deciding whether or not to create a default route. This is the "Send all traffic" checkbox on iOS.
Your PPP client will always create a route to the remote gateway, plus a route for the remote subnet. Provided that you have IP forwarding enabled on your VPN server (/proc/sys/net/ipv4/ip_forward = 1 plus appropriate iptables rules on linux) your client will be able to send traffic to hosts on the remote subnet.
You must specify proxyarp in the ppp options.xl2tpd file for hosts on the VPN server's LAN to be able to send traffic back to clients. This will create an entry in the arp table and enable the proxy_arp option in the kernel. This allows the VPN server to accept packets on behalf of VPN clients using its own ethernet interface. If you don't want to do this or need to cross routers it appears that putting the VPN clients behind NAT is a popular solution, though I didn't test this myself.
Use the ms-dns ppp option to provide a nameserver for clients if they are going to use the VPN as a default route. Otherwise an iPad will complain that it's not connected to the internet.