When implementing L2TP VPN solutions, a common requirement is to route only specific subnets (like 10.0.0.0/20) through the VPN tunnel while leaving other traffic unaffected. The default behavior of most L2TP implementations pushes all client traffic through the VPN connection, which isn't always desirable.
For Linux servers using xl2tpd and pppd, modify your configuration files:
# /etc/ppp/options.xl2tpd +mschap-v2 ms-dns 8.8.8.8 ms-dns 8.8.4.4 asyncmap 0 auth mtu 1200 mru 1200 hide-password name l2tpd proxyarp lcp-echo-interval 30 lcp-echo-failure 4 nodefaultroute ipparam l2tp
Create a custom ip-up script to handle route additions:
#!/bin/bash # /etc/ppp/ip-up.d/customroutes INTERFACE="$1" DEVICE="$2" SPEED="$3" LOCALIP="$4" REMOTEIP="$5" # Add specific routes when VPN connects if [ "$6" = "l2tp" ]; then route add -net 10.0.0.0 netmask 255.255.240.0 gw $REMOTEIP fi
For macOS clients, you can automate route configuration using a custom PPP hook:
#!/bin/sh # /etc/ppp/ip-up # Only execute for L2TP connections if [ "$PPPL2TP" = "1" ]; then /sbin/route -n add -net 10.0.0.0 -netmask 255.255.240.0 -interface $1 fi
Most mobile OSes don't provide native controls for selective routing. Workaround options include:
- Using third-party VPN clients that support route configuration
- Implementing a proxy solution for specific subnets
- Creating a custom VPN app with route control capabilities
After implementation, verify routing with:
# On Linux/Mac: route -n get 10.0.0.1 # On Windows: route print
Test connectivity while ensuring other traffic remains direct:
traceroute 10.0.0.1 traceroute 8.8.8.8
When setting up an L2TP VPN server (like in the referenced tutorial), a common requirement is to route only specific subnets through the VPN while maintaining normal internet connectivity for other traffic. This becomes particularly challenging when:
- You don't want all client traffic routed through the VPN (split tunneling)
- Mobile devices lack command-line access for manual route configuration
- You need consistent behavior across different client platforms
The key lies in modifying the VPN server's configuration to push specific routes to clients during connection. For L2TP/IPsec setups using xl2tpd and pppd, you can implement this through PPP options:
# In /etc/ppp/options.xl2tpd
ms-dns 8.8.8.8
ms-dns 8.8.4.4
proxyarp
nodefaultroute
# Add your specific route push:
ip-up-script /etc/ppp/ip-up.local
Create /etc/ppp/ip-up.local
with:
#!/bin/bash
# Push route for 10.0.0.0/20 to the client
/sbin/ip route add 10.0.0.0/20 dev $1
exit 0
Make it executable:
chmod +x /etc/ppp/ip-up.local
Different operating systems handle pushed routes differently:
- Windows: Automatically accepts pushed routes by default
- macOS: May require additional configuration in Network Preferences to honor server-pushed routes
- iOS/Android: Typically respect server-pushed routes without extra configuration
After connecting, verify the routes on your client:
On Linux/macOS:
netstat -rn | grep 10.0.0.0
On Windows:
route print | find "10.0.0.0"
If routes aren't being pushed correctly:
- Check pppd logs (
/var/log/ppp.log
or/var/log/syslog
) - Verify the ip-up script has execute permissions
- Ensure no firewall rules are blocking route advertisement packets
- Confirm the VPN server has proper routing to the 10.0.0.0/20 subnet