iPhone – Linux VPN

The iPhone 3G firmware is really open to the world via 3G or Wi-Fi. Compared to Wi-Fi, mobile networks are quite secure. Warning, I never said that they are bullet-proof, but tapping a mobile network requires much more resources than Wi-Fi! Wireless network are widely available, which make them a good target for hackers!

On the iPhone, common applications can be secured (HTTPS in Safari and the mail client support SSL encryption) but the remote server must offer SSL services! Fortunately, the iPhone supports VPN! Three types of VPN are available: IPSEC, L2TP and PPTP. In this case, to protect our personal information, why not encrypt all the traffic through a VPN session established with a remote server? Let’s go!

I decided to use PPTP (“Point-to-Point Tunnel Protocol“) to setup my VPN with a Linux box. PPTP became obsolete by new VPN solutions and relies on other protocols to provide authentication and encryption but is very easy to install on a Linux server. PPTP works with two sessions: a TCP session to port 1723 to initialize and manage the connection and a GRE tunnel to encapsulate PPP packets. The PPP packets are encrypted using the MPPEMicrosoft Point-to-Point Encryption“) protocol.

Warning: Some firewall or access points may not forward GRE packets!

PPTP Server Setup

My Linux runs a stock Debian distribution. To install the PPTP server, just install the package:

# apt-get install pptpd

If needed, fix your firewall to accept incoming traffic on port TCP/1723 and GRE protocol

# /sbin/iptables -A INPUT -i eth0 -p tcp --dport 1723 -j ACCEPT
# /sbin/iptables -A INPUT -i eth0 -p 47 -j ACCEPT

The PPTP server relies on a single configuration file “/etc/pptpd.conf“. The default settings should work out of the box. The only thing to care of is the IP address attribution (which cannot conflict with your existing IP networks). Fix them to match your network:

localip 192.168.0.1
remoteip 192.168.0.234-238,192.168.0.245

As pptpd spawns a ppp process. The following modules must be available:

# lsmod | grep ^ppp
ppp_async               6496  0
ppp_generic            13556  1 ppp_async
ppp_mppe                5643  0

Normally they are installed in a standard kernel distribution. Mine is a bit exotic (Debian running on a Cobalt server).

VPN Users Setup

Now, create your VPN users. Authentication is performed by PPP. Add users accounts with the following command:

# echo "<username> pptpd <password> *" >>/etc/ppp/chap-secrets

Be sure to set safe access right to this file! If you have a lot of users, consider using another authentication method such as RADIUS.

Setup Routing and NAT

We need to enable IPv4 forwarding and NAT on the PPTP server. All packets coming from the iPhone will be translated to the server IP address to access the Internet.

# echo 1 >/proc/sys/net/ipv4/ip_forward
# iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 \
      -j SNAT --to <serverip>

Customize the commands above according to your environment and put them in your init scripts to survive to a reboot.

iPhone Configuration

Tap on “Settings”, “VPN” and “Add VPN Configuration”. Select “PPTP” as VPN type, and fill all the required fields:

  • Description : My_PPTP_VPN
  • Server : IP address or hostname of your PPTP server
  • Account : The login configured in /etc/ppp/chap-secrets
  • RSA SecurID : Off
  • Password : You know what!
  • Encrpyion Level : Auto
  • Sent All Traffic : On

Save and slide the VPN switch to “On”. Your iPhone will setup the VPN. Once successfully done, use your applications as usual. Everything will be encrypted up to your Linux server!

Here is a successful connection as seen from the Linux side in debug mode:

