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
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
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]
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: 18.104.22.168.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.