Setting up OpenL2TP
This page documents my experiments setting up an LNS for my A&A data SIMs, also see How to set up L2TP on a FireBrick.
The OpenL2TP download page offers version 1.8, which compiles straight out of the tarball.
This is the configuration I'm using—with my IP addresses and tunnel secret removed, naturally! If you don't want tunnel authentication, leave out the 'secret=' and 'auth_mode=' lines.
peer profile create profile_name=a.gormless peer profile modify profile_name=a.gormless \ tunnel_profile_name=aaisp-in \ session_profile_name=aaisp-in \ ppp_profile_name=aaisp-in \ peer_ipaddr=18.104.22.168 \ peer_port=1701 \ peer profile create profile_name=b.gormless peer profile modify profile_name=b.gormless \ tunnel_profile_name=aaisp-in \ session_profile_name=aaisp-in \ ppp_profile_name=aaisp-in \ peer_ipaddr=22.214.171.124 \ peer_port=1701 \ peer profile create profile_name=c.gormless peer profile modify profile_name=c.gormless \ tunnel_profile_name=aaisp-in \ session_profile_name=aaisp-in \ ppp_profile_name=aaisp-in \ peer_ipaddr=126.96.36.199 \ peer_port=1701 \ peer profile create profile_name=d.gormless peer profile modify profile_name=d.gormless \ tunnel_profile_name=aaisp-in \ session_profile_name=aaisp-in \ ppp_profile_name=aaisp-in \ peer_ipaddr=188.8.131.52 \ peer_port=1701 \ tunnel profile create profile_name=aaisp-in tunnel profile modify profile_name=aaisp-in \ secret=<your secret here> \ # leave out if you don't want tunnel authentication auth_mode=challenge \ # leave out if you don't want tunnel authentication src_ipaddr=<your LNS IP> \ our_udp_port=1701 \ mtu=1500 \ peer_profile_name=aaisp-in \ session_profile_name=aaisp-in \ ppp_profile_name=aaisp-in \ session profile create profile_name=aaisp-in session profile modify profile_name=aaisp-in \ ppp_profile_name=aaisp-in \ ppp profile create profile_name=aaisp-in ppp profile modify profile_name=aaisp-in \ auth_pap=yes \ auth_chap=yes \ auth_mschapv1=no \ auth_mschapv2=no \ auth_eap=no \ auth_none=yes \ auth_peer=no \ dns_ipaddr_pri=<DNS IP to give to SIM> \ local_ipaddr=<IP address of LNS endpoint on PPP link> \ remote_ipaddr=<IP address to give to SIM> \
I needed the src_ipaddr line in the tunnel profile because my LNS machine has several IP addresses on the same subnet, and the one that the LNS should be using is not the primary IP. openl2tp does not record the IP address that an l2tp packet came to and use that as the source address for the reply ... adding src_ipaddr fixes that.
Enabling tunnel authentication lets you be confident that you really are talking to the gormless's, and not some other LAC. Without it you are limited to just trusting the incoming IP address. What this doesn't do is authenticate the individual PPP sessions over the tunnel. Gormless's supply a CHAP username (the SIM's ICCID), challenge and response which will be verified if you enable PPP proxy authentication. The secret that is used is so obvious that it took me nearly 2 months to work it out. It's "password", without the quotes.
PPP over GPRS connections is a bit, well, weird. The PPP connection that pppd on your laptop establishes is not all the way through to your LNS as you might expect. It isn't even terminated in the mobile network—it's actually terminated on the modem. What this means is that the username and password you give to pppd are verified by the modem—which just accepts anything you supply.
The proxy authentication username that the LAC presents is a UK 07xxx phone number. It also presents a CHAP authentication ID, challenge and response. These are ignored unless you enable allow_ppp_proxy.
I gather that there is an option to pass the username and password that were supplied to the modem all the way through to the LNS, this would replace the phone number and 'password'. Haven't tried this yet.
The 'calling number' and 'called number' in the incoming call request are the SIM's ICCID.
Things to do
Work out how to identify individual SIMs and supply the correct IP address to each one. If you set 'auth_none' to 'no' in the ppp profile then PPP forces the other end to authenticate—this is separate from the PPP proxy authentication although it uses the same username and secret. The username is currently a telephone number (447...) so I think I can use that.
I've got this working, in as much as it allows entries in the LNS's chap-secrets to contain IP addresses and the correct one is passed to the modem. However (at least on pppd 2.4.5 with openl2tp 1.8) I haven't found a way to set the IP address on the LNS's end of the link. If you use the '-- local:remote' syntax in chap-secrets it picks up the remote IP but not the local one.
Another bit of fun is that at the moment the IP address on the LNS's end of the PPP link doesn't get communicated to the other end. It goes out to the LAC okay, which accepts it, but never passes it on. (I think I once saw it work with a data SIM that was connecting directly to A&A, but that doesn't seem to happen any more either.) To be honest, this in itself isn't that great a problem. However ...
Windows 7, and the Vodafone Mobile Broadband software (the Mac version works nicely with non-Vodafone SIMs, the Windows one doesn't, go figure) treat suitably capable 3G devices essentially as if they were Ethernet interfaces, rather than PPP devices. There's lots of interesting magic going on in there that I haven't figured out, but what they try to do is figure out a netmask and default gateway based on the IP address they're given. If you supply the second or third IP in a /30 for instance, they pick the other one as the default gateway. I want to see if and how this behaviour changes if the server end's IP address gets passed through correctly.
My Huawei K4505 doesn't offer a remote address if it doesn't get one from the peer. In this situation, Linux picks 10.64.64.64. My Nokia E51 offers 10.6.6.6 in this situation.
Microsoft's PPP implementations up to and including Vista still believe in classful addressing. If you don't want the PPP interface to be the default route, then if they are given a 'class A' address they assume a netmask of 255.0.0.0 and set a corresponding network route, similarly for class B and C addresses. Windows 7 has the option to disable this automatic classful route if you don't set the default route. Nice one Microsoft :-)
The Linux pppd understands the concept of point-to-point, non-broadcast links and gets it right.
Mac OS X, despite using the same pppd, manages to muck things up, however this can be fixed with suitable runes in /etc/ppp/ip-up:
# Remove the network route that pppd 'helpfully' sets up for us, which we don't need, and which just gets in the way. O1=$(echo $IPLOCAL | sed 's/\..*//') if [ "$O1" -le 127 ] ; then # Class A -- netmask 255.0.0.0 /sbin/route delete -interface -net $O184.108.40.206 $IFNAME 255.0.0.0 >> /var/log/ppp-ip-updown.log elif [ "$O1" -le 191 ] ; then # Class B -- netmask 255.255.0.0 O12=$(echo $IPLOCAL | sed 's/\.[0-9]*\.[0-9]*$//') /sbin/route delete -interface -net $O12.0.0 $IFNAME 255.255.0.0 >> /var/log/ppp-ip-updown.log else # Class C -- netmask 255.255.255.0 # (This will also pick up class D and E, which I doubt we'll be given!) O123=$(echo $IPLOCAL | sed 's/\.[0-9]*$//') /sbin/route delete -interface -net $O123.0 $IFNAME 255.255.255.0 >> /var/log/ppp-ip-updown.log fi
Yes, it's hacky!