pptpd[27539]: MGR: Launching /usr/sbin/pptpctrl to handle client
pptpd[27539]: CTRL: local address = 192.168.0.1
pptpd[27539]: CTRL: remote address = 192.168.0.234
pptpd[27539]: CTRL: pppd options file = /etc/ppp/pptpd-options
pptpd[27539]: CTRL: Client 81.169.73.7 control connection started
pptpd[27539]: CTRL: Received PPTP Control Message (type: 1)
pptpd[27539]: CTRL: Made a START CTRL CONN RPLY packet
pptpd[27539]: CTRL: I wrote 156 bytes to the client.
pptpd[27539]: CTRL: Sent packet to client
pptpd[27539]: CTRL: Received PPTP Control Message (type: 7)
pptpd[27539]: CTRL: Set parameters to 100000000 maxbps, 64 window size
pptpd[27539]: CTRL: Made a OUT CALL RPLY packet
pptpd[27539]: CTRL: Starting call (launching pppd, opening GRE)
pptpd[27539]: CTRL: pty_fd = 6
pptpd[27539]: CTRL: tty_fd = 7
pptpd[27540]: CTRL (PPPD Launcher): program binary = /usr/sbin/pppd
pptpd[27540]: CTRL (PPPD Launcher): local address = 192.168.0.1
pptpd[27540]: CTRL (PPPD Launcher): remote address = 192.168.0.234
pppd[27540]: Plugin /usr/lib/pptpd/pptpd-logwtmp.so loaded.
pptpd[27539]: CTRL: I wrote 32 bytes to the client.
pptpd[27539]: CTRL: Sent packet to client
pppd[27540]: pppd 2.4.4 started by root, uid 0
pppd[27540]: Using interface ppp0
pppd[27540]: Connect: ppp0 <--> /dev/pts/3
pptpd[27539]: GRE: Bad checksum from pppd.
pptpd[27539]: GRE: Bad checksum from pppd.
pptpd[27539]: CTRL: Received PPTP Control Message (type: 15)
pptpd[27539]: CTRL: Got a SET LINK INFO packet with standard ACCMs
pptpd[27539]: GRE: buffering packet #1 (expecting #0, lost or reordered)
pptpd[27539]: GRE: buffering packet #2 (expecting #0, lost or reordered)
pptpd[27539]: GRE: timeout waiting for 1 packets
pptpd[27539]: GRE: accepting #1 from queue
pptpd[27539]: GRE: accepting #2 from queue
pptpd[27539]: GRE: accepting packet #3
pptpd[27539]: GRE: accepting packet #4
pptpd[27539]: GRE: accepting packet #5
pptpd[27539]: GRE: accepting packet #6
pppd[27540]: kernel does not support PPP filtering
pptpd[27539]: GRE: accepting packet #7
pptpd[27539]: GRE: accepting packet #8
pptpd[27539]: GRE: accepting packet #9
pptpd[27539]: GRE: accepting packet #10
pptpd[27539]: GRE: accepting packet #11
pptpd[27539]: GRE: accepting packet #12
pptpd[27539]: GRE: accepting packet #13
pppd[27540]: Cannot determine ethernet address for proxy ARP
pppd[27540]: local  IP address 192.168.0.1
pppd[27540]: remote IP address 192.168.0.234
pptpd[27539]: GRE: accepting packet #14
pptpd[27539]: GRE: accepting packet #15
pptpd[27539]: GRE: accepting packet #16
pptpd[27539]: GRE: accepting packet #17
pptpd[27539]: GRE: accepting packet #18
pptpd[27539]: GRE: accepting packet #19
pppd[27540]: LCP terminated by peer (User request)
pppd[27540]: Connect time 0.3 minutes.
pppd[27540]: Sent 0 bytes, received 1450 bytes.
pptpd[27539]: CTRL: EOF or bad error reading ctrl packet length.
pptpd[27539]: CTRL: couldn't read packet header (exit)
pptpd[27539]: CTRL: CTRL read failed
pptpd[27539]: CTRL: Reaping child PPP[27540]
pppd[27540]: Modem hangup
pppd[27540]: Connection terminated.
pppd[27540]: Exit.
pptpd[27539]: CTRL: Client 81.169.73.7 control connection finished
pptpd[27539]: CTRL: Exiting now
pptpd[31956]: MGR: Reaped child 27539

10 comments

  1. Anyone still monitoring this thread! I’m having an issue getting more than one user/session connected. Firewall isn’t complaining so I’m assuming I may have a max user/session command missing from the PPTPD configuration. Any ideas on how to correct this?

  2. I found it necessary to make sure ms-dns was not commented out , and was set to a DNS server that made the iphone happy. Eg, the same DNS server the machine running pptpd is using.
    Without this, the iphone VPN would start, but DNS resolution would not work. It would appear that the VPN was not working, but you could visit a website by IP address. The DNS server you had before you enable the VPN is ignored when the VPN is enabled and unless the iphone is told the new DNS server, it doesn’t know what to use.

  3. aye – that it is 🙂

    read up on it on the poptop pages (etc). i reckon it’s down to iptables now. having said that, i haven’t restarted networking yet though, as i’m trying this on a remotely hosted box in a data center (which is probably a bad idea but i forgot to turn on my home machine before i left home)… .

  4. right, I can access my web server running on the machine I’m connected to (192.168.0.1).

    my iptables looks like this:

    Chain INPUT (policy ACCEPT)
    target prot opt source destination
    DROP all — yx-out-f136.google.com anywhere
    ACCEPT all — anywhere anywhere
    ACCEPT all — anywhere anywhere
    ACCEPT all — anywhere anywhere
    ACCEPT icmp — anywhere anywhere icmp any
    ACCEPT all — anywhere anywhere state RELATED,ESTABLISHED
    ACCEPT tcp — anywhere anywhere tcp dpt:www state NEW
    ACCEPT tcp — anywhere anywhere tcp dpt:https state NEW
    ACCEPT tcp — anywhere anywhere tcp dpt:7742 state NEW
    ACCEPT tcp — anywhere anywhere tcp dpt:ftp state NEW
    REJECT all — anywhere anywhere reject-with icmp-port-unreachable
    ACCEPT tcp — anywhere anywhere tcp dpt:1723
    ACCEPT gre — anywhere anywhere

    Chain FORWARD (policy ACCEPT)
    target prot opt source destination
    REJECT all — anywhere anywhere reject-with icmp-port-unreachable

    Chain OUTPUT (policy ACCEPT)
    target prot opt source destination
    ACCEPT all — anywhere anywhere

    I’ve added “iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j SNAT –to 82.***.***.***” but nothing seems to be showing in the iptables config?

  5. argh. ok I’m being very silly this morning. vpn was off…

    no traffic in tcpdump and debug log looks fine.

    no idea why safari thinks it’s got no connection 🙁

  6. Nothing much happening. Safari simply says it’s not connected to the Internet.

    Belay that. All working now. No idea why. Oh – not to self: turn of the “auto proxy discovery” in the VPN settings on the iPhone 😉

    Thanks Xavier. Your tutorial saved me a lot of reading and googling.

  7. Hi Axel,
    When you try to access the website, run a tcpdump on your Linux box. Do you see traffic? Running the pptpd in debug mode can also help sometimes.

    Regarding Windows XP, no idea 🙁

  8. Hi Xavier, thanks for this! Works on my iPhone 3G/S 3.0 🙂

    However, I cannot browse the web.

    Also, how can I connect from a Windows XP box? I’ve played with several settings but it hangs on the authentication stage.

    Thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.