Tag Archives: PPTP

Routing IPv6 traffic through Debian pptpd into Hurricane Electric’s IPv6 tunnel

This is a repost of an answer I made to my own question on SuperUser (the “non-programmer” Stack Overflow) regarding setting up pptpd under Debian to route IPv6.

In the post, I’m also looking into using this under Mac OS X 10.8 Mountain Lion. I fully understand that PPTP is an insecure protocol and have separately also set up OpenVPN. However, I’m looking at this because PPTP is much more ubiquitous than OpenVPN and it’s easier to set up at both server and client side; no playing with certificate authorities, no playing with distributing configuration files to clients, etc. (Yes, I’m highly annoyed at the OpenVPN client for iOS not supporting the static key setup. Yes, I understand static key is less secure. No, I’m not dealing with stuff that require total and complete anonymity or encryption; I just want a VPN to work.)

This post does not deal with routing the segment through OS X once you got it to OS X.

This post only minimally deals with Windows as a client, because it Just Works™, and does not deal with GNU/Linux as a client, because it didn’t “magically” work under Ubuntu when I tried it, and I am not interested enough to figure out why.

Main goal here is documenting what an OS X user who has access to a Debian server with a public IP needs to do in order to get his OS X machine onto public IPv6 Internet without exposing it to public IPv4 Internet.

Client OS

Mac OS X does not particularly like IPv6 over PPP. Use the following after the connection has been set up:

sudo ipconfig set ppp0 AUTOMATIC-V6
sudo route add -inet6 default -interface ppp0

The prior seems to make OS X adhere to router advertisements; the latter adds a default route for IPv6. (Now, if only the certain-fruity-mobile-operating-system version of route provided -inet6, I’d be a happy wooden boy.)

Also take note that OS X will ignore whatever address was supposed to be negotiated over IPv6 and set up only a local address. This may interfere with routing towards OS X.

On the other hand, Windows 8 (of all systems!) has happily picked up the address sent over PPP, took note of the router advertisement, and overall configured itself flawlessly. PPTP really works nice in Windows.


First thing I missed was that Hurricane Electric’s tunnel broker actually assigns TWO /64 prefixes; one is supposed to be solely for client use, while the other is intended for routing additional clients (such as the PPTP client). And if you need more addresses (or prefixes!), you can even get a /48 prefix. (With IPv6, this means there’s more bits for ‘your’ use; HE’s prefix takes ‘only’ 48 bits. So that provides you a few more bits to control before the auto-generated suffix, created from a MAC address or even created randomly, kicks in and takes over last 64 bits. You could theoretically wiggle and subnet even with only 64-bits to spare, but I’ve seen strange behavior on either Windows 8 or OS X, so I wouldn’t rely too much on that.)

Instead of configuring radvd directly and running it as a server — simply don’t configure it globally. That is, don’t run it as a service on Debian.

Instead, let’s follow Konrad Rosenbaum’s example, at Silmor.de, and have radvd configured after pppd creates the PPP interface.

  1. Set up your IPv6 connectivity. I use Hurricane Electric; I’ve configured it as follows:
    # hurricane electric tunnel
    # based on: http://www.tunnelbroker.net/forums/index.php?topic=1642.0
    auto he-ipv6
    iface he-ipv6 inet6 v4tunnel
        address 2001:470:UUUU:VVVV::2
        netmask 64
        ttl 255
        gateway 2001:470:UUUU:VVVV::1
        ## from http://lightyearsoftware.com/2011/02/configure-debian-as-an-ipv6-router/
        # I did not set up the routing of the /64 nor the /48 prefix here, but
        # this would ordinarily do it.  
        #up ip link set mtu 1280 dev he-ipv6
        #up route -6 add 2001:470:WWWW:VVVV::/64 he-ipv6
        # Note that Hurricane Electric provides different /64 IPv6 prefixes
        # for the client (UUUU:VVVV) and routing (WWWW:VVVV). 
        # And the /48 prefix is very different altogether.
  2. Install pptpd. (Of course, take note of PPTP’s insecurity as a protocol, and consider using OpenVPN or some other alternative.)

  3. Edit /etc/ppp/pptpd-options
    name pptpd
    ipv6 ::1,::2

    Note the last line is different from the text in my question. You’re assigning some static addresses which may be respected by your client OS or not. (OS X seems to ignore them, but Windows uses them.)

  4. Create users for PPTP. Second column filters based on name argument in pptpd-options. Edit /etc/ppp/chap-secrets:
    ivucica pptpd AHyperSecretPasswordInPlainText

    You’re supposed to be able to replace the addresses with * instead of listing them manually. I did not try that out.

  5. Assign your PPTP users some IPv6 prefixes. NOTE: this is solely used by the script I’ll list below, which is derived from Konrad’s script.

    Edit /etc/ppp/ipv6-addr:

  6. Add new file /etc/ipv6-up.d/setupradvd:
    ADDR=$(grep ^$PEERNAME: /etc/ppp/ipv6-addr |cut -f 2 -d :)
    if test x$ADDR == x ; then
     echo "No IPv6 address found for user $PEERNAME"
     exit 0
    # We'll assign the user a /64 prefix.
    # I'm using a Hurricane Electric-assigned /48 prefix.
    # Operating systems seem to expect to be able to assign the 
    # last 64 bits of the address (based on ethernet MAC address
    # or some other identifier). So try to obtain a /48 prefix.
    # If you only have a /64 bit prefix, you can try to assign a
    # /80 prefix to your remote users. It works, but I'm only now
    # trying to enable these users to have routing.
    # Add the address for your side of the tunnel to the PPP device.
    # establish new route
    # (when a packet is directed toward user subnet, send it to user ip)
    #generate radvd config
    echo interface $IFNAME >$RA
    echo '{ AdvSendAdvert on; MinRtrAdvInterval 5; MaxRtrAdvInterval 100;' >>$RA
    echo ' prefix' $USERPREFIX::/$USERPREFIXSIZE '{};' >>$RA
    # Instead of your DNS...
    # ...try assigning the Google DNS :)
    echo ' RDNSS 2001:4860:4860::8888 {}; }; ' >> $RA
    # The creation of radvd configuration could be more readable, but whatever.
    # Start radvd
    /usr/sbin/radvd -C $RA -p $RAP.pid
    exit 0

    Don’t forget to chmod the script to make it executable by pppd:

    chmod 755 /etc/ipv6-up.d/setupradvd
  7. The script spews radvd configuration into /etc/ppp/ipv6-radvd/… ensure that the folder exists!
    mkdir /etc/ppp/ipv6-radvd
  8. Also add /etc/ppp/ipv6-down.d/setupradvd (and make it executable!) — taken verbatim from Konrad:
    kill `cat $RAP.pid` || true
    rm -f $RAP.*


    chmod 755 /etc/ppp/ipv6-down.d/setupradvd

I have not tested using DHCPv6 to distribute the routing information, addresses or DNS information, especially since rtadv should be fulfilling these roles. It also would not help me, because as of Mountain Lion, OS X still does not ship with a DHCPv6 client (perhaps intentionally; nine out of ten dentists most of IPv6 experts agree that DHCP is evil).

Once again, please note Michael’s comments on PPTP security; consider using OpenVPN in production.

Yes, Konrad Rosenbaum also has a nice tutorial on IPv6 over OpenVPN. 🙂