Probleem

Ik wil overal ter wereld mijn mail kunnen lezen, die via IMAPS door mijn mailserver beschikbaar wordt gesteld. Nu kan ik poort 993 open zetten voor de hele wereld, maar dat is ook weer zo... open :)

Oplossing

Op mijn FreeBSD firewall, die voorzien is van PF van OpenBSD, maak ik een regel aan die alleen toegang geeft aan iemand met een iPhone. PF heeft een prachtige optie, 'Passive Operating System Fingerprinting', die dit mogelijk maakt.

Uitwerking

Bij PF wordt een pf.os bestand meegeleverd die door pf gesourced wordt bij het starten. In dit bestand staan de bekende OS fingerprints. Helaas staat hier geen iPhone, dus moet ik eerst de fingerprint van mijn iPhone uitzoeken. De manualpage van pf.os beschrijft hoe een fingerprint wordt opgebouwd en leert mij ook dat ik met de opdracht tcpdump -s128 -nv 'tcp[13] == 2' and port 993 de gevraagde informatie zichtbaar kan maken. Door vanaf mijn iPhone de mail op te halen, kreeg ik de volgende output:

14:08:10.048578 IP (tos 0x20, ttl 48, id 61345, offset 0, flags [DF], proto TCP (6), length 64) xx.xx.xx.xx.7854 > xx.xx.xx.xx.993: S, cksum 0x15c7 (correct), 1069626058:1069626058(0) win 65535 <mss 1360,nop,wscale 2,nop,nop,timestamp 840340694 0,sackOK,eol>

Volgens de pf.os manpage moet ik hier de volgende velden uit kunnen halen:

window: The TCP window size.
TTL: The IP time to live.
df: The presence of the IPv4 don't fragment bit.
packet size: The size of the initial TCP packet.
TCP options: An ordered list of the TCP options.

Om de fingerprint compleet te maken, moet ik er dan zelf nog de volgende informatie aan toevoegen:

class: The class of operating system.
version: The version of the operating system.
subtype: The subtype of patchlevel of the operating system.
description: The overall textual description of the operating system, version and subtype.

Nu ik alle informatie beschikbaar had, kon ik daar de volgende regel voor in het bestand pf.os van maken:

65535:48:1:64:M1360:Darwin iPhone:10.0.0d3::iPhone 3.1.2

Nadat ik deze had toegevoegd werd met pfctl -s osfp duidelijk dat ik dan moest gaan filteren op Darwin iPhone. In mijn firewall staan nu dus de volgende regels voor IMAPS

rdr on $ext_if proto tcp from any to any port 993 -> $mailserver port 993
pass in on $ext_if proto tcp from any os "Darwin iPhone   10.0.0d3" to $mailserver port 993 flags S/SA keep state

Ik ben mij er van bewust dat ik op deze manier alle iPhone's met firmware 3.1.2 toegang geef tot mijn IMAPS server, maar dat is voor mij een geaccepteerd risico. Uiteraard dien ik ook bij een firmware upgrade te controleren of de fingerprint gewijzigd is.

Update 29-12-2009
Helaas bleek deze vorm van filtering toch niet stabiel. De ene keer werkte het wel, de andere keer ineens weer niet. Ik heb er inmiddels vele uren ingestoken om uit te zoeken wat er nu precies fout gaat, maar tot nu toe heb ik het helaas niet voor elkaar gekregen. Ik heb daarom ook besloten om te stoppen met zoeken en de draad weer op te pakken na een upgrade van mijn firewall.