summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/anwenderdoku.txt74
-rw-r--r--doc/entwicklerdoku.txt90
2 files changed, 82 insertions, 82 deletions
diff --git a/doc/anwenderdoku.txt b/doc/anwenderdoku.txt
index afff4d0..ebe73c2 100644
--- a/doc/anwenderdoku.txt
+++ b/doc/anwenderdoku.txt
@@ -17,11 +17,11 @@ des Programs siehe 'Entwicklerdokumentation'.
Ein DNS Tunnel ermöglicht regulären IP Verkehr durch den Internet
Namensauflösungsdienst DNS zu tunneln. Damit ist es möglich, in Netzen
die keine normales Internet Routing unterstützen, Daten auszutauschen.
-Voraussetzung ist, dass das Netz gewöhnliche DNS-Auflösung unterstützt.
+Voraussetzung ist, dass das Netz gewöhnliche DNS-Auflösung unterstützt.
Die Datenpakete werden in DNS-Anfragen kodiert, die durch die hierarchische
Struktur an einen speziellen (i.d.R. third-level) Nameserver weitergeleitet werden.
-Die Software <<iodine>> ist eine Implementierung eines DNS Tunnel für Linux,
+Die Software <<iodine>> ist eine Implementierung eines DNS Tunnel für Linux,
Mac OS X, FreeBSD, NetBSD, OpenBSD and Windows. Diese Dokumentation beschreibt
die Portierung auf Android mit einer angepassten Benutzeroberfläche.
--
@@ -38,7 +38,7 @@ http://code.kryo.se/iodine/iodine-latest-android.zip[cross-kompiliertes
iodine] auszuführen.
-
+
Funktionsweise eines DNS-Tunnel
-------------------------------
@@ -58,14 +58,14 @@ Einbetten von beliebigen Daten
Im folgenden ist der Datenverkehr zur Auflösung des Namens "bla.de" dekodiert dargestellt.
Das erste Paket ist die Anfrage des A-Record zu "bla.de". Das zweite Paket die Antwort des DNS Relay.
-Das DNS-Relay antwortet "bla.de A IN 217.160.95.28", diese Angabe soll "5 hours, 39 minutes,
+Das DNS-Relay antwortet "bla.de A IN 217.160.95.28", diese Angabe soll "5 hours, 39 minutes,
47 seconds" gültig sein. `217.160.95.28` wurde direkt binär übertragen als `d9 a0 5f 1c`.
Nichts hält einen DNS Server davon ab andere Daten als IP-Adressen in der Antwort zu verschicken und
nichts kann einen Client davon abhalten beliebige Daten in subdomains (hallowelt.bla.de) zu kodieren.
Aufgrund der hierarchischen Architektur von DNS kann der Inhaber einer Domains die Auflösung von
-Subdomains übernehmen. Nach RFC1035 ist die maximale Länge eines auflösbaren Namens 255 Zeichen.
+Subdomains übernehmen. Nach RFC1035 ist die maximale Länge eines auflösbaren Namens 255 Zeichen.
[source,c]
-------------------------------------------------------------------------------------------------------------
@@ -131,33 +131,33 @@ Gegenmaßnahmen
Die von einem idealen DNS Tunnel gestellten Anfragen sind gültig und unterscheiden sich
in erster Linie nicht von denen einer gewöhnlichen Anwendung von DNS. Um Tunnel
-aufzuspüren wären daher statistische Verfahren nötig die Kriterien wie Anzahl,
-Größe und Inhalt der Pakete betrachten. Aufgrund der Fehleranfälligkeit ist
-es damit aber auch möglich legitime Anwendungen zu blockieren.
+aufzuspüren wären daher statistische Verfahren nötig die Kriterien wie Anzahl,
+Größe und Inhalt der Pakete betrachten. Aufgrund der Fehleranfälligkeit ist
+es damit aber auch möglich legitime Anwendungen zu blockieren.
Möchte man lediglich iodine als konkrete Implementierung blockieren ist dies sehr einfach möglich.
Der vom iodine Client Verwendete "ping" Aufruf kann sehr einfach erkannt werden, es könnte jeder Client
der regelmäßíg eine Subdomain mit dem Anfangsbuchstaben "p" der gleichen Restdomain erfragt geblockt werden.
-In einem durch Proxy Server sowieso schon stark eingeschränkten Netzwerk ist es denkbar, dass auf die Auflösung von
-Namen ausserhalb der lokalen Domain durch den DNS Server allgemein verzichtet wird.
+In einem durch Proxy Server sowieso schon stark eingeschränkten Netzwerk ist es denkbar, dass auf die Auflösung von
+Namen ausserhalb der lokalen Domain durch den DNS Server allgemein verzichtet wird.
Sowohl ein HTTP-Proxyserver als auch ein SOCKS Server kann dies für
den Client übernehmen.
In einer Konfiguration für einen Internet Hotspot mit Autorisation der Benutzer (z.B. nach Bezahlvorgang) ist
es unbedingt sinnvoll die Autoriserungsregeln auch auf den DNS Server anzuwenden, sodass für den nicht autorisierten
Benutzer nur das Loginformular aufrufbar ist. Dies in vielen öffentlichen Hotspots momentan nicht umgesetzt.
-Für weitere Informationen zum Blockieren von DNS Tunneln siehe <<schillinger11>>.
-
+Für weitere Informationen zum Blockieren von DNS Tunneln siehe <<schillinger11>>.
+
Bedienung
---------
Im folgenden wird die Bedienung der Android Oberfläche beschrieben. Die Anwendungen
-teilt sich für den Benutzer in zwei Bereiche: Die Steuerung der Tunnel und die
+teilt sich für den Benutzer in zwei Bereiche: Die Steuerung der Tunnel und die
Verbindungskonfiguration.
-
+
Hauptbildschirm
~~~~~~~~~~~~~~~
@@ -165,10 +165,10 @@ unfloat::[]
image::bilder/screen_main.png[width="300px",scaledwidth="50%",float="left"]
-Der Hauptbildschirm zeigt die konfigurierten Verbindungsprofile. Eine Verbindung wird
+Der Hauptbildschirm zeigt die konfigurierten Verbindungsprofile. Eine Verbindung wird
mit Auswahl des Eintrags gestartet.
-Mit dem Einstellungsbutton image:../res/drawable/ic_bt_config.png[width="32px"] können
+Mit dem Einstellungsbutton image:../res/drawable/ic_bt_config.png[width="32px"] können
die Verbindungsparameter geändert werden.
Mit dem Button image:../res/drawable/device_access_new_account.png[width="32px"] in der ActionBar
@@ -183,14 +183,14 @@ unfloat::[]
image::bilder/screen_pref.png[width="300px",scaledwidth="50%",float="left"]
-In der Verbindungskonfiguration werden Parameter festgelegt die beim Starten
+In der Verbindungskonfiguration werden Parameter festgelegt die beim Starten
des Tunnels gesetzt werden. Die Änderungen werden sofort übernommen.
-Zu jeder Einstellung kann mit Drücken des Hilfebuttons die Hilfe aus der Nachfolgenden
+Zu jeder Einstellung kann mit Drücken des Hilfebuttons die Hilfe aus der Nachfolgenden
Tabelle aufgerufen werden.
Mit mit der Auswahl von image:../res/drawable/delete.png[width="32px"] wird
-die aktuell geöffnete Konfiguration gelöscht.
+die aktuell geöffnete Konfiguration gelöscht.
unfloat::[]
@@ -199,26 +199,26 @@ unfloat::[]
|=====================================
|Parameter | Beschreibung
|Name | Name für diese Verbindungskonfiguration<
-|Lazy-Mode | Lazy mode erhöht den Durchsatz und senkt die Reaktionszeit.
- Eine kleine Minderheit an DNS Relays scheint damit nicht klarzukommen was
- darin resultiert dass keine oder fast keine Daten übertragen werden.
- Der Client wird dies aber in der Regel feststellen und den Lazy mode ausschalten.
+|Lazy-Mode | Lazy mode erhöht den Durchsatz und senkt die Reaktionszeit.
+ Eine kleine Minderheit an DNS Relays scheint damit nicht klarzukommen was
+ darin resultiert dass keine oder fast keine Daten übertragen werden.
+ Der Client wird dies aber in der Regel feststellen und den Lazy mode ausschalten.
Falls nicht, kann lazy-mode mit dieser Option ausgeschaltet werden.
-|Tunnel Nameserver | Der Nameserver/DNS Relay, der verwendet wird um mit iodined zu kommunizieren.
- Dieses Feld ist optional und wenn es nicht gesetzt ist wird der im System hinterlegte
+|Tunnel Nameserver | Der Nameserver/DNS Relay, der verwendet wird um mit iodined zu kommunizieren.
+ Dieses Feld ist optional und wenn es nicht gesetzt ist wird der im System hinterlegte
DNS Server verwendet
|Nameserver-Mode | Legt fest wie der Nameserver gesetzt werden soll nachdem der Tunnel aufgebaut wurde
-|Nameserver | IP-Adresse eine speziellen Nameserver der gesetzt werden soll
+|Nameserver | IP-Adresse eine speziellen Nameserver der gesetzt werden soll
wenn Nameserver Modus = Custom ist.
|Password | Dieses Feld ist optional. Es werden nur die ersten 32 Zeichen verwendet.
pwasswo cont
|Raw-Mode | Falls gesetzt wird iodine versuchen die öffentliche IP-Adresse des iodined Server
- aufzulösen und testen ob er direkt erreichbar ist. Falls ja, wird er den Traffic
+ aufzulösen und testen ob er direkt erreichbar ist. Falls ja, wird er den Traffic
direkt an den Server senden anstatt an ein DNS relay
|Request-Type | Typ der DNS Abfragen. Standardmäßig wird die beste Request type automatisch ausgewählt.
-|Top-Domain | Der DNS Traffic wird als Anfragen für subdomains unterhalb dieser Topdomain gesendert.
- Dies ist gewöhnlich eine Domain die Dir gehört. Verwende eine kurze
- Domain um mehr Durchsatz zu erzielen.
+|Top-Domain | Der DNS Traffic wird als Anfragen für subdomains unterhalb dieser Topdomain gesendert.
+ Dies ist gewöhnlich eine Domain die Dir gehört. Verwende eine kurze
+ Domain um mehr Durchsatz zu erzielen.
Diese Einstellung muss am Server und am Client gleich sein
|Default Route | Legt fest ob die Default Route gesetzt wird nachdem die Verbindung aufgebaut wurde
|====================================
@@ -240,11 +240,11 @@ vom iodine Server, aus einem IP Subnetz das beim Start festgelegt wird, zugewies
iodined -c -P PASSWORD 192.168.0.1/24 t.example.com
Die Option `-c` ist nicht immer erforderlich. Sie bewirkt, dass iodine die Quelladressen der Anfragen
-nicht überprüft. Die Überprüfung ist nicht möglich wenn die DNS Anfragen über ein Cluster verarbeitet werden,
-sodass die beim Server einkommenden Pakete von verschiedenen Quelladressen stammen.
+nicht überprüft. Die Überprüfung ist nicht möglich wenn die DNS Anfragen über ein Cluster verarbeitet werden,
+sodass die beim Server einkommenden Pakete von verschiedenen Quelladressen stammen.
Der Server legt ein TUN-Device an (typischerweise "dns0"), je nach Zweck ist noch das
-IP Routing/Masquerade zu konfigurieren.
+IP Routing/Masquerade zu konfigurieren.
Testen
~~~~~~
@@ -261,9 +261,9 @@ $ dig -t A zabc.t.example.com
;; ANSWER SECTION:
zabc.t.example.com. 0 IN CNAME hpjqweyzo.dh.
-$ ./base32 d pjqweyz
+$ ./base32 d pjqweyz
Decoded 4 bytes:
-0x7a (z) 0x61 (a) 0x62 (b) 0x63 (c)
+0x7a (z) 0x61 (a) 0x62 (b) 0x63 (c)
--------------------------------------------------------------------------------------------------------
Unter http://code.kryo.se/iodine/check-it/ wird ein Online Service zum Testen der Konfiguration angeboten.
@@ -273,7 +273,7 @@ Anhang
------
[bibliography]
-- [[[schillinger11]]]
- http://www.data.ks.uni-freiburg.de/download/praxisseminarSS11/dns-tunnel/Fabian%20Schillinger%20-%20DNS-Tunnel.pdf[Fabian Schillinger, DNS-Tunnel, Universität Freiburg 2011]
+- [[[schillinger11]]]
+ http://www.data.ks.uni-freiburg.de/download/praxisseminarSS11/dns-tunnel/Fabian%20Schillinger%20-%20DNS-Tunnel.pdf[Fabian Schillinger, DNS-Tunnel, Universität Freiburg 2011]
- [[[iodine]]] http://code.kryo.se/iodine/
diff --git a/doc/entwicklerdoku.txt b/doc/entwicklerdoku.txt
index ce92eeb..b39f3b4 100644
--- a/doc/entwicklerdoku.txt
+++ b/doc/entwicklerdoku.txt
@@ -10,7 +10,7 @@ April 2013
[abstract]
--
Die Dokumentation ist zweigeteilt. Dieser Teil enthält eine technische Beschreibung.
-Die Bedienung und Funktionsweise ist in der 'Anwenderdokumentation' beschrieben.
+Die Bedienung und Funktionsweise ist in der 'Anwenderdokumentation' beschrieben.
--
Aufbau
@@ -48,7 +48,7 @@ Konfiguration
~~~~~~~~~~~~~
Die Tunnelkonfigurationen werden in einer SQLite Datenbank abgelegt. Es
existiert mit `.config.IodineConfiguration` ein leichtgewichtiger Proxy
-um die Android `ContentValues` Klasse. Die `.config.ConfigDatabase` Klasse
+um die Android `ContentValues` Klasse. Die `.config.ConfigDatabase` Klasse
ist ein `SQLiteOpenHelper` und kann mehrfach instanziert werden.
VPN-Service
@@ -58,11 +58,11 @@ Der VPN Service hat 5 Zustände die er über Broadcast Intents mitteilt.
Eine solche Mitteilung wird verschickt wenn sich der Zustand ändert oder
dies über ACTION_CONTROL_UPDATE angefordert wurde.
-Die Kommunikation der Oberfläche mit dem VPN Service erfolgt mit Broadcasts Intents.
+Die Kommunikation der Oberfläche mit dem VPN Service erfolgt mit Broadcasts Intents.
<<whiteboard-intents>> zeigt die Zustände des Iodine VPN-Service. Rot nummeriert sind die
Intents die der Service verschickt um über Statusänderungen zu informieren. Blau nummeriert
-sind Intents mit denen der Service gesteuert werden kann.
+sind Intents mit denen der Service gesteuert werden kann.
[[whiteboard-intents]]
.Status Informations und Steuerungs Intents des VPN Service
@@ -72,10 +72,10 @@ JNI
~~~
Die JNI Methoden für iodine befinden sich in der Klasse `.IodineClient`
-bzw. `/jni/iodine-client.c`. `IodineClient#connect` ersetzt dabei prinzipiell
+bzw. `/jni/iodine-client.c`. `IodineClient#connect` ersetzt dabei prinzipiell
die `main()` des ursprünglichen iodine Client.
-Weitere Methoden dienen dem Austausch der vom Server übermittelten Konfiguration
+Weitere Methoden dienen dem Austausch der vom Server übermittelten Konfiguration
und des im System eingestellten DNS Server.
@@ -150,7 +150,7 @@ Nachdem vom Server die IP-Konfiguration mitgeteilt wurde, wird diese im
int tun_fd = parcelFD.detachFd();
// pass the filedescriptor to iodine
- IodineClient.tunnel(tun_fd);
+ IodineClient.tunnel(tun_fd);
--------------------------------------------------------
iodine
@@ -162,7 +162,7 @@ Der folgende Text zeigt ein Beispiel für den Ablauf eines Handshake. Der genaue
variieren jenachdem wie die Verbindungsparameter gewählt werden.
Hier sind gewählt -m 768 fragment size und ein 9 Zeichen
-Passwort. Die Gegenstelle ist `t.yves.tw`. Eine Raw (direkte UDP) Verbindung
+Passwort. Die Gegenstelle ist `t.yves.tw`. Eine Raw (direkte UDP) Verbindung
wurde verhindert indem der Rechner zum Testzeitpunkt keine default Route hatte.
RX/TX aus der Sicht des Servers. Die "*" in den Hostnamen markieren Zeichen die
@@ -171,18 +171,18 @@ sich aus Random Daten ergeben.
[source,java]
---------------------------------------------------------------------
== Der Client testet die Qualitaet der Uebertragung
- <-- client.c:handshake_qtype_autodetect()
- -> handshake_qtypetest()
+ <-- client.c:handshake_qtype_autodetect()
+ -> handshake_qtypetest()
-> send_downenctest()
hostname[0] = "y"
hostanme[1] = downenc = 'r'
hostname[2] = variant = 1 = 'b' (b32)
hostname[3..5] = rand_seed++
RX: yrb***.t.yves.tw
-
+
--> 48 bytes aus encoding.h:DOWNCODECHECK
TX: yrb***.t.yves.tw, 48 bytes data
-
+
== Austausch der Versionsinformationen
<-- client.c:send_version()
VERSION=0x00 00 05 02
@@ -190,7 +190,7 @@ sich aus Random Daten ergeben.
hostname[1..6] = b32(0,0,5,2,random<<8,random)
hostname = "vAAAAKAR__"
RX: vaaaaka****.t.yves.tw
-
+
--> iodined.c:send_version_response()
der Server bestaetigt mit
data[0..8] = "VACK" b32(seed>>24, seed>>16, seed>>8, seed, userid)
@@ -206,7 +206,7 @@ sich aus Random Daten ergeben.
--> iodined.c:handle_null_request()
Sendet bei Erfolg die IP Einstellungen wie
- "172.16.0.1-172.16.0.2-1130-16"
+ "172.16.0.1-172.16.0.2-1130-16"
server="172.16.0.1"
client="172.16.0.2"
mtu=1130
@@ -214,11 +214,11 @@ sich aus Random Daten ergeben.
TX: lad24srn4ezmg21qjsfy13msagd0srfq.t.yves.tw
= 3137322e31362e302e312d3137322e31362e302e322d313133302d3136 (_16)
= 172.16.0.1-172.16.0.2-1130-16
-
+
== Senden der IP Adresse des Clients
<-- Request for IP address
RX: iamin.t.yves.tw
-
+
--> iodined.c:handle_null_request()
addr = externe IP Adresse des Server (-n Switch)
reply[0] = 'I';
@@ -228,28 +228,28 @@ sich aus Random Daten ergeben.
reply[4] = (addr >> 0) & 0xFF;
TX: iamin.t.yves.tw
= 494e2f737d (_16)
-
+
== Testen auf EDNS Erweiterung
<-- client.c:handshake_edns0_check()
-> send_downenctest()
- downenc = 'r' fuer T_NULL 't'
+ downenc = 'r' fuer T_NULL 't'
variant = 1 = 'b' (b32)
data[0..5] = "y" downenc variant rand_seed[0..2]
RX: yrb***.t.yves.tw
-
- --> iodined.c:handle_null_login() : 937
- -> write_dns( type='R')
+
+ --> iodined.c:handle_null_login() : 937
+ -> write_dns( type='R')
Der Server antwortet mit 48 bytes aus encoding.h:DOWNCODECHECK
TX: yrb***.t.yves.tw, 48 bytes data
-
-
+
+
== Testen der Kodierungen mit verschiedenen Patterns
<-- client.c:handshake_upenc_autodetect()
In den folgenden Tests testet der Client ob mit Base128
kodierte Nachrichten vom DNS Relay korrekt verarbeitet werden.
-
+
--> Der Server schickt die Patterns einfach wieder zurueck.
-
+
== Client legt Kodierung fest, Server bestaetigt
<-- client.c:handshake_switch_codec()
hostname[0] = command 's'
@@ -258,25 +258,25 @@ sich aus Random Daten ergeben.
hostname[3..5] = rand_seed++
rand_seed++;
RX: sahmiut.yves.tw
-
+
--> iodined.c:840
Schreibt den Namen des ausgewaehlten Codecs:
data="Base128" (kein encoding!)
- TX: sahmiut.yves.tw, 7 bytes of data
-
- == Anschalten lazy mode (an: Server beantwortet Anfragen nicht sofort)
+ TX: sahmiut.yves.tw, 7 bytes of data
+
+ == Anschalten lazy mode (an: Server beantwortet Anfragen nicht sofort)
<-- client.c:send_lazy_switch()
hostname[0] = 'o'
hostname[1] = b32(userid) = 'a'
hostname[2] = 'l' fuer lazy mode oder 'i'
hostname[3..5] = rand_seed++
RX: oalmiv.t.yves.tw
-
+
--> iodined.c:919
data="Lazy" (kein encoding!)
TX: oalmiv.t.yves.tw, 4 bytes of data
-
- ==
+
+ ==
<-- client.c:send_set_downstream_fragsize()
data[0] = userid;
data[1] = (fragsize & 0xff00) >> 8;
@@ -288,16 +288,16 @@ sich aus Random Daten ergeben.
--> iodined.c:1042
bestaetigt empfangene Framesize durch Wiederholung
-
- == Regelmaesige pings fragen den Server nach anstehenden Daten ab
+
+ == Regelmaesige pings fragen den Server nach anstehenden Daten ab
<-- client.c:send_ping()
data[0] = userid;
data[1] = ((inpkt.seqno & 7) << 4) | (inpkt.fragment & 15);
data[2] = (rand_seed >> 8) & 0xff;
data[3] = (rand_seed >> 0) & 0xff;
- hostname = 'p' + b32(data)
+ hostname = 'p' + b32(data)
RX: paaalcfy.t.yves.tw
-
+
--> iodined.c:1067
Der Server nutzt die regelmaessigen Pings um Daten an den Client zu liefern.
---------------------------------------------------------------------
@@ -305,16 +305,16 @@ sich aus Random Daten ergeben.
Der lazy Modus
^^^^^^^^^^^^^^
-Wie in der Anwenderdokumentation beschrieben erhöht der Lazy Modus den Durchsatz
+Wie in der Anwenderdokumentation beschrieben erhöht der Lazy Modus den Durchsatz
und senkt die Latenzzeit, wird aber nicht von allen DNS-Relays unterstützt.
Lazy bezieht sich auf das Verhalten des Servers. Der Server wird im Lazy-mode
alle Antworten auf Anfragen solange zurückhalten bis er neue Daten für den
Client erhalten hat. Im Idealfall also bis das Antwortpaket der getunnelten
-IP Verbindung angekommen ist.
+IP Verbindung angekommen ist.
Diese Verzögerung kann mit manchen DNS-Relays Probleme machen. Der Server kann dies jedoch
-anhand der Duplikate in den Anfragen erkennen und damit den lazy-mode ausschalten.
+anhand der Duplikate in den Anfragen erkennen und damit den lazy-mode ausschalten.
Ohne diesen Mechanismus müsste der Client jedoch viel häufiger nach neuen Daten
pollen (vgl. HTTP Long polling in Comet oder BOSH).
@@ -343,15 +343,15 @@ int main(int argc, char *argv[]) {
if (*argv[1] == 'd') {
int r = b32->decode(buf, &len, argv[2], strlen(argv[2]));
int i;
- printf("Decoded %d bytes:\n", r);
+ printf("Decoded %d bytes:\n", r);
for (i = 0; i< r; i++) {
printf("0x%02hhx (%c) ", buf[i], (buf[i] >= '0' && buf[i] <= 'z') ? buf[i] : ' ');
- }
+ }
printf("\n");
} else if (*argv[1] == 'e') {
int r = b32->encode(buf, &len, argv[2], strlen(argv[2]));
printf("Encoded %d bytes in %ld output bytes: >%s<\n", len, r, buf);
- }
+ }
return 0;
}
----------------------------------------------------------------------------------------------------
@@ -375,7 +375,7 @@ sondern 'Bionic libc'. Dies ist eine besonders kleine, auf die BSD libc zurückg
standard C Library. Es fehlen einige Features der glibc wie wide-character support,
volle POSIX Thread Unterstützung oder locale Unterstützung. Das Ziel von Bionic ist
nicht eine vollständige C Standardbibliothek sondern lediglich eine schlanke Implementierung
-aller für ein Android nötigen Funktionen.
+aller für ein Android nötigen Funktionen.
Im einfachsten Fall scheitert die Ausführung von iodine unter Android an einem `system()` Aufruf
mit dem iodine die IP-Konfiguration anwendet.
@@ -393,7 +393,7 @@ C-Quellen angestossen werden.
org.xapek.andiodine % ~/$NDK_ROOT/ndk-build clean
Clean: iodine-client [armeabi]
Clean: stdc++ [armeabi]
-org.xapek.andiodine % ~/$NDK_ROOT/ndk-build
+org.xapek.andiodine % ~/$NDK_ROOT/ndk-build
Compile thumb : iodine-client <= iodine-client.c
Compile thumb : iodine-client <= tun.c
Compile thumb : iodine-client <= dns.c
@@ -530,7 +530,7 @@ Anhang
------
[bibliography]
-- [[[vpnapi]]]
+- [[[vpnapi]]]
http://developer.android.com/reference/android/net/VpnService.html Dokumentation
zu den Android VPN Service API