| 1 | |
|---|
| 2 | iodine - http://code.kryo.se/iodine |
|---|
| 3 | |
|---|
| 4 | *********************************** |
|---|
| 5 | |
|---|
| 6 | This is a piece of software that lets you tunnel IPv4 data through a DNS |
|---|
| 7 | server. This can be usable in different situations where internet access is |
|---|
| 8 | firewalled, but DNS queries are allowed. |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | QUICKSTART: |
|---|
| 12 | |
|---|
| 13 | Try it out within your own LAN! Follow these simple steps: |
|---|
| 14 | - On your server, run: ./iodined -f 10.0.0.1 test.com |
|---|
| 15 | (If you already use the 10.0.0.0 network, use another internal net like |
|---|
| 16 | 172.16.0.0) |
|---|
| 17 | - Enter a password |
|---|
| 18 | - On the client, run: ./iodine -f -r 192.168.0.1 test.com |
|---|
| 19 | (Replace 192.168.0.1 with your server's ip address) |
|---|
| 20 | - Enter the same password |
|---|
| 21 | - Now the client has the tunnel ip 10.0.0.2 and the server has 10.0.0.1 |
|---|
| 22 | - Try pinging each other through the tunnel |
|---|
| 23 | - Done! :) |
|---|
| 24 | To actually use it through a relaying nameserver, see below. |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | HOW TO USE: |
|---|
| 28 | |
|---|
| 29 | Note: server and client are required to speak the exact same protocol. In most |
|---|
| 30 | cases, this means running the same iodine version. Unfortunately, implementing |
|---|
| 31 | backward and forward protocol compatibility is usually not feasible. |
|---|
| 32 | |
|---|
| 33 | Server side: |
|---|
| 34 | To use this tunnel, you need control over a real domain (like mydomain.com), |
|---|
| 35 | and a server with a public IP address to run iodined on. If this server |
|---|
| 36 | already runs a DNS program, change its listening port and then use iodined's |
|---|
| 37 | -b option to let iodined forward the DNS requests. (Note that this procedure |
|---|
| 38 | is not advised in production environments, because iodined's DNS forwarding |
|---|
| 39 | is not completely transparent.) |
|---|
| 40 | |
|---|
| 41 | Then, delegate a subdomain (say, t1.mydomain.com) to the iodined server. |
|---|
| 42 | If you use BIND for your domain, add two lines like these to the zone file: |
|---|
| 43 | |
|---|
| 44 | t1 IN NS t1ns.mydomain.com. ; note the dot! |
|---|
| 45 | t1ns IN A 10.15.213.99 |
|---|
| 46 | |
|---|
| 47 | The "NS" line is all that's needed to route queries for the "t1" subdomain |
|---|
| 48 | to the "t1ns" server. We use a short name for the subdomain, to keep as much |
|---|
| 49 | space as possible available for the data traffic. At the end of the "NS" line |
|---|
| 50 | is the name of your iodined server. This can be any name, pointing anywhere, |
|---|
| 51 | but in this case it's easily kept in the same zone file. It must be a name |
|---|
| 52 | (not an IP address), and that name itself must have an A record (not a CNAME). |
|---|
| 53 | |
|---|
| 54 | If your iodined server has a dynamic IP, use a dynamic dns provider. Simply |
|---|
| 55 | point the "NS" line to it, and leave the "A" line out: |
|---|
| 56 | |
|---|
| 57 | t1 IN NS myname.mydyndnsprovider.com. ; note the dot! |
|---|
| 58 | |
|---|
| 59 | Then reload or restart your nameserver program. Now any DNS queries for |
|---|
| 60 | domains ending in t1.mydomain.com will be sent to your iodined server. |
|---|
| 61 | |
|---|
| 62 | Finally start iodined on your server. The first argument is the IP address |
|---|
| 63 | inside the tunnel, which can be from any range that you don't use yet (for |
|---|
| 64 | example 192.168.99.1), and the second argument is the assigned domain (in this |
|---|
| 65 | case t1.mydomain.com). Using the -f option will keep iodined running in the |
|---|
| 66 | foreground, which helps when testing. iodined will open a virtual interface |
|---|
| 67 | ("tun device"), and will also start listening for DNS queries on UDP port 53. |
|---|
| 68 | Either enter a password on the commandline (-P pass) or after the server has |
|---|
| 69 | started. Now everything is ready for the client. |
|---|
| 70 | |
|---|
| 71 | If there is a chance you'll be using an iodine tunnel from unexpected |
|---|
| 72 | environments, start iodined with a -c option. |
|---|
| 73 | |
|---|
| 74 | Resulting commandline in this example situation: |
|---|
| 75 | ./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com |
|---|
| 76 | |
|---|
| 77 | Client side: |
|---|
| 78 | All the setup is done, just start iodine. It takes one or two arguments, the |
|---|
| 79 | first is the local relaying DNS server (optional) and the second is the domain |
|---|
| 80 | you used (t1.mydomain.com). If you don't specify the first argument, the |
|---|
| 81 | system's current DNS setting will be consulted. |
|---|
| 82 | |
|---|
| 83 | If DNS queries are allowed to any computer, you can directly give the iodined |
|---|
| 84 | server's address as first argument (in the example: t1ns.mydomain.com or |
|---|
| 85 | 10.15.213.99). In that case, it may also happen that _any_ traffic is allowed |
|---|
| 86 | to the DNS port (53 UDP) of any computer. Iodine will detect this, and switch |
|---|
| 87 | to raw UDP tunneling if possible. To force DNS tunneling in any case, use the |
|---|
| 88 | -r option (especially useful when testing within your own network). |
|---|
| 89 | |
|---|
| 90 | The client's tunnel interface will get an IP close to the server's (in this |
|---|
| 91 | case 192.168.99.2 or .3 etc.) and a suitable MTU. Enter the same password as |
|---|
| 92 | on the server either as commandline option or after the client has started. |
|---|
| 93 | Using the -f option will keep the iodine client running in the foreground. |
|---|
| 94 | |
|---|
| 95 | Resulting commandline in this example situation: |
|---|
| 96 | ./iodine -f -P secretpassword t1.mydomain.com |
|---|
| 97 | (add -r to force DNS tunneling even if raw UDP tunneling would be possible) |
|---|
| 98 | |
|---|
| 99 | From either side, you should now be able to ping the IP address on the other |
|---|
| 100 | end of the tunnel. In this case, ping 192.168.99.1 from the iodine client, and |
|---|
| 101 | 192.168.99.2 or .3 etc. from the iodine server. |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | MISC. INFO: |
|---|
| 105 | |
|---|
| 106 | Routing: |
|---|
| 107 | It is possible to route all traffic through the DNS tunnel. To do this, first |
|---|
| 108 | add a host route to the nameserver used by iodine over the wired/wireless |
|---|
| 109 | interface with the default gateway as gateway. Then replace the default |
|---|
| 110 | gateway with the iodined server's IP address inside the DNS tunnel, and |
|---|
| 111 | configure the server to do NAT. |
|---|
| 112 | |
|---|
| 113 | However, note that the tunneled data traffic is not encrypted at all, and can |
|---|
| 114 | be read and changed by external parties relatively easily. For maximum |
|---|
| 115 | security, run a VPN through the DNS tunnel (=double tunneling), or use secure |
|---|
| 116 | shell (SSH) access, possibly with port forwarding. The latter can also be used |
|---|
| 117 | for web browsing, when you run a web proxy (for example Privoxy) on your |
|---|
| 118 | server. |
|---|
| 119 | |
|---|
| 120 | Testing: |
|---|
| 121 | The iodined server replies to NS requests sent for subdomains of the tunnel |
|---|
| 122 | domain. If your iodined subdomain is t1.mydomain.com, send a NS request for |
|---|
| 123 | foo123.t1.mydomain.com to see if the delegation works. dig is a good tool |
|---|
| 124 | for this: |
|---|
| 125 | dig -t NS foo123.t1.mydomain.com |
|---|
| 126 | |
|---|
| 127 | Also, the iodined server will answer requests starting with 'z' for any of the |
|---|
| 128 | supported request types, for example: |
|---|
| 129 | dig -t TXT z456.t1.mydomain.com |
|---|
| 130 | dig -t SRV z456.t1.mydomain.com |
|---|
| 131 | dig -t CNAME z456.t1.mydomain.com |
|---|
| 132 | The reply should look like garbled text in all these cases. |
|---|
| 133 | |
|---|
| 134 | Operational info: |
|---|
| 135 | The DNS-response fragment size is normally autoprobed to get maximum bandwidth. |
|---|
| 136 | To force a specific value (and speed things up), use the -m option. |
|---|
| 137 | |
|---|
| 138 | The DNS hostnames are normally used up to their maximum length, 255 characters. |
|---|
| 139 | Some DNS relays have been found that answer full-length queries rather |
|---|
| 140 | unreliably, giving widely varying (and mostly very bad) results of the |
|---|
| 141 | fragment size autoprobe on repeated tries. In these cases, use the -M switch |
|---|
| 142 | to reduce the DNS hostname length to for example 200 characters, which makes |
|---|
| 143 | these DNS relays much more stable. This is also useful on some "de-optimizing" |
|---|
| 144 | DNS relays that stuff the response with two full copies of the query, leaving |
|---|
| 145 | very little space for downstream data (also not capable of EDNS0). The -M |
|---|
| 146 | switch can trade some upstream bandwidth for downstream bandwidth. Note that |
|---|
| 147 | the minimum -M value is about 100, since the protocol can split packets (1200 |
|---|
| 148 | bytes max) in only 16 fragments, requiring at least 75 real data bytes per |
|---|
| 149 | fragment. |
|---|
| 150 | |
|---|
| 151 | The upstream data is sent gzipped encoded with Base32; or Base64 if the relay |
|---|
| 152 | server supports mixed case and '+' in domain names; or Base64u if '_' is |
|---|
| 153 | supported instead; or Base128 if high-byte-value characters are supported. |
|---|
| 154 | This upstream encoding is autodetected. The DNS protocol allows one query per |
|---|
| 155 | packet, and one query can be max 256 chars. Each domain name part can be max |
|---|
| 156 | 63 chars. So your domain name and subdomain should be as short as possible to |
|---|
| 157 | allow maximum upstream throughput. |
|---|
| 158 | |
|---|
| 159 | Several DNS request types are supported, with the NULL type expected to provide |
|---|
| 160 | the largest downstream bandwidth. Other available types are TXT, SRV, MX, |
|---|
| 161 | CNAME and A (returning CNAME), in decreasing bandwidth order. Normally the |
|---|
| 162 | "best" request type is autodetected and used. However, DNS relays may impose |
|---|
| 163 | limits on for example NULL and TXT, making SRV or MX actually the best choice. |
|---|
| 164 | This is not autodetected, but can be forced using the -T option. It is |
|---|
| 165 | advisable to try various alternatives especially when the autodetected request |
|---|
| 166 | type provides a downstream fragment size of less than 200 bytes. |
|---|
| 167 | |
|---|
| 168 | Note that SRV, MX and A (returning CNAME) queries may/will cause additional |
|---|
| 169 | lookups by "smart" caching nameservers to get an actual IP address, which may |
|---|
| 170 | either slow down or fail completely. |
|---|
| 171 | |
|---|
| 172 | DNS responses for non-NULL queries can be encoded with the same set of codecs |
|---|
| 173 | as upstream data. This is normally also autodetected, but no fully exhaustive |
|---|
| 174 | tests are done, so some problems may not be noticed when selecting more |
|---|
| 175 | advanced codecs. In that case, you'll see failures/corruption in the fragment |
|---|
| 176 | size autoprobe. In particular, several DNS relays have been found that change |
|---|
| 177 | replies returning hostnames (SRV, MX, CNAME, A) to lowercase only when that |
|---|
| 178 | hostname exceeds ca. 180 characters. In these and similar cases, use the -O |
|---|
| 179 | option to try other downstream codecs; Base32 should always work. |
|---|
| 180 | |
|---|
| 181 | Normal operation now is for the server to _not_ answer a DNS request until |
|---|
| 182 | the next DNS request has come in, a.k.a. being "lazy". This way, the server |
|---|
| 183 | will always have a DNS request handy when new downstream data has to be sent. |
|---|
| 184 | This greatly improves (interactive) performance and latency, and allows to |
|---|
| 185 | slow down the quiescent ping requests to 4 second intervals by default, and |
|---|
| 186 | possibly much slower. In fact, the main purpose of the pings now is to force |
|---|
| 187 | a reply to the previous ping, and prevent DNS server timeouts (usually at |
|---|
| 188 | least 5-10 seconds per RFC1035). Some DNS servers are more impatient and will |
|---|
| 189 | give SERVFAIL errors (timeouts) in periods without tunneled data traffic. All |
|---|
| 190 | data should still get through in these cases, but iodine will reduce the ping |
|---|
| 191 | interval to 1 second anyway (-I1) to reduce the number of error messages. This |
|---|
| 192 | may not help for very impatient DNS relays like dnsadvantage.com (ultradns), |
|---|
| 193 | which time out in 1 second or even less. Yet data will still get trough, and |
|---|
| 194 | you can ignore the SERVFAIL errors. |
|---|
| 195 | |
|---|
| 196 | If you are running on a local network without any DNS server in-between, try |
|---|
| 197 | -I 50 (iodine and iodined close the connection after 60 seconds of silence). |
|---|
| 198 | The only time you'll notice a slowdown, is when DNS reply packets go missing; |
|---|
| 199 | the iodined server then has to wait for a new ping to re-send the data. You can |
|---|
| 200 | speed this up by generating some upstream traffic (keypress, ping). If this |
|---|
| 201 | happens often, check your network for bottlenecks and/or run with -I1. |
|---|
| 202 | |
|---|
| 203 | The delayed answering in lazy mode will cause some "carrier grade" commercial |
|---|
| 204 | DNS relays to repeatedly re-send the same DNS query to the iodined server. |
|---|
| 205 | If the DNS relay is actually implemented as a pool of parallel servers, |
|---|
| 206 | duplicate requests may even arrive from multiple sources. This effect will |
|---|
| 207 | only be visible in the network traffic at the iodined server, and will not |
|---|
| 208 | affect the client's connection. Iodined will notice these duplicates, and send |
|---|
| 209 | the same answer (when its time has come) to both the original query and the |
|---|
| 210 | latest duplicate. After that, the full answer is cached for a short while. |
|---|
| 211 | Delayed duplicates that arrive at the server even later, get a reply that the |
|---|
| 212 | iodine client will ignore (if it ever arrives there). |
|---|
| 213 | |
|---|
| 214 | If you have problems, try inspecting the traffic with network monitoring tools |
|---|
| 215 | like tcpdump or ethereal/wireshark, and make sure that the relaying DNS server |
|---|
| 216 | has not cached the response. A cached error message could mean that you |
|---|
| 217 | started the client before the server. The -D (and -DD) option on the server |
|---|
| 218 | can also show received and sent queries. |
|---|
| 219 | |
|---|
| 220 | |
|---|
| 221 | TIPS & TRICKS: |
|---|
| 222 | |
|---|
| 223 | If your port 53 is taken on a specific interface by an application that does |
|---|
| 224 | not use it, use -p on iodined to specify an alternate port (like -p 5353) and |
|---|
| 225 | use for instance iptables (on Linux) to forward the traffic: |
|---|
| 226 | iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353 |
|---|
| 227 | (Sent in by Tom Schouten) |
|---|
| 228 | |
|---|
| 229 | Iodined will reject data from clients that have not been active (data/pings) |
|---|
| 230 | for more than 60 seconds. Similarly, iodine will exit when no downstream |
|---|
| 231 | data has been received for 60 seconds. In case of a long network outage or |
|---|
| 232 | similar, just restart iodine (re-login), possibly multiple times until you get |
|---|
| 233 | your old IP address back. Once that's done, just wait a while, and you'll |
|---|
| 234 | eventually see the tunneled TCP traffic continue to flow from where it left |
|---|
| 235 | off before the outage. |
|---|
| 236 | |
|---|
| 237 | With the introduction of the downstream packet queue in the server, its memory |
|---|
| 238 | usage has increased with several megabytes in the default configuration. |
|---|
| 239 | For use in low-memory environments (e.g. running on your DSL router), you can |
|---|
| 240 | decrease USERS and undefine OUTPACKETQ_LEN in user.h without any ill conse- |
|---|
| 241 | quence, assuming at most one client will be connected at any time. A small |
|---|
| 242 | DNSCACHE_LEN is still advised, preferably 2 or higher, however you can also |
|---|
| 243 | undefine it to save a few more kilobytes. |
|---|
| 244 | |
|---|
| 245 | |
|---|
| 246 | PERFORMANCE: |
|---|
| 247 | |
|---|
| 248 | This section tabulates some performance measurements. To view properly, use |
|---|
| 249 | a fixed-width font like Courier. |
|---|
| 250 | |
|---|
| 251 | Measurements were done in protocol 00000502 in lazy mode; upstream encoding |
|---|
| 252 | always Base128; iodine -M255; iodined -m1130. Network conditions were not |
|---|
| 253 | extremely favorable; results are not benchmarks but a realistic indication of |
|---|
| 254 | real-world performance that can be expected in similar situations. |
|---|
| 255 | |
|---|
| 256 | Upstream/downstream throughput was measured by scp'ing a file previously |
|---|
| 257 | read from /dev/urandom (i.e. incompressible), and measuring size with |
|---|
| 258 | "ls -l ; sleep 30 ; ls -l" on a separate non-tunneled connection. Given the |
|---|
| 259 | large scp block size of 16 kB, this gives a resolution of 4.3 kbit/s, which |
|---|
| 260 | explains why some values are exactly equal. |
|---|
| 261 | Ping round-trip times measured with "ping -c100", presented are average rtt |
|---|
| 262 | and mean deviation (indicating spread around the average), in milliseconds. |
|---|
| 263 | |
|---|
| 264 | |
|---|
| 265 | Situation 1: |
|---|
| 266 | Laptop -> Wifi AP -> Home server -> DSL provider -> Datacenter |
|---|
| 267 | iodine DNS "relay" bind9 DNS cache iodined |
|---|
| 268 | |
|---|
| 269 | downstr. upstream downstr. ping-up ping-down |
|---|
| 270 | fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev |
|---|
| 271 | ------------------------------------------------------------------------------ |
|---|
| 272 | |
|---|
| 273 | iodine -> Wifi AP :53 |
|---|
| 274 | -Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4 |
|---|
| 275 | |
|---|
| 276 | iodine -> Home server :53 |
|---|
| 277 | -Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4 |
|---|
| 278 | |
|---|
| 279 | iodine -> DSL provider :53 |
|---|
| 280 | -Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4 |
|---|
| 281 | -Ttxt -Obase32 730 56.7 174.7* |
|---|
| 282 | -Ttxt -Obase64 874 56.7 174.7 |
|---|
| 283 | -Ttxt -Obase128 1018 56.7 174.7 |
|---|
| 284 | -Ttxt -Oraw 1162 56.7 358.2 |
|---|
| 285 | -Tsrv -Obase128 910 56.7 174.7 |
|---|
| 286 | -Tcname -Obase32 151 56.7 43.6 |
|---|
| 287 | -Tcname -Obase128 212 56.7 52.4 |
|---|
| 288 | |
|---|
| 289 | iodine -> DSL provider :53 |
|---|
| 290 | wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4 |
|---|
| 291 | |
|---|
| 292 | [174.7* : these all have 2frag/packet] |
|---|
| 293 | |
|---|
| 294 | |
|---|
| 295 | Situation 2: |
|---|
| 296 | Laptop -> Wifi+vpn / wired -> Home server |
|---|
| 297 | iodine iodined |
|---|
| 298 | |
|---|
| 299 | downstr. upstream downstr. ping-up ping-down |
|---|
| 300 | fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev |
|---|
| 301 | ------------------------------------------------------------------------------ |
|---|
| 302 | |
|---|
| 303 | wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6 |
|---|
| 304 | |
|---|
| 305 | wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1 |
|---|
| 306 | |
|---|
| 307 | |
|---|
| 308 | Performance is strongly coupled to low ping times, as iodine requires |
|---|
| 309 | confirmation for every data fragment before moving on to the next. Allowing |
|---|
| 310 | multiple fragments in-flight like TCP could possibly increase performance, |
|---|
| 311 | but it would likely cause serious overload for the intermediary DNS servers. |
|---|
| 312 | The current protocol scales performance with DNS responsivity, since the |
|---|
| 313 | DNS servers are on average handling at most one DNS request per client. |
|---|
| 314 | |
|---|
| 315 | |
|---|
| 316 | PORTABILITY: |
|---|
| 317 | |
|---|
| 318 | iodine has been tested on Linux (arm, ia64, x86, AMD64 and SPARC64), FreeBSD |
|---|
| 319 | (ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc and x86, with |
|---|
| 320 | http://tuntaposx.sourceforge.net/). and Windows (with OpenVPN TAP32 driver, see |
|---|
| 321 | win32 readme file). It should be easy to port to other unix-like systems that |
|---|
| 322 | has TUN/TAP tunneling support. Let us know if you get it to run on other |
|---|
| 323 | platforms. |
|---|
| 324 | |
|---|
| 325 | |
|---|
| 326 | THE NAME: |
|---|
| 327 | |
|---|
| 328 | The name iodine was chosen since it starts with IOD (IP Over DNS) and since |
|---|
| 329 | iodine has atomic number 53, which happens to be the DNS port number. |
|---|
| 330 | |
|---|
| 331 | |
|---|
| 332 | THANKS: |
|---|
| 333 | |
|---|
| 334 | - To kuxien for FreeBSD and OS X testing |
|---|
| 335 | - To poplix for code audit |
|---|
| 336 | |
|---|
| 337 | |
|---|
| 338 | AUTHORS & LICENSE: |
|---|
| 339 | |
|---|
| 340 | Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> |
|---|
| 341 | Also major contributions by Anne Bezemer. |
|---|
| 342 | |
|---|
| 343 | Permission to use, copy, modify, and distribute this software for any purpose |
|---|
| 344 | with or without fee is hereby granted, provided that the above copyright notice |
|---|
| 345 | and this permission notice appear in all copies. |
|---|
| 346 | |
|---|
| 347 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
|---|
| 348 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
|---|
| 349 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
|---|
| 350 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
|---|
| 351 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
|---|
| 352 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|---|
| 353 | PERFORMANCE OF THIS SOFTWARE. |
|---|
| 354 | |
|---|
| 355 | |
|---|
| 356 | MD5 implementation by L. Peter Deutsch (license and source in src/md5.[ch]) |
|---|
| 357 | Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. |
|---|