A Dutch techie in China
23 Apr
After moving to China I ran into a few issues that got me to install a VPN. Namely:
After using OpenVPN for a while I got mildly annoyed by:
This made me switch to IPSec instead. IPSec requires a little more effort to configure but it has proven rock solid and cross-platform in several of my past projects. Having used Freeswan and Openswan before, I now decided to use Strongswan instead as it requires no kernel tweaks on Debian/Ubuntu making the installation a matter of minutes. (This is well documented on www.strongswan.org and I know you’re just here to read about the iPhone, so I won’t go into that now.
Making IPSec work with iPhone and OS/X’s native clients requires installing an L2TP daemon.
First the fairly standard Strongswan configuration:
/etc/ipsec.conf:
config setup
# crlcheckinterval=600
# strictcrlpolicy=yes
# cachecrls=yes
nat_traversal=yes
charonstart=yes
plutostart=yes
conn L2TP
authby=psk
pfs=no
rekey=no
type=tunnel
esp=aes128-sha1
ike=aes128-sha-modp1024
left=your.ip.goes.here
leftnexthop=%defaultroute
leftprotoport=17/1701
right=%any
rightprotoport=17/%any
rightsubnetwithin=0.0.0.0/0
auto=add
/etc/ipsec.secrets:
your.ip.goes.here %any: PSK "yoursharedkeygoeshere"
As you can see we’re enabling nat-traversal and transport mode at the same time. And that’s really the only ‘hack’ we need to do as it’s disabled by default.
On a Debian or Ubuntu system this should get you a long way:
apt-get install build-essential fakeroot dpkg-dev devscripts apt-get source strongswan apt-get install libcurl4-openssl-dev apt-get build-dep strongswan cd strongswan-4.2.4/ dch -i
Now edit debian/rules and change –disable-md5 –disable-sha1 –disable-sha2 to –disable-md5 –disable-sha1 –disable-sha2 –enable-nat-transport and continue:
dpkg-buildpackage -rfakeroot -uc -b dpkg -i ../strongswan_4.2.4-5ubuntu2_i386.deb /etc/init.d/ipsec restart
Alright. IPSec is good to go. Next the L2TP daemon for iPhone and OS/X:
apt-get install xl2tpd
/etc/xl2tpd/xl2tpd.conf:
[global] debug network = yes debug tunnel = yes [lns default] ip range = 10.0.0.200-10.0.0.254 local ip = 10.0.0.1 require chap = yes refuse pap = yes require authentication = yes name = NIELSPEEN.COM ppp debug = yes pppoptfile = /etc/ppp/options.xl2tpd length bit = yes
10.0.0.0/24 is your local LAN. 10.0.0.200-10.0.0.254 are IP addresses that we can freely assign to the users. 10.0.0.1 is a free IP on your local LAN. (It should not be the IP bound to your LAN interface!)
Note: you don’t need an actual LAN to make this work. In fact, the server I use the above config on is not connected to one.
/etc/xl2tpd/l2tp-secrets:
* * l2tppassworduser1 *
/etc/ppp/options.xl2tpd:
ipcp-accept-local ipcp-accept-remote ms-dns you.dns.ip.here noccp auth crtscts idle 1800 mtu 1410 mru 1410 nodefaultroute debug lock proxyarp connect-delay 5000

Great! Now to configure your iPhone:
If, like me, you’re not using this to hook your iPhone to your office network, but want to use the connection to access the Internet, you’ll need to add a masquerading rule to iptables:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
That’s it!
13 Apr
@kofai asked me to share my Fanfou to Twitter sync script. It’s not art, but it works, so here goes:
<?php define(STATUS_PATH, '/home/www/twitbridg/status/'); include_once('password.php'); $since_id = file_get_contents(STATUS_PATH.$twitter_username.'.last') OR $since_id = '1'; // The twitter API address $url = 'https://twitter.com/statuses/user_timeline/'.$twitter_username.'.xml?since_id='.$since_id; $curl_handle = curl_init(); curl_setopt($curl_handle, CURLOPT_URL, "$url"); curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl_handle, CURLOPT_GET, 1); $buffer = curl_exec($curl_handle); curl_close($curl_handle); if (empty($buffer)) die('failed to get tweets: '.$since_id."\n"); $xml = new SimpleXMLElement($buffer); $i = sizeof($xml->status)-1; if($i<0) exit; while($i >= 0) { // Update FanFou $url = 'http://api.fanfou.com/statuses/update.xml'; $curl_handle = curl_init(); curl_setopt($curl_handle, CURLOPT_URL, "$url"); curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl_handle, CURLOPT_POST, 1); curl_setopt($curl_handle, CURLOPT_POSTFIELDS, "source=".urlencode("<a href=\"http://twitter.com/".$twitter_username."\">Twitter</a>")."&status=".urlencode($xml->status[$i]->text)); curl_setopt($curl_handle, CURLOPT_USERPWD, "$fanfou_username:$fanfou_password"); $buffer = curl_exec($curl_handle); curl_close($curl_handle); $i--; } $last_id = $xml->status[0]->id; $fp = fopen(STATUS_PATH.$twitter_username.'.last', 'w'); fwrite($fp, $last_id); fclose($fp); ?>
As you can see it includes a password.php. This sets a few login variables. You can just insert them at the top of the above PHP file, but as I edit my code in public places I prefer not to do that.
<?php $twitter_username = 'nielspeen'; $fanfou_username = 'nielspeen'; $fanfou_password = '123xyz'; ?>
Enjoy!