Changeset b17790
- Timestamp:
- 12/29/09 21:00:57 (2 years ago)
- Branches:
- master
- Children:
- aa818c
- Parents:
- 1a26a9
- git-author:
- J. A. Bezemer <J.A.Bezemer@…> (12/29/09 21:00:57)
- git-committer:
- Erik Ekman <erik@…> (02/04/12 20:34:04)
- Files:
-
- 2 added
- 16 edited
- 1 moved
-
README (modified) (7 diffs)
-
doc/proto_00000502.txt (moved) (moved from doc/proto_00000501.txt) (11 diffs)
-
man/iodine.8 (modified) (12 diffs)
-
src/Makefile (modified) (2 diffs)
-
src/base128.c (added)
-
src/base128.h (added)
-
src/base32.c (modified) (4 diffs)
-
src/base64.c (modified) (6 diffs)
-
src/client.c (modified) (65 diffs)
-
src/client.h (modified) (1 diff)
-
src/common.h (modified) (2 diffs)
-
src/dns.c (modified) (19 diffs)
-
src/dns.h (modified) (1 diff)
-
src/encoding.c (modified) (2 diffs)
-
src/encoding.h (modified) (2 diffs)
-
src/iodine.c (modified) (9 diffs)
-
src/iodined.c (modified) (50 diffs)
-
src/user.h (modified) (3 diffs)
-
src/version.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
README
r05e99c rb17790 12 12 13 13 Try it out within your own LAN! Follow these simple steps: 14 - On your server, run: ./iodined -f 10.0.0.1 test. asdf14 - On your server, run: ./iodined -f 10.0.0.1 test.com 15 15 (If you already use the 10.0.0.0 network, use another internal net like 16 16 172.16.0.0) 17 17 - Enter a password 18 - On the client, run: ./iodine -f 192.168.0.1 test.asdf19 (Replace 192.168.0.1 with theserver's ip address)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 20 - Enter the same password 21 21 - Now the client has the tunnel ip 10.0.0.2 and the server has 10.0.0.1 … … 27 27 HOW TO USE: 28 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 29 33 Server side: 30 To use this tunnel, you need control over a real domain (like mytunnel.com), 31 and a server with a public IP number. If the server already runs a DNS 32 server, change the listening port and then use the -b option to let 33 iodined forward the DNS requests. Then, delegate a subdomain 34 (say, tunnel1.mytunnel.com) to the server. If you use BIND for the domain, 35 add these lines to the zone file: 36 37 tunnel1host IN A 10.15.213.99 38 tunnel1 IN NS tunnel1host.mytunnel.com. 39 40 Do not use CNAME instead of A above. 41 If your server has a dynamic IP, use a dynamic dns provider: 42 43 tunnel1 IN NS tunnel1host.mydyndnsprovider.com 44 45 Now any DNS querys for domains ending with tunnel1.mytunnnel.com will be sent 46 to your server. Start iodined on the server. The first argument is the tunnel 47 IP address (like 192.168.99.1) and the second is the assigned domain (in this 48 case tunnel1.mytunnel.com). The -f argument will keep iodined running in the 49 foreground, which helps when testing. iodined will start a virtual interface, 50 and also start listening for DNS queries on UDP port 53. Either enter a 51 password on the commandline (-P pass) or after the server has started. Now 52 everything is ready for the client. 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 53 76 54 77 Client side: 55 All the setup is done, just start iodine. It takes up totwo arguments, the78 All the setup is done, just start iodine. It takes one or two arguments, the 56 79 first is the local relaying DNS server (optional) and the second is the domain 57 used (tunnel1.mytunnnel.com). If DNS queries are allowed to any computer, you 58 can use the tunnel endpoint (example: 10.15.213.99 or tunnel1host.mytunnel.com) 59 as the first argument. The tunnel interface will get an IP close to the servers 60 (in this case 192.168.99.2) and a suitable MTU. Enter the same password as on 61 the server either by argument or after the client has started. Now you should 62 be able to ping the other end of the tunnel from either side. 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. 63 102 64 103 … … 66 105 67 106 Routing: 68 The normal case is to route all traffic through the DNS tunnel. To do this, first 69 add a route to the nameserver you use with the default gateway as gateway. Then 70 replace the default gateway with the servers IP address within the DNS tunnel, 71 and configure the server to do NAT. 72 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: 73 135 The DNS-response fragment size is normally autoprobed to get maximum bandwidth. 74 136 To force a specific value (and speed things up), use the -m option. 75 137 76 The iodined server replies to NS requests sent for subdomains of the tunnel 77 domain. If your domain is tunnel.com, send a NS request for foo.tunnel.com 78 to see if the delegation works. dig is a good tool for this: 79 dig -t NS foo123.tunnel.com 80 81 The upstream data is sent gzipped encoded with Base32, or Base64 if the relay 82 server support '+' in domain names. DNS protocol allows one query per packet, 83 and one query can be max 256 chars. Each domain name part can be max 63 chars. 84 So your domain name and subdomain should be as short as possible to allow 85 maximum upstream throughput. 86 87 The default is to use DNS NULL-type queries, as this provides the largest 88 downstream bandwidth. If your DNS server blocks NULL requests, try TXT or 89 CNAME queries via the -T option. Also supported are A (returning CNAME) and 90 MX requests, but these may/will cause additional lookups by "smart" caching 91 nameservers to get an actual IP address, which may either slow down or fail 92 completely. DNS responses for non-NULL are Base32 encoded by default, which 93 should always work. For more bandwidth, try Base64 or Raw (TXT only) via the 94 -O option. If Base64/Raw doesn't work, you'll see many failures in the 95 fragment size autoprobe. 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. 96 180 97 181 Normal operation now is for the server to _not_ answer a DNS request until … … 99 183 will always have a DNS request handy when new downstream data has to be sent. 100 184 This greatly improves (interactive) performance and latency, and allows to 101 slow down the quiescent ping requests to 4 second intervals by default. 102 In fact, the main purpose of the pings now is to force a reply to the previous 103 ping, and prevent DNS server timeouts (usually 5-10 seconds per RFC1035). 104 In the unlikely case that you do experience DNS server timeouts (SERVFAIL), 105 decrease the -I option to 1. If you are running on a local network without 106 any DNS server in-between, try -I 50 (iodine and iodined time out after 60 107 seconds). The only time you'll notice a slowdown, is when DNS reply packets 108 go missing; the iodined server then has to wait for a new ping to re-send the 109 data. You can speed this up by generating some upstream traffic (keypress, 110 ping). If this happens often, check your network for bottlenecks and/or run 111 with -I1 . 112 113 Some DNS servers appear to be quite impatient and start retrying DNS requests 114 (with _different_ DNS ids!) when an answer does not appear within a few 115 milliseconds. Usually they scale back retries when iodined's lazy mode 116 repeatedly takes several seconds to answer; and they scale up retries again 117 when iodined answers fast during heavy data transfer. Some commercial DNS 118 servers advertise this as "carrier-grade adaptive retransmission techniques". 119 The effect will only be visible in the network traffic at the iodined server, 120 and will not affect the client's connection. Iodined has rather elaborate 121 logic to deal with (i.e., ignore) these unwanted duplicates. 122 123 Other DNS servers, notably the opendns.com network, seem to regard iodined's 124 lazyness as incompetency, and will start shuffling requests around, possibly 125 in an attempt to reduce iodined's workload. The resulting out-of-sequence DNS 126 traffic works quite badly for lazy mode. The iodine client will detect this, 127 and switch back to legacy mode ("immediate ping-pong") automatically. In these 128 cases, start the iodine client with -L0 to prevent it from operating in lazy 129 mode altogether. Note that this will negatively affect interactive performance 130 and latency, especially in the downstream direction. 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). 131 213 132 214 If you have problems, try inspecting the traffic with network monitoring tools 133 and make sure that the relaying DNS server has not cached the response. A 134 cached error message could mean that you started the client before the server. 135 The -D (and -DD) option on the server can also show received and sent queries. 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. 136 219 137 220 … … 166 249 a fixed-width font like Courier. 167 250 168 Measurements were done in protocol 00000500 with lazy mode unless indicated 169 otherwise. Upstream encoding always Base64. 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 170 256 Upstream/downstream throughput was measured by scp'ing a file previously 171 257 read from /dev/urandom (i.e. incompressible), and measuring size with 172 258 "ls -l ; sleep 30 ; ls -l" on a separate non-tunneled connection. Given the 173 259 large scp block size of 16 kB, this gives a resolution of 4.3 kbit/s, which 174 explains why manyvalues are exactly equal.260 explains why some values are exactly equal. 175 261 Ping round-trip times measured with "ping -c100", presented are average rtt 176 262 and mean deviation (indicating spread around the average), in milliseconds. … … 186 272 187 273 iodine -> Wifi AP :53 188 -Tnull (= -Oraw) 982 39.3 148.5 26.7 3.1 26.6 3.0274 -Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4 189 275 190 276 iodine -> Home server :53 191 -Tnull (= -Oraw) 1174 4 3.6 174.7 25.2 4.0 25.5 3.4277 -Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4 192 278 193 279 iodine -> DSL provider :53 194 -Tnull (= -Oraw) 1174 52.4 200.9 20.3 3.2 20.3 2.7 195 -Ttxt -Obase32 730 52.4 192.2* 196 -Ttxt -Obase64 874 52.4 192.2 197 -Ttxt -Oraw 1162 52.4 192.2 198 -Tcname -Obase32 148 52.4 48.0 199 -Tcname -Obase64 181 52.4 61.1 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 200 288 201 289 iodine -> DSL provider :53 202 wired (no Wifi) -Tnull 1174 65.5 244.6 17.7 1.9 17.8 1.6203 204 [1 92.2* : nice, because still2frag/packet]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] 205 293 206 294 207 295 Situation 2: 208 Laptop -> (wire) -> (Home server) -> (DSL) -> opendns.com -> Datacenter209 iodine DNS cacheiodined296 Laptop -> Wifi+vpn / wired -> Home server 297 iodine iodined 210 298 211 299 downstr. upstream downstr. ping-up ping-down … … 213 301 ------------------------------------------------------------------------------ 214 302 215 iodine -> opendns.com :53 216 -Tnull -L1 (lazy mode) 230 - - 404.4 196.2 663.8 679.6 217 (20% lost) (2% lost) 218 219 -Tnull -L0 (legacy mode) 230 5.6 7.4 197.3 4.7 610.8 323.5 220 221 [Note: Throughput measured over 300 seconds to get better resolution] 222 223 224 Situation 3: 225 Laptop -> Wifi+vpn / wired -> Home server 226 iodine iodined 227 228 downstr. upstream downstr. ping-up ping-down 229 fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev 230 ------------------------------------------------------------------------------ 231 232 wifi + openvpn -Tnull 1186 183.5 611.6 5.7 1.4 7.0 2.7 233 234 wired -Tnull 1186 685.9 2350.5 1.3 0.1 1.4 0.4 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 235 306 236 307 -
doc/proto_00000502.txt
r05e99c rb17790 1 Detailed specification of protocol in version 0000050 11 Detailed specification of protocol in version 00000502 2 2 ====================================================== 3 3 … … 7 7 1. DNS protocol 8 8 ====================================================== 9 10 Quick alphabetical index / register: 11 0-9 Data packet 12 A-F Data packet 13 I IP address 14 L Login 15 N Downstream fragsize (NS.topdomain A-type reply) 16 O Options 17 P Ping 18 R Downstream fragsize probe 19 S Switch upstream codec 20 V Version 21 W (WWW.topdomain A-type reply) 22 Y Downstream codec check 23 Z Upstream codec check 24 9 25 10 26 CMC = 2 byte Cache Miss Counter, increased every time it is used … … 39 55 First byte i or I 40 56 5 bits coded as Base32 char, meaning userid 41 CMC 57 CMC as 3 Base32 chars 42 58 Server replies 43 59 BADIP if bad userid, or 44 60 I and then 4 bytes network order external IP address of iodined server 45 61 46 Case check:62 Upstream codec check / bounce: 47 63 Client sends: 48 64 First byte z or Z 49 65 Lots of data that should not be decoded 50 66 Server replies: 51 The requested domain copied raw 67 The requested domain copied raw, in the lowest-grade downstream codec 68 available for the request type. 69 70 Downstream codec check: 71 Client sends: 72 First byte y or Y 73 1 char, meaning downstream codec to use 74 5 bits coded as Base32 char, meaning check variant 75 CMC as 3 Base32 chars 76 Possibly extra data, depending on check variant 77 Server sends: 78 Data encoded with requested downstream codec; data content depending 79 on check variant number. 80 BADCODEC if requested downstream codec not available. 81 BADLEN if check variant is not available, or problem with extra data. 82 83 Downstream codec chars are same as in 'O' Option request, below. 84 85 Check variants: 86 1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h 87 88 (Other variants reserved; possibly variant that sends a decoded-encoded 89 copy of Base32-encoded extra data in the request) 52 90 53 91 Switch codec: … … 55 93 First byte s or S 56 94 5 bits coded as Base32 char, meaning userid 57 5 bits coded as Base32 char, with value 5 or 6, representing number of raw 58 bits per encoded byte 59 CMC 95 5 bits coded as Base32 char, representing number of raw bits per 96 encoded byte: 97 5: Base32 (a-z0-5) 98 6: Base64 (a-zA-Z0-9+-) 99 26: Base64u (a-zA-Z0-9_-) 100 7: Base128 (a-zA-Z0-9\274-\375) 101 CMC as 3 Base32 chars 60 102 Server sends: 61 103 Name of codec if accepted. After this all upstream data packets must 62 104 be encoded with the new codec. 63 BADCODEC if not accepted. Client must then revert to Base32105 BADCODEC if not accepted. Client must then revert to previous codec 64 106 BADLEN if length of query is too short 65 107 … … 69 111 5 bits coded as Base32 char, meaning userid 70 112 1 char, meaning option 113 CMC as 3 Base32 chars 71 114 Server sends: 72 115 Full name of option if accepted. After this, option immediately takes … … 78 121 t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default) 79 122 s or S: Downstream encoding Base64, for TXT/CNAME/A/MX 123 u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX 124 v or V: Downstream encoding Base128, for TXT/CNAME/A/MX 80 125 r or R: Downstream encoding Raw, for TXT/NULL (default for NULL) 81 126 If codec unsupported for request type, server will use Base32; note … … 97 142 Then follows a long random query which contents does not matter 98 143 Server sends: 99 Requested number of bytes as a response. The first two bytes contains 100 the requested length. Rest of message can be any data. 144 Requested number of bytes as a response. The first two bytes contain 145 the requested length. The third byte is 107 (0x6B). The fourth byte 146 is a random value, and each following byte is incremented with 107. 147 This is checked by the client to determine corruption. 101 148 BADFRAG if requested length not accepted. 102 149 … … 115 162 Data: 116 163 Upstream data header: 117 3210 432 10 43 210 4321 0 118 +----+---+--+--+---+----+-+ 119 |UUUU|SSS|FF|FF|DDD|GGGG|L| 120 +----+---+--+--+---+----+-+ 164 3210 432 10 43 210 4321 0 43210 165 +----+---+--+--+---+----+-+-----+ 166 |UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC| 167 +----+---+--+--+---+----+-+-----+ 121 168 122 169 Downstream data header: … … 133 180 GGGG = Downstream fragment number 134 181 C = Compression enabled for downstream packet 135 136 Upstream data packet starts with 1 byte ASCII hex coded user byte, then 3 bytes 137 Base32 encoded header, then comes the payload data, encoded with chosen codec. 182 UDCMC = Upstream Data CMC, 36 steps a-z0-9, case-insensitive 183 184 Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes 185 Base32 encoded header; then 1 char data-CMC; then comes the payload data, 186 encoded with the chosen upstream codec. 138 187 139 188 Downstream data starts with 2 byte header. Then payload data, which may be … … 148 197 t or T: Base32 encoded before chop, decoded after un-chop 149 198 s or S: Base64 encoded before chop, decoded after un-chop 199 u or U: Base64u encoded before chop, decoded after un-chop 200 v or V: Base128 encoded before chop, decoded after un-chop 150 201 r or R: Raw no encoding, only DNS-chop 151 CNAME/A/MX:202 SRV/MX/CNAME/A: 152 203 h or H: Hostname encoded with Base32 153 204 i or I: Hostname encoded with Base64 205 j or J: Hostname encoded with Base64u 206 k or K: Hostname encoded with Base128 207 SRV and MX may reply with multiple hostnames, each encoded separately. Each 208 has a 10-multiple priority, and encoding/decoding is done in strictly 209 increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS 210 relays will shuffle the answer records in the response. 154 211 155 212 Ping: … … 163 220 CMC 164 221 165 The server response to Ping and Data packets is a DNS NULL type response: 166 If server has nothing to send, data length is 0 bytes. 167 If server has something to send, it will send a downstream data packet, 168 prefixed with 2 bytes header as shown above. 222 The server response to Ping and Data packets is a DNS NULL/TXT/.. type response, 223 always starting with the 2 bytes downstream data header as shown above. 224 If server has nothing to send, no data is added after the header. 225 If server has something to send, it will add the downstream data packet 226 (or some fragment of it) after the header. 169 227 170 228 -
man/iodine.8
r1a26a9 rb17790 1 1 .\" groff -man -Tascii iodine.8 2 .TH IODINE 8 " SEP2009" "User Manuals"2 .TH IODINE 8 "DEC 2009" "User Manuals" 3 3 .SH NAME 4 4 iodine, iodined \- tunnel IPv4 over DNS … … 20 20 .B ] [-m 21 21 .I fragsize 22 .B ] [-M 23 .I namelen 22 24 .B ] [-z 23 25 .I context … … 85 87 .B iodined 86 88 is the server. 89 90 Note: server and client are required to speak the exact same protocol. In most 91 cases, this means running the same iodine version. Unfortunately, implementing 92 backward and forward protocol compatibility is usually not feasible. 87 93 .SH OPTIONS 88 94 .SS Common Options: … … 128 134 client to automatically probe the maximum accepted downstream fragment size. 129 135 .TP 136 .B -M namelen 137 Maximum length of upstream hostnames, default 255. 138 Usable range ca. 100 to 255. 139 Use this option to scale back upstream bandwidth in favor of downstream 140 bandwidth. 141 Also useful for DNS servers that perform unreliably when using full-length 142 hostnames, noticable when fragment size autoprobe returns very 143 different results each time. 144 .TP 130 145 .B -T dnstype 131 DNS request type. 132 .I NULL 133 is default. If this doesn't work, try 134 .I TXT 135 (some less bandwidth) or 146 DNS request type override. 147 By default, autodetection will probe for working DNS request types, and 148 will select the request type that is expected to provide the most bandwidth. 149 However, it may turn out that a DNS relay imposes limits that skew the 150 picture, which may lead to an "unexpected" DNS request type providing 151 more bandwidth. 152 In that case, use this option to override the autodetection. 153 In (expected) decreasing bandwidth order, the supported DNS request types are: 154 .IR NULL , 155 .IR TXT , 156 .IR SRV , 157 .IR MX , 136 158 .I CNAME 137 (much less bandwidth). Also supported are 159 and 138 160 .I A 139 (returning CNAME) and 161 (returning CNAME). 162 Note that 163 .IR SRV , 140 164 .I MX 141 requests, but these may/will cause additional lookups by "smart" caching 165 and 166 .I A 167 may/will cause additional lookups by "smart" caching 142 168 nameservers to get an actual IP address, which may either slow down or fail 143 169 completely. 144 170 .TP 145 171 .B -O downenc 146 Downstream encoding for all query type responses except NULL. 172 Force downstream encoding type for all query type responses except NULL. 173 Default is autodetected, but may not spot all problems for the more advanced 174 codecs. 175 Use this option to override the autodetection. 147 176 .I Base32 148 is default and should always work. 177 is the lowest-grade codec and should always work; this is used when 178 autodetection fails. 149 179 .I Base64 150 180 provides more bandwidth, but may not work on all nameservers. 181 .I Base64u 182 is equal to Base64 except in using underscore ('_') 183 instead of plus sign ('+'), possibly working where 184 .I Base64 185 does not. 186 .I Base128 187 uses high byte values (mostly accented letters in iso8859-1), 188 which might work with some nameservers. 151 189 For TXT queries, 152 190 .I Raw 153 will provide maximum performance . This will only work if the nameserver191 will provide maximum performance, but this will only work if the nameserver 154 192 path is fully 8-bit-clean for responses that are assumed to be "legible text". 155 193 .TP 156 194 .B -L 0|1 157 195 Lazy-mode switch. 158 \-L1 (default): Use lazy mode if server supports it, for improved 159 performance and decreased latency. 160 Some DNS servers, notably the opendns.com network, appear unstable when 161 handling lazy mode DNS traffic and will re-order requests. If this occurs, 162 you will notice fluctuating response speed in interactive sessions. 163 The iodine client will eventually detect this and switch back to legacy 164 mode automatically. Use \-L0 to force running in legacy mode 196 \-L1 (default): Use lazy mode for improved performance and decreased latency. 197 A very small minority of DNS relays appears to be unable to handle the 198 lazy mode traffic pattern, resulting in no or very little data coming through. 199 The iodine client will detect this and try to switch back to legacy mode, 200 but this may not always work. 201 In these situations use \-L0 to force running in legacy mode 165 202 (implies \-I1). 166 203 .TP … … 168 205 Maximum interval between requests (pings) so that intermediate DNS 169 206 servers will not time out. Default is 4 in lazy mode, which will work 170 fine in almost all cases. Decrease if you get SERVFAIL errors in periods 171 without tunneled data traffic. To get absolute minimum DNS traffic, 172 increase well above 4 until SERVFAIL errors start to occur. 207 fine in most cases. When too many SERVFAIL errors occur, iodine 208 will automatically reduce this to 1. 209 To get absolute minimum DNS traffic, 210 increase well above 4, but not so high that SERVFAIL errors start to occur. 211 There are some DNS relays with very small timeouts, 212 notably dnsadvantage.com (ultradns), that will give 213 SERVFAIL errors even with \-I1; data will still get trough, 214 and these errors can be ignored. 173 215 Maximum useful value is 59, since iodined will close a client's 174 216 connection after 60 seconds of inactivity. … … 191 233 .B -f 192 234 option. 235 On level 2 (-DD) or higher, DNS queries will be printed literally. 236 When using Base128 upstream encoding, this is best viewed as 237 ISO Latin-1 text instead of (illegal) UTF-8. 238 This is easily done with : "LC_ALL=C luit iodined -DD ..." 239 (see luit(1)). 193 240 .TP 194 241 .B -m mtu 195 242 Set 'mtu' as mtu size for the tun device. 196 243 This will be sent to the client on login, and the client will use the same mtu 197 for its tun device. Default 1 200. Note that the DNS traffic will be244 for its tun device. Default 1130. Note that the DNS traffic will be 198 245 automatically fragmented when needed. 199 246 .TP … … 237 284 .TP 238 285 .B tunnel_ip[/netmask] 239 +This is the server's ip address on the tun interface. The client will be286 This is the server's ip address on the tun interface. The client will be 240 287 given the next ip number in the range. It is recommended to use the 241 288 10.0.0.0 or 172.16.0.0 ranges. The default netmask is /27, can be overriden … … 244 291 .TP 245 292 .B topdomain 246 +The dns traffic is expected to arrive as queries for293 The dns traffic is expected to arrive as queries for 247 294 subdomains under 'topdomain'. This is normally a subdomain to a domain you 248 295 own. Use a short domain name to get better throughput. This argument must be … … 251 298 they will be dropped. 252 299 .SH EXAMPLES 253 .SS Quickstart: 254 .TP 255 Try it out within your own LAN! Follow these simple steps: 256 .TP 257 - On your server, run: ./iodined \-f 10.0.0.1 test.asdf 258 (If you already use the 10.0.0.0 network, use another internal net like 259 172.16.0.0) 260 .TP 261 - Enter a password 262 .TP 263 - On the client, run: ./iodine \-f 192.168.0.1 test.asdf 264 (Replace 192.168.0.1 with the server's ip address) 265 .TP 266 - Enter the same password 267 .TP 268 - Now the client has the tunnel ip 10.0.0.2 and the server has 10.0.0.1 269 .TP 270 - Try pinging each other through the tunnel 271 .TP 272 - Done! :) 273 .TP 274 To actually use it through a relaying nameserver, see below. 275 .SS Full setup: 276 277 .TP 278 .B Server side: 279 To use this tunnel, you need control over a real domain (like mytunnel.com), 280 and a server with a public IP number. If the server already runs a DNS 281 server, change the listening port and then use the \-b option to let 282 iodined forward the DNS requests. Then, delegate a subdomain 283 (say, tunnel1.mytunnel.com) to the server. If you use BIND for the domain, 284 add these lines to the zone file (replace 10.15.213.99 with your server ip): 285 286 .nf 287 tunnel1host IN A 10.15.213.99 288 tunnel1 IN NS tunnel1host.mytunnel.com. 289 .fi 290 291 Now any DNS querys for domains ending with tunnel1.mytunnnel.com will be sent 292 to your server. Start iodined on the server. The first argument is the tunnel 293 IP address (like 192.168.99.1) and the second is the assigned domain (in this 294 case tunnel1.mytunnel.com). The \-f argument will keep iodined running in the 295 foreground, which helps when testing. iodined will start a virtual interface, 296 and also start listening for DNS queries on UDP port 53. Either enter a 297 password on the commandline (\-P pass) or after the server has started. Now 298 everything is ready for the client. 299 .TP 300 .B Client side: 301 All the setup is done, just start iodine. It also takes two 302 arguments, the first is the local relaying DNS server and the second is the 303 domain used (tunnel1.mytunnnel.com). If DNS queries are allowed to any 304 computer, you can use the tunnel endpoint (example: 10.15.213.99 or 305 tunnel1host.mytunnel.com) as the first argument. The tunnel interface will get 306 an IP close to the servers (in this case 192.168.99.2) and a suitable MTU. 307 Enter the same password as on the server either by argument or after the client 308 has started. Now you should be able to ping the other end of the tunnel from 309 either side. 310 .TP 311 .B Routing: 312 The normal case is to route all traffic through the DNS tunnel. To do this, first 313 add a route to the nameserver you use with the default gateway as gateway. Then 314 replace the default gateway with the servers IP address within the DNS tunnel, 315 and configure the server to do NAT. 316 .TP 317 .B Troubleshooting: 318 Use the \-D option on the server to show received and sent queries, or use a 319 tool like Wireshark/tcpdump. The iodined server replies to NS requests sent for 320 subdomains of the tunnel domain. If your domain is tunnel.com, send a NS 321 request for foo.tunnel.com to see if the delegation works. dig is a good tool 322 for this: 323 .nf 324 dig \-t NS foo123.tunnel.com 325 .fi 326 .TP 327 .B MTU issues: 328 These issues should be solved now, with automatic fragmentation of downstream 329 packets. There should be no need to set the MTU explicitly on the server. 300 See the README file for both a quick test scenario, and a detailed description 301 of real-world deployment. 330 302 .SH SECURITY 331 303 Login is a relatively secure challenge-response MD5 hash, with the … … 337 309 with the \-c option. Use of ssh or vpn tunneling is strongly recommended. 338 310 On both server and client, use 339 .I iptables 340 , 311 .IR iptables , 341 312 .I pf 342 or other firew lls to block all traffic coming in from the tun interfaces,313 or other firewalls to block all traffic coming in from the tun interfaces, 343 314 except to the used ssh or vpn ports. 344 315 .SH ENVIRONMENT … … 349 320 for one. The 350 321 .B -P 351 option still has pre ference.322 option still has precedence. 352 323 .SS IODINED_PASS 353 324 If the environment variable … … 356 327 for one. The 357 328 .B -P 358 option still has pre ference.329 option still has precedence. 359 330 .El 360 331 .SH SEE ALSO -
src/Makefile
r27fdc2 rb17790 1 COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o md5.o common.o1 COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o md5.o common.o 2 2 CLIENTOBJS = iodine.o client.o util.o 3 3 CLIENT = ../bin/iodine … … 31 31 @$(CC) $(CFLAGS) $< -o $@ 32 32 33 base64u.o client.o iodined.o: base64u.h 34 base64u.c: base64.c 35 @echo Making $@ 36 @echo '/* No use in editing, produced by Makefile! */' > $@ 37 @sed -e 's/\(base64\)/\1u/ig ; s/0123456789+/0123456789_/' < $< >> $@ 38 base64u.h: base64.h 39 @echo Making $@ 40 @echo '/* No use in editing, produced by Makefile! */' > $@ 41 @sed -e 's/\(base64\)/\1u/ig ; s/0123456789+/0123456789_/' < $< >> $@ 42 33 43 clean: 34 44 @echo "Cleaning src/" 35 @rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core 45 @rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core base64u.* 36 46 -
src/base32.c
rfb1747 rb17790 1 1 /* 2 2 * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> 3 * Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl 3 4 * 4 5 * Permission to use, copy, modify, and distribute this software for any … … 29 30 static const char cb32_ucase[] = 30 31 "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"; 31 static unsigned char rev32[128]; 32 32 static unsigned char rev32[256]; 33 static int reverse_init = 0; 34 35 static int base32_encode(char *, size_t *, const void *, size_t); 33 36 static int base32_decode(void *, size_t *, const char *, size_t); 34 static int base32_encode(char *, size_t *, const void *, size_t);35 37 static int base32_handles_dots(); 36 38 static int base32_blksize_raw(); … … 72 74 } 73 75 74 static void76 inline static void 75 77 base32_reverse_init() 76 78 { 77 79 int i; 78 80 unsigned char c; 79 static int reverse_init = 0;80 81 81 82 if (!reverse_init) { 83 memset (rev32, 0, 256); 82 84 for (i = 0; i < 32; i++) { 83 85 c = cb32[i]; … … 105 107 static int 106 108 base32_encode(char *buf, size_t *buflen, const void *data, size_t size) 107 { 108 size_t newsize; 109 size_t maxsize; 110 unsigned char *p; 111 unsigned char *q; 112 int i; 113 114 memset(buf, 0, *buflen); 115 116 /* how many chars can we encode within the buf */ 117 maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC); 118 /* how big will the encoded data be */ 119 newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW); 120 if (size % BLKSIZE_RAW) { 121 newsize += BLKSIZE_ENC; 109 /* 110 * Fills *buf with max. *buflen characters, encoding size bytes of *data. 111 * 112 * NOTE: *buf space should be at least 1 byte _more_ than *buflen 113 * to hold the trailing '\0'. 114 * 115 * return value : #bytes filled in buf (excluding \0) 116 * sets *buflen to : #bytes encoded from data 117 */ 118 { 119 unsigned char *udata = (unsigned char *) data; 120 int iout = 0; /* to-be-filled output char */ 121 int iin = 0; /* one more than last input byte that can be 122 successfully decoded */ 123 124 /* Note: Don't bother to optimize manually. GCC optimizes 125 better(!) when using simplistic array indexing. */ 126 127 while (1) { 128 if (iout >= *buflen || iin >= size) 129 break; 130 buf[iout] = cb32[((udata[iin] & 0xf8) >> 3)]; 131 iout++; 132 133 if (iout >= *buflen || iin >= size) { 134 iout--; /* previous char is useless */ 135 break; 136 } 137 buf[iout] = cb32[((udata[iin] & 0x07) << 2) | 138 ((iin + 1 < size) ? 139 ((udata[iin + 1] & 0xc0) >> 6) : 0)]; 140 iin++; /* 0 complete, iin=1 */ 141 iout++; 142 143 if (iout >= *buflen || iin >= size) 144 break; 145 buf[iout] = cb32[((udata[iin] & 0x3e) >> 1)]; 146 iout++; 147 148 if (iout >= *buflen || iin >= size) { 149 iout--; /* previous char is useless */ 150 break; 151 } 152 buf[iout] = cb32[((udata[iin] & 0x01) << 4) | 153 ((iin + 1 < size) ? 154 ((udata[iin + 1] & 0xf0) >> 4) : 0)]; 155 iin++; /* 1 complete, iin=2 */ 156 iout++; 157 158 if (iout >= *buflen || iin >= size) 159 break; 160 buf[iout] = cb32[((udata[iin] & 0x0f) << 1) | 161 ((iin + 1 < size) ? 162 ((udata[iin + 1] & 0x80) >> 7) : 0)]; 163 iin++; /* 2 complete, iin=3 */ 164 iout++; 165 166 if (iout >= *buflen || iin >= size) 167 break; 168 buf[iout] = cb32[((udata[iin] & 0x7c) >> 2)]; 169 iout++; 170 171 if (iout >= *buflen || iin >= size) { 172 iout--; /* previous char is useless */ 173 break; 174 } 175 buf[iout] = cb32[((udata[iin] & 0x03) << 3) | 176 ((iin + 1 < size) ? 177 ((udata[iin + 1] & 0xe0) >> 5) : 0)]; 178 iin++; /* 3 complete, iin=4 */ 179 iout++; 180 181 if (iout >= *buflen || iin >= size) 182 break; 183 buf[iout] = cb32[((udata[iin] & 0x1f))]; 184 iin++; /* 4 complete, iin=5 */ 185 iout++; 122 186 } 123 /* if the buffer is too small, eat some of the data */ 124 if (*buflen < newsize) { 125 size = maxsize; 126 } 127 128 p = (unsigned char *) buf; 129 q = (unsigned char *)data; 130 131 for(i=0;i<size;i+=BLKSIZE_RAW) { 132 p[0] = cb32[((q[0] & 0xf8) >> 3)]; 133 p[1] = cb32[(((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6))]; 134 p[2] = (i+1 < size) ? cb32[((q[1] & 0x3e) >> 1)] : '\0'; 135 p[3] = (i+1 < size) ? cb32[((q[1] & 0x01) << 4) | ((q[2] & 0xf0) >> 4)] : '\0'; 136 p[4] = (i+2 < size) ? cb32[((q[2] & 0x0f) << 1) | ((q[3] & 0x80) >> 7)] : '\0'; 137 p[5] = (i+3 < size) ? cb32[((q[3] & 0x7c) >> 2)] : '\0'; 138 p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) >> 5)] : '\0'; 139 p[7] = (i+4 < size) ? cb32[((q[4] & 0x1f))] : '\0'; 140 141 q += BLKSIZE_RAW; 142 p += BLKSIZE_ENC; 143 } 144 *p = 0; 187 188 buf[iout] = '\0'; 145 189 146 190 /* store number of bytes from data that was used */ 147 *buflen = size; 148 149 return strlen(buf); 150 } 151 152 #define DECODE_ERROR 0xffffffff 191 *buflen = iin; 192 193 return iout; 194 } 195 153 196 #define REV32(x) rev32[(int) (x)] 154 155 static int156 decode_token(const unsigned char *t, unsigned char *data, size_t len)157 {158 if (len < 2)159 return 0;160 161 data[0] = ((REV32(t[0]) & 0x1f) << 3) |162 ((REV32(t[1]) & 0x1c) >> 2);163 164 if (len < 4)165 return 1;166 167 data[1] = ((REV32(t[1]) & 0x03) << 6) |168 ((REV32(t[2]) & 0x1f) << 1) |169 ((REV32(t[3]) & 0x10) >> 4);170 171 if (len < 5)172 return 2;173 174 data[2] = ((REV32(t[3]) & 0x0f) << 4) |175 ((REV32(t[4]) & 0x1e) >> 1);176 177 if (len < 7)178 return 3;179 180 data[3] = ((REV32(t[4]) & 0x01) << 7) |181 ((REV32(t[5]) & 0x1f) << 2) |182 ((REV32(t[6]) & 0x18) >> 3);183 184 if (len < 8)185 return 4;186 187 data[4] = ((REV32(t[6]) & 0x07) << 5) |188 ((REV32(t[7]) & 0x1f));189 190 return 5;191 }192 197 193 198 static int 194 199 base32_decode(void *buf, size_t *buflen, const char *str, size_t slen) 195 { 196 unsigned char *q; 197 size_t newsize; 198 size_t maxsize; 199 const char *p; 200 int len; 201 202 base32_reverse_init(); 203 204 /* chars needed to decode slen */ 205 newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1; 206 /* encoded chars that fit in buf */ 207 maxsize = BLKSIZE_ENC * (*buflen / BLKSIZE_RAW + 1) + 1; 208 /* if the buffer is too small, eat some of the data */ 209 if (*buflen < newsize) { 210 slen = maxsize; 200 /* 201 * Fills *buf with max. *buflen bytes, decoded from slen chars in *str. 202 * Decoding stops early when *str contains \0. 203 * Illegal encoded chars are assumed to decode to zero. 204 * 205 * NOTE: *buf space should be at least 1 byte _more_ than *buflen 206 * to hold a trailing '\0' that is added (though *buf will usually 207 * contain full-binary data). 208 * 209 * return value : #bytes filled in buf (excluding \0) 210 */ 211 { 212 unsigned char *ubuf = (unsigned char *) buf; 213 int iout = 0; /* to-be-filled output byte */ 214 int iin = 0; /* next input char to use in decoding */ 215 216 base32_reverse_init (); 217 218 /* Note: Don't bother to optimize manually. GCC optimizes 219 better(!) when using simplistic array indexing. */ 220 221 while (1) { 222 if (iout >= *buflen || iin + 1 >= slen || 223 str[iin] == '\0' || str[iin + 1] == '\0') 224 break; 225 ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) | 226 ((REV32(str[iin + 1]) & 0x1c) >> 2); 227 iin++; /* 0 used up, iin=1 */ 228 iout++; 229 230 if (iout >= *buflen || iin + 2 >= slen || 231 str[iin] == '\0' || str[iin + 1] == '\0' || 232 str[iin + 2] == '\0') 233 break; 234 ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) | 235 ((REV32(str[iin + 1]) & 0x1f) << 1) | 236 ((REV32(str[iin + 2]) & 0x10) >> 4); 237 iin += 2; /* 1,2 used up, iin=3 */ 238 iout++; 239 240 if (iout >= *buflen || iin + 1 >= slen || 241 str[iin] == '\0' || str[iin + 1] == '\0') 242 break; 243 ubuf[iout] = ((REV32(str[iin]) & 0x0f) << 4) | 244 ((REV32(str[iin + 1]) & 0x1e) >> 1); 245 iin++; /* 3 used up, iin=4 */ 246 iout++; 247 248 if (iout >= *buflen || iin + 2 >= slen || 249 str[iin] == '\0' || str[iin + 1] == '\0' || 250 str[iin + 2] == '\0') 251 break; 252 ubuf[iout] = ((REV32(str[iin]) & 0x01) << 7) | 253 ((REV32(str[iin + 1]) & 0x1f) << 2) | 254 ((REV32(str[iin + 2]) & 0x18) >> 3); 255 iin += 2; /* 4,5 used up, iin=6 */ 256 iout++; 257 258 if (iout >= *buflen || iin + 1 >= slen || 259 str[iin] == '\0' || str[iin + 1] == '\0') 260 break; 261 ubuf[iout] = ((REV32(str[iin]) & 0x07) << 5) | 262 ((REV32(str[iin + 1]) & 0x1f)); 263 iin += 2; /* 6,7 used up, iin=8 */ 264 iout++; 211 265 } 212 266 213 q = buf; 214 for (p = str; *p && strchr(cb32, *p); p += BLKSIZE_ENC) { 215 len = decode_token((unsigned char *) p, (unsigned char *) q, slen); 216 q += len; 217 slen -= BLKSIZE_ENC; 218 219 if (len < BLKSIZE_RAW) 220 break; 221 } 222 *q = '\0'; 223 224 return q - (unsigned char *) buf; 225 } 226 267 ubuf[iout] = '\0'; 268 269 return iout; 270 } -
src/base64.c
r0b280b rb17790 1 1 /* 2 2 * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se> 3 * Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl 3 4 * 4 5 * Permission to use, copy, modify, and distribute this software for any … … 20 21 21 22 #include "encoding.h" 22 #include "common.h"23 23 #include "base64.h" 24 24 … … 26 26 #define BLKSIZE_ENC 4 27 27 28 /* Note: the "unofficial" char is last here, which means that the \377 pattern 29 in DOWNCODECCHECK1 ('Y' request) will properly test it. */ 28 30 static const char cb64[] = 29 31 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+"; 30 static unsigned char rev64[ 128];32 static unsigned char rev64[256]; 31 33 static int reverse_init = 0; 32 34 … … 36 38 static int base64_blksize_raw(); 37 39 static int base64_blksize_enc(); 38 39 #define REV64(x) rev64[(int) (x)]40 40 41 41 static struct encoder base64_encoder = … … 74 74 } 75 75 76 static int 77 base64_encode(char *buf, size_t *buflen, const void *data, size_t size) 78 { 79 size_t newsize; 80 size_t maxsize; 81 unsigned char *s; 82 unsigned char *p; 83 unsigned char *q; 76 inline static void 77 base64_reverse_init() 78 { 84 79 int i; 85 86 memset(buf, 0, *buflen);87 88 /* how many chars can we encode within the buf */89 maxsize = BLKSIZE_RAW * (*buflen / BLKSIZE_ENC);90 /* how big will the encoded data be */91 newsize = BLKSIZE_ENC * (size / BLKSIZE_RAW);92 if (size % BLKSIZE_RAW) {93 newsize += BLKSIZE_ENC;94 }95 96 /* if the buffer is too small, eat some of the data */97 if (*buflen < newsize) {98 size = maxsize;99 }100 101 p = s = (unsigned char *) buf;102 q = (unsigned char *)data;103 104 for(i=0;i<size;i+=BLKSIZE_RAW) {105 p[0] = cb64[((q[0] & 0xfc) >> 2)];106 p[1] = cb64[(((q[0] & 0x03) << 4) | ((q[1] & 0xf0) >> 4))];107 p[2] = (i+1 < size) ? cb64[((q[1] & 0x0f) << 2 ) | ((q[2] & 0xc0) >> 6)] : '\0';108 p[3] = (i+2 < size) ? cb64[(q[2] & 0x3f)] : '\0';109 110 q += BLKSIZE_RAW;111 p += BLKSIZE_ENC;112 }113 *p = 0;114 115 /* store number of bytes from data that was used */116 *buflen = size;117 118 return strlen(buf);119 }120 121 #define DECODE_ERROR 0xffffffff122 123 static int124 decode_token(const unsigned char *t, unsigned char *data, size_t len)125 {126 if (len < 2)127 return 0;128 129 data[0] = ((REV64(t[0]) & 0x3f) << 2) |130 ((REV64(t[1]) & 0x30) >> 4);131 132 if (len < 3)133 return 1;134 135 data[1] = ((REV64(t[1]) & 0x0f) << 4) |136 ((REV64(t[2]) & 0x3c) >> 2);137 138 if (len < 4)139 return 2;140 141 data[2] = ((REV64(t[2]) & 0x03) << 6) |142 (REV64(t[3]) & 0x3f);143 144 return 3;145 }146 147 static int148 base64_decode(void *buf, size_t *buflen, const char *str, size_t slen)149 {150 unsigned char *q;151 size_t newsize;152 size_t maxsize;153 const char *p;154 80 unsigned char c; 155 unsigned char block[BLKSIZE_ENC];156 int len;157 int i;158 81 159 82 if (!reverse_init) { 83 memset (rev64, 0, 256); 160 84 for (i = 0; i < 64; i++) { 161 85 c = cb64[i]; … … 164 88 reverse_init = 1; 165 89 } 166 167 /* chars needed to decode slen */ 168 newsize = BLKSIZE_RAW * (slen / BLKSIZE_ENC + 1) + 1; 169 /* encoded chars that fit in buf */ 170 maxsize = BLKSIZE_ENC * (*buflen / BLKSIZE_RAW + 1) + 1; 171 /* if the buffer is too small, eat some of the data */ 172 if (*buflen < newsize) { 173 slen = maxsize; 90 } 91 92 static int 93 base64_encode(char *buf, size_t *buflen, const void *data, size_t size) 94 /* 95 * Fills *buf with max. *buflen characters, encoding size bytes of *data. 96 * 97 * NOTE: *buf space should be at least 1 byte _more_ than *buflen 98 * to hold the trailing '\0'. 99 * 100 * return value : #bytes filled in buf (excluding \0) 101 * sets *buflen to : #bytes encoded from data 102 */ 103 { 104 unsigned char *udata = (unsigned char *) data; 105 int iout = 0; /* to-be-filled output char */ 106 int iin = 0; /* one more than last input byte that can be 107 successfully decoded */ 108 109 /* Note: Don't bother to optimize manually. GCC optimizes 110 better(!) when using simplistic array indexing. */ 111 112 while (1) { 113 if (iout >= *buflen || iin >= size) 114 break; 115 buf[iout] = cb64[((udata[iin] & 0xfc) >> 2)]; 116 iout++; 117 118 if (iout >= *buflen || iin >= size) { 119 iout--; /* previous char is useless */ 120 break; 121 } 122 buf[iout] = cb64[((udata[iin] & 0x03) << 4) | 123 ((iin + 1 < size) ? 124 ((udata[iin + 1] & 0xf0) >> 4) : 0)]; 125 iin++; /* 0 complete, iin=1 */ 126 iout++; 127 128 if (iout >= *buflen || iin >= size) 129 break; 130 buf[iout] = cb64[((udata[iin] & 0x0f) << 2 ) | 131 ((iin + 1 < size) ? 132 ((udata[iin + 1] & 0xc0) >> 6) : 0)]; 133 iin++; /* 1 complete, iin=2 */ 134 iout++; 135 136 if (iout >= *buflen || iin >= size) 137 break; 138 buf[iout] = cb64[(udata[iin] & 0x3f)]; 139 iin++; /* 2 complete, iin=3 */ 140 iout++; 174 141 } 175 176 177 q = buf; 178 for (p = str; *p; p += BLKSIZE_ENC) { 179 /* since the str is const, we unescape in another buf */ 180 for (i = 0; i < BLKSIZE_ENC; i++) { 181 block[i] = p[i]; 182 } 183 len = decode_token(block, (unsigned char *) q, slen); 184 q += len; 185 slen -= BLKSIZE_ENC; 186 187 if (len < BLKSIZE_RAW) 188 break; 142 143 buf[iout] = '\0'; 144 145 /* store number of bytes from data that was used */ 146 *buflen = iin; 147 148 return iout; 149 } 150 151 #define REV64(x) rev64[(int) (x)] 152 153 static int 154 base64_decode(void *buf, size_t *buflen, const char *str, size_t slen) 155 /* 156 * Fills *buf with max. *buflen bytes, decoded from slen chars in *str. 157 * Decoding stops early when *str contains \0. 158 * Illegal encoded chars are assumed to decode to zero. 159 * 160 * NOTE: *buf space should be at least 1 byte _more_ than *buflen 161 * to hold a trailing '\0' that is added (though *buf will usually 162 * contain full-binary data). 163 * 164 * return value : #bytes filled in buf (excluding \0) 165 */ 166 { 167 unsigned char *ubuf = (unsigned char *) buf; 168 int iout = 0; /* to-be-filled output byte */ 169 int iin = 0; /* next input char to use in decoding */ 170 171 base64_reverse_init (); 172 173 /* Note: Don't bother to optimize manually. GCC optimizes 174 better(!) when using simplistic array indexing. */ 175 176 while (1) { 177 if (iout >= *buflen || iin + 1 >= slen || 178 str[iin] == '\0' || str[iin + 1] == '\0') 179 break; 180 ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) | 181 ((REV64(str[iin + 1]) & 0x30) >> 4); 182 iin++; /* 0 used up, iin=1 */ 183 iout++; 184 185 if (iout >= *buflen || iin + 1 >= slen || 186 str[iin] == '\0' || str[iin + 1] == '\0') 187 break; 188 ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) | 189 ((REV64(str[iin + 1]) & 0x3c) >> 2); 190 iin++; /* 1 used up, iin=2 */ 191 iout++; 192 193 if (iout >= *buflen || iin + 1 >= slen || 194 str[iin] == '\0' || str[iin + 1] == '\0') 195 break; 196 ubuf[iout] = ((REV64(str[iin]) & 0x03) << 6) | 197 (REV64(str[iin + 1]) & 0x3f); 198 iin += 2; /* 2,3 used up, iin=4 */ 199 iout++; 189 200 } 190 *q = '\0'; 191 192 return q - (unsigned char *) buf; 193 } 194 201 202 ubuf[iout] = '\0'; 203 204 return iout; 205 } -
src/client.c
r1a26a9 rb17790 46 46 #include "base32.h" 47 47 #include "base64.h" 48 #include "base64u.h" 49 #include "base128.h" 48 50 #include "dns.h" 49 51 #include "login.h" … … 70 72 /* My userid at the server */ 71 73 static char userid; 72 static char userid_char; /* used when sending ( uppercase) */73 static char userid_char2; /* also accepted when receiving ( lowercase) */74 static char userid_char; /* used when sending (lowercase) */ 75 static char userid_char2; /* also accepted when receiving (uppercase) */ 74 76 75 77 /* DNS id for next packet */ … … 80 82 /* Base32 encoder used for non-data packets and replies */ 81 83 static struct encoder *b32; 82 /* Base64 e ncoderfor replies */84 /* Base64 etc encoders for replies */ 83 85 static struct encoder *b64; 86 static struct encoder *b64u; 87 static struct encoder *b128; 84 88 85 89 /* The encoder used for data packets … … 91 95 92 96 /* set query type to send */ 93 static unsigned short do_qtype = T_ NULL;97 static unsigned short do_qtype = T_UNSET; 94 98 95 99 /* My connection mode */ 96 100 static enum connection conn; 97 101 98 int selecttimeout; /* RFC says timeout minimum 5sec */99 100 int lazymode;101 102 long send_ping_soon;103 104 time_t lastdownstreamtime;102 static int selecttimeout; /* RFC says timeout minimum 5sec */ 103 static int lazymode; 104 static long send_ping_soon; 105 static time_t lastdownstreamtime; 106 static long send_query_sendcnt = -1; 107 static long send_query_recvcnt = 0; 108 static int hostname_maxlen = 0xFF; 105 109 106 110 void … … 110 114 b32 = get_base32_encoder(); 111 115 b64 = get_base64_encoder(); 116 b64u = get_base64u_encoder(); 117 b128 = get_base128_encoder(); 112 118 dataenc = get_base32_encoder(); 113 119 rand_seed = ((unsigned int) rand()) & 0xFFFF; … … 209 215 else if (!strcasecmp(qtype, "MX")) 210 216 do_qtype = T_MX; 217 else if (!strcasecmp(qtype, "SRV")) 218 do_qtype = T_SRV; 211 219 else if (!strcasecmp(qtype, "TXT")) 212 220 do_qtype = T_TXT; 221 } 222 223 char * 224 get_qtype() 225 { 226 char *c = "UNDEFINED"; 227 228 if (do_qtype == T_NULL) c = "NULL"; 229 else if (do_qtype == T_CNAME) c = "CNAME"; 230 else if (do_qtype == T_A) c = "A"; 231 else if (do_qtype == T_MX) c = "MX"; 232 else if (do_qtype == T_SRV) c = "SRV"; 233 else if (do_qtype == T_TXT) c = "TXT"; 234 235 return c; 213 236 } 214 237 … … 220 243 else if (!strcasecmp(encoding, "base64")) 221 244 downenc = 'S'; 245 else if (!strcasecmp(encoding, "base64u")) 246 downenc = 'U'; 247 else if (!strcasecmp(encoding, "base128")) 248 downenc = 'V'; 222 249 else if (!strcasecmp(encoding, "raw")) 223 250 downenc = 'R'; … … 234 261 { 235 262 lazymode = lazy_mode; 263 } 264 265 void 266 client_set_hostname_maxlen(int i) 267 { 268 if (i <= 0xFF) 269 hostname_maxlen = i; 236 270 } 237 271 … … 265 299 } 266 300 301 #if 0 302 fprintf(stderr, " Sendquery: id %5d name[0] '%c'\n", q.id, hostname[0]); 303 #endif 304 267 305 sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv)); 306 307 /* There are DNS relays that time out quickly but don't send anything 308 back on timeout. 309 And there are relays where, in lazy mode, our new query apparently 310 _replaces_ our previous query, and we get no answers at all in 311 lazy mode while legacy immediate-ping-pong works just fine. 312 Here we detect and fix these situations. 313 (Can't very well do this anywhere else; this is the only place 314 we'll reliably get to in such situations.) 315 */ 316 317 if (send_query_sendcnt >= 0 && send_query_sendcnt < 100 && lazymode) { 318 send_query_sendcnt++; 319 320 if ((send_query_sendcnt > 6 && send_query_recvcnt <= 0) || 321 (send_query_sendcnt > 10 && 322 4 * send_query_recvcnt < send_query_sendcnt)) { 323 if (selecttimeout > 1) { 324 warnx("Receiving too few answers. Setting interval to 1 (-I1)"); 325 selecttimeout = 1; 326 /* restart counting */ 327 send_query_sendcnt = 0; 328 send_query_recvcnt = 0; 329 } else if (lazymode) { 330 warnx("Receiving too few answers. Will try to switch lazy mode off, but that may not always work any more. Start with -L0 next time on this network."); 331 lazymode = 0; 332 selecttimeout = 1; 333 handshake_lazyoff(fd); 334 } 335 } 336 } 268 337 } 269 338 … … 302 371 buf[0] = cmd; 303 372 304 build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, b32); 373 build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, 374 b32, hostname_maxlen); 305 375 send_query(fd, buf); 306 376 } … … 319 389 int code; 320 390 char *p; 391 static int datacmc = 0; 392 char *datacmcchars = "abcdefghijklmnopqrstuvwxyz0123456789"; 321 393 322 394 p = outpkt.data; … … 324 396 avail = outpkt.len - outpkt.offset; 325 397 326 outpkt.sentlen = build_hostname(buf + 4, sizeof(buf) - 4, p, avail, topdomain, dataenc); 398 /* Note: must be same, or smaller than send_fragsize_probe() */ 399 outpkt.sentlen = build_hostname(buf + 5, sizeof(buf) - 5, p, avail, 400 topdomain, dataenc, hostname_maxlen); 327 401 328 402 /* Build upstream data header (see doc/proto_xxxxxxxx.txt) */ … … 338 412 code = ((inpkt.fragment & 15) << 1) | (outpkt.sentlen == avail); 339 413 buf[3] = b32_5to8(code); /* Fourth byte is 4 bits downstream fragment count, 1 bit last frag flag */ 414 415 buf[4] = datacmcchars[datacmc]; /* Fifth byte is data-CMC */ 416 datacmc++; 417 if (datacmc >= 36) 418 datacmc = 0; 340 419 341 420 #if 0 … … 373 452 374 453 static void 375 write_dns_error(struct query *q) 454 write_dns_error(struct query *q, int ignore_some_errors) 455 /* This is called from: 456 1. handshake_waitdns() when already checked that reply fits to our 457 latest query. 458 2. tunnel_dns() when already checked that reply is for our ping or data 459 packet, but not necessarily the most recent (SERVFAIL mostly comes 460 after long delay). 461 So ignorable errors are never printed. 462 */ 376 463 { 377 464 if (!q) return; … … 379 466 switch (q->rcode) { 380 467 case NOERROR: /* 0 */ 381 warnx("Got reply without error, but also without question and/or answer"); 468 if (!ignore_some_errors) 469 warnx("Got reply without error, but also without question and/or answer"); 382 470 break; 383 471 case FORMERR: /* 1 */ … … 385 473 break; 386 474 case SERVFAIL: /* 2 */ 387 warnx("Got SERVFAIL as reply: server failed or recursion timeout"); 475 if (!ignore_some_errors) 476 warnx("Got SERVFAIL as reply: server failed or recursion timeout"); 388 477 break; 389 478 case NXDOMAIN: /* 3 */ … … 403 492 404 493 static int 405 read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q) /* FIXME: tun_fd needed for raw handling */ 494 dns_namedec(char *outdata, int outdatalen, char *buf, int buflen) 495 /* Decodes *buf to *outdata. 496 * *buf WILL be changed by undotify. 497 * Note: buflen must be _exactly_ strlen(buf) before undotifying. 498 * (undotify of reduced-len won't copy \0, base-X decode will decode too much.) 499 * Returns #bytes usefully filled in outdata. 500 */ 501 { 502 size_t outdatalenu = outdatalen; 503 504 switch (buf[0]) { 505 case 'h': /* Hostname with base32 */ 506 case 'H': 507 /* Need 1 byte H, 3 bytes ".xy", >=1 byte data */ 508 if (buflen < 5) 509 return 0; 510 511 /* this also does undotify */ 512 return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, 513 b32); 514 515 case 'i': /* Hostname++ with base64 */ 516 case 'I': 517 /* Need 1 byte I, 3 bytes ".xy", >=1 byte data */ 518 if (buflen < 5) 519 return 0; 520 521 /* this also does undotify */ 522 return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, 523 b64); 524 525 case 'j': /* Hostname++ with base64u */ 526 case 'J': 527 /* Need 1 byte J, 3 bytes ".xy", >=1 byte data */ 528 if (buflen < 5) 529 return 0; 530 531 /* this also does undotify */ 532 return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, 533 b64u); 534 535 case 'k': /* Hostname++ with base128 */ 536 case 'K': 537 /* Need 1 byte J, 3 bytes ".xy", >=1 byte data */ 538 if (buflen < 5) 539 return 0; 540 541 /* this also does undotify */ 542 return unpack_data(outdata, outdatalen, buf + 1, buflen - 4, 543 b128); 544 545 case 't': /* plain base32(Thirty-two) from TXT */ 546 case 'T': 547 if (buflen < 2) 548 return 0; 549 550 return b32->decode(outdata, &outdatalenu, buf + 1, buflen - 1); 551 552 case 's': /* plain base64(Sixty-four) from TXT */ 553 case 'S': 554 if (buflen < 2) 555 return 0; 556 557 return b64->decode(outdata, &outdatalenu, buf + 1, buflen - 1); 558 559 case 'u': /* plain base64u (Underscore) from TXT */ 560 case 'U': 561 if (buflen < 2) 562 return 0; 563 564 return b64u->decode(outdata, &outdatalenu, buf + 1, buflen - 1); 565 566 case 'v': /* plain base128 from TXT */ 567 case 'V': 568 if (buflen < 2) 569 return 0; 570 571 return b128->decode(outdata, &outdatalenu, buf + 1, buflen - 1); 572 573 case 'r': /* Raw binary from TXT */ 574 case 'R': 575 /* buflen>=1 already checked */ 576 buflen--; 577 buflen = MIN(buflen, outdatalen); 578 memcpy(outdata, buf + 1, buflen); 579 return buflen; 580 581 default: 582 warnx("Received unsupported encoding"); 583 return 0; 584 } 585 586 /* notreached */ 587 return 0; 588 } 589 590 static int 591 read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q) 592 /* FIXME: tun_fd needed for raw handling */ 593 /* Returns -1 on receive error or decode error, including DNS error replies. 594 Returns 0 on replies that could be correct but are useless, and are not 595 DNS error replies. 596 Returns >0 on correct replies; value is #valid bytes in *buf. 597 */ 406 598 { 407 599 struct sockaddr_in from; … … 427 619 return rv; 428 620 429 if (q->type == T_CNAME || q->type == T_ MX || q->type == T_TXT)430 /* CNAME an also be returned from an A (or MX)question */621 if (q->type == T_CNAME || q->type == T_TXT) 622 /* CNAME can also be returned from an A question */ 431 623 { 432 size_t space;433 434 624 /* 435 625 * buf is a hostname or txt stream that we still need to … … 441 631 */ 442 632 443 switch (buf[0]) { 444 case 'h': /* Hostname with base32 */ 445 case 'H': 446 if (rv < 5) { 447 /* 1 byte H, 3 bytes ".xy", >=1 byte data */ 448 rv = 0; 633 rv = dns_namedec(data, sizeof(data), buf, rv); 634 635 rv = MIN(rv, buflen); 636 if (rv > 0) 637 memcpy(buf, data, rv); 638 639 } else if (q->type == T_MX || q->type == T_SRV) { 640 /* buf is like "Hname.com\0Hanother.com\0\0" */ 641 int buftotal = rv; /* idx of last \0 */ 642 int bufoffset = 0; 643 int dataoffset = 0; 644 int thispartlen, dataspace, datanew; 645 646 while (1) { 647 thispartlen = strlen(buf); 648 thispartlen = MIN(thispartlen, buftotal-bufoffset); 649 dataspace = sizeof(data) - dataoffset; 650 if (thispartlen <= 0 || dataspace <= 0) 449 651 break; 450 } 451 452 rv -= 3; /* rv=strlen, strip ".xy" */ 453 rv = unpack_data (data, sizeof(data), buf + 1, rv - 1, b32); 454 /* this also does undotify */ 455 456 rv = MIN(rv, buflen); 652 653 datanew = dns_namedec(data + dataoffset, dataspace, 654 buf + bufoffset, thispartlen); 655 if (datanew <= 0) 656 break; 657 658 bufoffset += thispartlen + 1; 659 dataoffset += datanew; 660 } 661 rv = dataoffset; 662 rv = MIN(rv, buflen); 663 if (rv > 0) 457 664 memcpy(buf, data, rv); 458 break;459 case 'i': /* Hostname++ with base64 */460 case 'I':461 if (rv < 5) {462 /* 1 byte H, 3 bytes ".xy", >=1 byte data */463 rv = 0;464 break;465 }466 467 rv -= 3; /* rv=strlen, strip ".xy" */468 rv = unpack_data (data, sizeof(data), buf + 1, rv - 1, b64);469 /* this also does undotify */470 471 rv = MIN(rv, buflen);472 memcpy(buf, data, rv);473 break;474 case 't': /* plain base32(Thirty-two) from TXT */475 case 'T':476 if (rv < 2) {477 rv = 0;478 break;479 }480 481 space = sizeof(data);482 rv = b32->decode (data, &space, buf + 1, rv - 1);483 rv = MIN(rv, buflen);484 memcpy(buf, data, rv);485 break;486 case 's': /* plain base64(Sixty-four) from TXT */487 case 'S':488 if (rv < 2) {489 rv = 0;490 break;491 }492 493 space = sizeof(data);494 rv = b64->decode (data, &space, buf + 1, rv - 1);495 rv = MIN(rv, buflen);496 memcpy(buf, data, rv);497 break;498 case 'r': /* Raw binary from TXT */499 case 'R':500 rv--; /* rv>=1 already checked */501 memmove(buf, buf+1, rv);502 break;503 default:504 warnx("Received unsupported encoding");505 rv = 0;506 break;507 }508 665 } 509 666 … … 517 674 /* should start with header */ 518 675 if (memcmp(data, raw_header, RAW_HDR_IDENT_LEN)) return 0; 676 /* should be my user id */ 677 if (RAW_HDR_GET_USR(data) != userid) return 0; 678 679 if (RAW_HDR_GET_CMD(data) == RAW_HDR_CMD_DATA || 680 RAW_HDR_GET_CMD(data) == RAW_HDR_CMD_PING) 681 lastdownstreamtime = time(NULL); 682 519 683 /* should be data packet */ 520 684 if (RAW_HDR_GET_CMD(data) != RAW_HDR_CMD_DATA) return 0; 521 /* should be my user id */522 if (RAW_HDR_GET_USR(data) != userid) return 0;523 685 524 686 r -= RAW_HDR_LEN; … … 527 689 write_tun(tun_fd, buf, datalen); 528 690 } 691 692 /* don't process any further */ 529 693 return 0; 530 694 } 531 695 } 532 696 533 static inline int 534 read_dns_namecheck(int dns_fd, int tun_fd, char *buf, int buflen, char c1, char c2) 535 /* Only returns >0 when the query hostname in the received packet matches 536 either c1 or c2; used to tell handshake-dupes apart. 697 static int 698 handshake_waitdns(int dns_fd, char *buf, int buflen, char c1, char c2, int timeout) 699 /* Wait for DNS reply fitting to our latest query and returns it. 700 Returns length of reply = #bytes used in buf. 701 Returns 0 if fitting reply happens to be useless. 702 Returns -2 on (at least) DNS error that fits to our latest query, 703 error message already printed. 704 Returns -3 on timeout (given in seconds). 705 Returns -1 on other errors. 706 707 Timeout is restarted when "wrong" (previous/delayed) replies are received, 708 so effective timeout may be longer than specified. 537 709 */ 538 710 { 539 711 struct query q; 540 int rv; 541 542 rv = read_dns_withq(dns_fd, tun_fd, buf, buflen, &q); 543 544 /* Filter out any other replies */ 545 if (q.name[0] != c1 && q.name[0] != c2) 546 return 0; 547 548 /* Print rcode errors */ 549 if (rv < 0) { 550 write_dns_error(&q); 551 } 552 553 return rv; /* may also be 0 = useless or -1 = error (printed) */ 712 int r, rv; 713 fd_set fds; 714 struct timeval tv; 715 716 while (1) { 717 tv.tv_sec = timeout; 718 tv.tv_usec = 0; 719 FD_ZERO(&fds); 720 FD_SET(dns_fd, &fds); 721 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 722 723 if (r < 0) 724 return -1; /* select error */ 725 if (r == 0) 726 return -3; /* select timeout */ 727 728 q.id = 0; 729 q.name[0] = '\0'; 730 rv = read_dns_withq(dns_fd, 0, buf, buflen, &q); 731 732 if (q.id != chunkid || (q.name[0] != c1 && q.name[0] != c2)) { 733 #if 0 734 fprintf(stderr, "Ignoring unfitting reply id %d starting with '%c'\n", q.id, q.name[0]); 735 #endif 736 continue; 737 } 738 739 /* if still here: reply matches our latest query */ 740 741 /* Non-recursive DNS servers (such as [a-m].root-servers.net) 742 return no answer, but only additional and authority records. 743 Can't explicitly test for that here, just assume that 744 NOERROR is such situation. Only trigger on the very first 745 requests (Y or V, depending if -T given). 746 */ 747 if (rv < 0 && q.rcode == NOERROR && 748 (q.name[0] == 'Y' || q.name[0] == 'y' || 749 q.name[0] == 'V' || q.name[0] == 'v')) { 750 fprintf(stderr, "Got empty reply. This nameserver may not be resolving recursively, use another.\n"); 751 fprintf(stderr, "Try \"iodine [options] ns.%s %s\" first, it might just work.\n", 752 topdomain, topdomain); 753 return -2; 754 } 755 756 /* If we get an immediate SERVFAIL on the handshake query 757 we're waiting for, wait a while before sending the next. 758 SERVFAIL reliably happens during fragsize autoprobe, but 759 mostly long after we've moved along to some other queries. 760 However, some DNS relays, once they throw a SERVFAIL, will 761 for several seconds apply it immediately to _any_ new query 762 for the same topdomain. When this happens, waiting a while 763 is the only option that works. 764 */ 765 if (rv < 0 && q.rcode == SERVFAIL) 766 sleep(1); 767 768 if (rv < 0) { 769 write_dns_error(&q, 1); 770 return -2; 771 } 772 /* rv either 0 or >0, return it as is. */ 773 return rv; 774 } 775 776 /* not reached */ 777 return -1; 554 778 } 555 779 … … 599 823 static long packrecv = 0; 600 824 static long packrecv_oos = 0; 825 static long packrecv_servfail = 0; 601 826 int up_ack_seqno; 602 827 int up_ack_fragment; … … 612 837 read = read_dns_withq(dns_fd, tun_fd, buf, sizeof(buf), &q); 613 838 614 /* Don't process anything that isn't data for us */ 839 if (conn != CONN_DNS_NULL) 840 return 1; /* everything already done */ 841 842 #if 0 843 fprintf(stderr, " Recv: id %5d name[0]='%c'\n", 844 q.id, q.name[0]); 845 #endif 846 847 /* Don't process anything that isn't data for us; usually error 848 replies from fragsize probes etc. However a sequence of those, 849 mostly 1 sec apart, will continuously break the >=2-second select 850 timeout, which means we won't send a proper ping for a while. 851 So make select a bit faster, <1sec. */ 615 852 if (q.name[0] != 'P' && q.name[0] != 'p' && 616 q.name[0] != userid_char && q.name[0] != userid_char2) 853 q.name[0] != userid_char && q.name[0] != userid_char2) { 854 send_ping_soon = 700; 617 855 return -1; /* nothing done */ 856 } 618 857 619 858 if (read < 2) { 620 859 /* Maybe SERVFAIL etc. Send ping to get things back in order, 621 860 but wait a bit to prevent fast ping-pong loops. */ 622 write_dns_error(&q); 861 862 if (read < 0) 863 write_dns_error(&q, 0); 864 865 if (read < 0 && q.rcode == SERVFAIL && lazymode && 866 selecttimeout > 1) { 867 if (packrecv < 500 && packrecv_servfail < 4) { 868 packrecv_servfail++; 869 warnx("Hmm, that's %ld. Your data should still go through...", packrecv_servfail); 870 } else if (packrecv < 500 && packrecv_servfail == 4) { 871 packrecv_servfail++; 872 warnx("I think %ld is too many. Setting interval to 1 to hopefully reduce SERVFAILs. But just ignore them if data still comes through. (Use -I1 next time on this network.)", packrecv_servfail); 873 selecttimeout = 1; 874 send_query_sendcnt = 0; 875 send_query_recvcnt = 0; 876 } else if (packrecv >= 500 && packrecv_servfail > 0) { 877 warnx("(Sorry, stopped counting; try -I1 if you experience hiccups.)"); 878 packrecv_servfail = 0; 879 } 880 } 881 882 /* read==1 happens with "QMEM" illegal replies, caused by 883 heavy reordering, or after short disconnections when 884 data-CMC has looped around into the "duplicate" values. 885 All these cases are helped by faster pinging. */ 886 #if 0 887 if (read == 1) 888 fprintf(stderr, " q=%c id %5d 1-byte illegal \"QMEM\" reply\n", q.name[0], q.id); 889 #endif 890 623 891 send_ping_soon = 900; 624 892 return -1; /* nothing done */ … … 644 912 645 913 #if 0 646 fprintf(stderr, " Recv:down %d/%d up %d/%d, %d bytes\n",647 new_down_seqno, new_down_fragment, up_ack_seqno,914 fprintf(stderr, " Recv: id %5d down %d/%d up %d/%d, %d bytes\n", 915 q.id, new_down_seqno, new_down_fragment, up_ack_seqno, 648 916 up_ack_fragment, read); 649 917 #endif … … 666 934 } 667 935 668 packrecv++; 669 670 /* Don't process any non-recent stuff any further */ 936 if (!(packrecv & 0x1000000)) 937 packrecv++; 938 send_query_recvcnt++; /* overflow doesn't matter */ 939 940 /* Don't process any non-recent stuff any further. 941 No need to remember more than 3 ids: in practice any older replies 942 arrive after new/current replies, and whatever data the old replies 943 have, it has become useless in the mean time. 944 Actually, ever since iodined is replying to both the original query 945 and the last dupe, this hardly triggers any more. 946 */ 671 947 if (q.id != chunkid && q.id != chunkid_prev && q.id != chunkid_prev2) { 672 948 packrecv_oos++; … … 674 950 fprintf(stderr, " q=%c Packs received = %8ld Out-of-sequence = %8ld\n", q.name[0], packrecv, packrecv_oos); 675 951 #endif 676 if (lazymode && packrecv < 600 && packrecv_oos == 5)677 warnx("Hmm, getting some out-of-sequence DNS replies. You may want to try -I1 or -L0 if you notice hiccups in the data traffic.");678 if (lazymode && packrecv < 600 && packrecv_oos == 15) {679 warnx("Your DNS server connection causes severe re-ordering of DNS traffic. Lazy mode doesn't work well here, switching off. Next time on this network, start with -L0.");680 lazymode = 0;952 if (lazymode && packrecv < 1000 && packrecv_oos == 5) { 953 if (selecttimeout > 1) 954 warnx("Hmm, getting some out-of-sequence DNS replies. Setting interval to 1 (use -I1 next time on this network). If data traffic still has large hiccups, try if -L0 works better."); 955 else 956 warnx("Hmm, getting some out-of-sequence DNS replies. If data traffic often has large hiccups, try running with -L0 ."); 681 957 selecttimeout = 1; 682 handshake_lazyoff(dns_fd); 958 send_query_sendcnt = 0; 959 send_query_recvcnt = 0; 683 960 } 684 961 … … 697 974 698 975 /* In lazy mode, we shouldn't get much replies to our most-recent 699 query, only during heavy data transfer. Except when severe packet 700 reordering occurs, such as opendns... Since this means the server 976 query, only during heavy data transfer. Since this means the server 701 977 doesn't have any packets left, send one relatively fast (but not 702 978 too fast, to avoid runaway ping-pong loops..) */ … … 857 1133 rv = 0; 858 1134 lastdownstreamtime = time(NULL); 1135 send_query_sendcnt = 0; /* start counting now */ 859 1136 860 1137 while (running) { … … 975 1252 probedata[1] = MAX(1, (rand_seed >> 8) & 0xff); 976 1253 rand_seed++; 977 build_hostname(buf + 4, sizeof(buf) - 4, probedata, sizeof(probedata), topdomain, dataenc); 1254 1255 /* Note: must either be same, or larger, than send_chunk() */ 1256 build_hostname(buf + 5, sizeof(buf) - 5, probedata, sizeof(probedata), 1257 topdomain, dataenc, hostname_maxlen); 978 1258 979 1259 fragsize &= 2047; … … 983 1263 buf[2] = b32_5to8((fragsize >> 5) & 31); 984 1264 buf[3] = b32_5to8(fragsize & 31); 1265 buf[4] = 'd'; /* dummy to match send_chunk() */ 985 1266 986 1267 send_query(fd, buf); … … 1018 1299 rand_seed++; 1019 1300 1020 send_packet(fd, ' V', data, sizeof(data));1301 send_packet(fd, 'v', data, sizeof(data)); 1021 1302 } 1022 1303 … … 1024 1305 send_ip_request(int fd, int userid) 1025 1306 { 1026 char buf[512] = " I____.";1307 char buf[512] = "i____."; 1027 1308 buf[1] = b32_5to8(userid); 1028 1309 … … 1046 1327 1047 1328 static void 1048 send_case_check(int fd) 1049 { 1050 /* The '+' plus character is not allowed according to RFC. 1051 * Expect to get SERVFAIL or similar if it is rejected. 1052 */ 1053 char buf[512] = "zZ+-aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY1234."; 1329 send_upenctest(int fd, char *s) 1330 /* NOTE: String may be at most 63-4=59 chars to fit in 1 dns chunk. */ 1331 { 1332 char buf[512] = "z___"; 1333 1334 buf[1] = b32_5to8((rand_seed >> 10) & 0x1f); 1335 buf[2] = b32_5to8((rand_seed >> 5) & 0x1f); 1336 buf[3] = b32_5to8((rand_seed ) & 0x1f); 1337 rand_seed++; 1338 1339 strncat(buf, s, 512); 1340 strncat(buf, ".", 512); 1341 strncat(buf, topdomain, 512 - strlen(buf)); 1342 send_query(fd, buf); 1343 } 1344 1345 static void 1346 send_downenctest(int fd, char downenc, int variant, char *s, int slen) 1347 /* Note: content/handling of s is not defined yet. */ 1348 { 1349 char buf[512] = "y_____."; 1350 1351 buf[1] = tolower(downenc); 1352 buf[2] = b32_5to8(variant); 1353 1354 buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); 1355 buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); 1356 buf[5] = b32_5to8((rand_seed ) & 0x1f); 1357 rand_seed++; 1054 1358 1055 1359 strncat(buf, topdomain, 512 - strlen(buf)); … … 1093 1397 send_lazy_switch(int fd, int userid) 1094 1398 { 1095 char buf[512] = "o__ .";1399 char buf[512] = "o_____."; 1096 1400 buf[1] = b32_5to8(userid); 1097 1401 … … 1101 1405 buf[2] = 'i'; 1102 1406 1407 buf[3] = b32_5to8((rand_seed >> 10) & 0x1f); 1408 buf[4] = b32_5to8((rand_seed >> 5) & 0x1f); 1409 buf[5] = b32_5to8((rand_seed ) & 0x1f); 1410 rand_seed++; 1411 1103 1412 strncat(buf, topdomain, 512 - strlen(buf)); 1104 1413 send_query(fd, buf); … … 1110 1419 char hex[] = "0123456789abcdef"; 1111 1420 char hex2[] = "0123456789ABCDEF"; 1112 struct timeval tv;1113 1421 char in[4096]; 1114 fd_set fds;1115 1422 uint32_t payload; 1116 1423 int i; 1117 int r;1118 1424 int read; 1119 1425 1120 1426 for (i = 0; running && i < 5; i++) { 1121 tv.tv_sec = i + 1;1122 tv.tv_usec = 0;1123 1427 1124 1428 send_version(dns_fd, VERSION); 1125 1126 FD_ZERO(&fds); 1127 FD_SET(dns_fd, &fds); 1128 1129 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1130 1131 if(r > 0) { 1132 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'v', 'V'); 1133 1134 if(read <= 0) 1135 continue; 1136 1429 1430 read = handshake_waitdns(dns_fd, in, sizeof(in), 'v', 'V', i+1); 1431 1432 /*XXX START adjust indent 1 tab back*/ 1137 1433 if (read >= 9) { 1138 1434 payload = (((in[4] & 0xff) << 24) | … … 1157 1453 return 1; 1158 1454 } 1159 } else 1455 } else if (read > 0) 1160 1456 warnx("did not receive proper login challenge"); 1161 }1457 /*XXX END adjust indent 1 tab back*/ 1162 1458 1163 1459 fprintf(stderr, "Retrying version check...\n"); … … 1170 1466 handshake_login(int dns_fd, int seed) 1171 1467 { 1172 struct timeval tv;1173 1468 char in[4096]; 1174 1469 char login[16]; … … 1176 1471 char client[65]; 1177 1472 int mtu; 1178 fd_set fds;1179 1473 int i; 1180 int r;1181 1474 int read; 1182 1475 … … 1184 1477 1185 1478 for (i=0; running && i<5 ;i++) { 1186 tv.tv_sec = i + 1;1187 tv.tv_usec = 0;1188 1479 1189 1480 send_login(dns_fd, login, 16); 1190 1191 FD_ZERO(&fds); 1192 FD_SET(dns_fd, &fds); 1193 1194 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1195 1196 if(r > 0) { 1197 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'l', 'L'); 1198 1199 if(read <= 0) 1200 continue; 1201 1481 1482 read = handshake_waitdns(dns_fd, in, sizeof(in), 'l', 'L', i+1); 1483 1484 /*XXX START adjust indent 1 tab back*/ 1202 1485 if (read > 0) { 1203 1486 int netmask; … … 1222 1505 } 1223 1506 } 1224 }1507 /*XXX END adjust indent 1 tab back*/ 1225 1508 1226 1509 fprintf(stderr, "Retrying login...\n"); … … 1242 1525 struct in_addr server; 1243 1526 1244 fprintf(stderr, "Testing raw UDP data to the server (skip with -r) \n");1527 fprintf(stderr, "Testing raw UDP data to the server (skip with -r)"); 1245 1528 for (i=0; running && i<3 ;i++) { 1246 tv.tv_sec = i + 1;1247 tv.tv_usec = 0;1248 1529 1249 1530 send_ip_request(dns_fd, userid); 1250 1251 FD_ZERO(&fds); 1252 FD_SET(dns_fd, &fds); 1253 1254 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1255 1256 if(r > 0) { 1257 len = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'i', 'I'); 1531 1532 len = handshake_waitdns(dns_fd, in, sizeof(in), 'i', 'I', i+1); 1533 1534 /*XXX START adjust indent 1 tab back*/ 1258 1535 if (len == 5 && in[0] == 'I') { 1259 1536 /* Received IP address */ … … 1268 1545 break; 1269 1546 } 1270 } else { 1271 fprintf(stderr, "."); 1272 fflush(stderr); 1273 } 1274 } 1547 /*XXX END adjust indent 1 tab back*/ 1548 1549 fprintf(stderr, "."); 1550 fflush(stderr); 1551 } 1552 fprintf(stderr, "\n"); 1553 if (!running) 1554 return 0; 1275 1555 1276 1556 if (!remoteaddr) { … … 1325 1605 1326 1606 static int 1327 handshake_case_check(int dns_fd) 1328 { 1329 struct timeval tv; 1607 handshake_upenctest(int dns_fd, char *s) 1608 /* NOTE: *s may be max 59 chars; must start with "aA" for case-swap check 1609 Returns: 1610 -1: case swap, no need for any further test: error printed; or Ctrl-C 1611 0: not identical or error or timeout 1612 1: identical string returned 1613 */ 1614 { 1330 1615 char in[4096]; 1331 fd_set fds; 1616 unsigned char *uin = (unsigned char *) in; 1617 unsigned char *us = (unsigned char *) s; 1332 1618 int i; 1333 int r;1334 1619 int read; 1335 int case_preserved; 1336 1337 case_preserved = 0; 1620 int slen; 1621 1622 slen = strlen(s); 1623 for (i=0; running && i<3 ;i++) { 1624 1625 send_upenctest(dns_fd, s); 1626 1627 read = handshake_waitdns(dns_fd, in, sizeof(in), 'z', 'Z', i+1); 1628 1629 if (read == -2) 1630 return 0; /* hard error */ 1631 1632 if (read > 0 && read < slen + 4) 1633 return 0; /* reply too short (chars dropped) */ 1634 1635 if (read > 0) { 1636 int k; 1637 #if 0 1638 /* in[56] = '@'; */ 1639 /* in[56] = '_'; */ 1640 /* if (in[29] == '\344') in[29] = 'a'; */ 1641 in[read] = '\0'; 1642 fprintf(stderr, "BounceReply: >%s<\n", in); 1643 #endif 1644 /* quick check if case swapped, to give informative error msg */ 1645 if (in[4] == 'A') { 1646 fprintf(stderr, "DNS queries get changed to uppercase, keeping upstream codec Base32\n"); 1647 return -1; 1648 } 1649 if (in[5] == 'a') { 1650 fprintf(stderr, "DNS queries get changed to lowercase, keeping upstream codec Base32\n"); 1651 return -1; 1652 } 1653 1654 for (k = 0; k < slen; k++) { 1655 if (in[k+4] != s[k]) { 1656 /* Definitely not reliable */ 1657 if (in[k+4] >= ' ' && in[k+4] <= '~' && 1658 s[k] >= ' ' && s[k] <= '~') { 1659 fprintf(stderr, "DNS query char '%c' gets changed into '%c'\n", 1660 s[k], in[k+4]); 1661 } else { 1662 fprintf(stderr, "DNS query char 0x%02X gets changed into 0x%02X\n", 1663 (unsigned int) us[k], 1664 (unsigned int) uin[k+4]); 1665 } 1666 return 0; 1667 } 1668 } 1669 /* if still here, then all okay */ 1670 return 1; 1671 } 1672 1673 fprintf(stderr, "Retrying upstream codec test...\n"); 1674 } 1675 1676 if (!running) 1677 return -1; 1678 1679 /* timeout */ 1680 return 0; 1681 } 1682 1683 static int 1684 handshake_upenc_autodetect(int dns_fd) 1685 /* Returns: 1686 0: keep Base32 1687 1: Base64 is okay 1688 2: Base64u is okay 1689 3: Base128 is okay 1690 */ 1691 { 1692 /* Note: max 59 chars, must start with "aA". 1693 pat64: If 0129 work, assume 3-8 are okay too. 1694 1695 RFC1035 par 2.3.1 states that [A-Z0-9-] allowed, but only 1696 [A-Z] as first, and [A-Z0-9] as last char _per label_. 1697 Test by having '-' as last char. 1698 */ 1699 char *pat64="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ+0129-"; 1700 char *pat64u="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ_0129-"; 1701 char *pat128a="aA-Aaahhh-Drink-mal-ein-J\344germeister-"; 1702 char *pat128b="aA-La-fl\373te-na\357ve-fran\347aise-est-retir\351-\340-Cr\350te"; 1703 char *pat128c="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; 1704 char *pat128d="aA0123456789\274\275\276\277" 1705 "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"; 1706 char *pat128e="aA" 1707 "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" 1708 "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" 1709 "\360\361\362\363\364\365\366\367\370\371\372\373\374\375"; 1710 int res; 1711 1712 /* Try Base128, starting very gently to not draw attention */ 1713 while (1) { 1714 res = handshake_upenctest(dns_fd, pat128a); 1715 if (res < 0) { 1716 /* DNS swaps case, msg already printed; or Ctrl-C */ 1717 return 0; 1718 } else if (res == 0) { 1719 /* Probably not okay, skip Base128 entirely */ 1720 break; 1721 } 1722 1723 res = handshake_upenctest(dns_fd, pat128b); 1724 if (res < 0) 1725 return 0; 1726 else if (res == 0) 1727 break; 1728 1729 /* if this works, we can test the real stuff */ 1730 1731 res = handshake_upenctest(dns_fd, pat128c); 1732 if (res < 0) 1733 return 0; 1734 else if (res == 0) 1735 break; 1736 1737 res = handshake_upenctest(dns_fd, pat128d); 1738 if (res < 0) 1739 return 0; 1740 else if (res == 0) 1741 break; 1742 1743 res = handshake_upenctest(dns_fd, pat128e); 1744 if (res < 0) 1745 return 0; 1746 else if (res == 0) 1747 break; 1748 1749 /* if still here, then base128 works completely */ 1750 return 3; 1751 } 1752 1753 /* Try Base64 (with plus sign) */ 1754 res = handshake_upenctest(dns_fd, pat64); 1755 if (res < 0) { 1756 /* DNS swaps case, msg already printed; or Ctrl-C */ 1757 return 0; 1758 } else if (res > 0) { 1759 /* All okay, Base64 msg will be printed later */ 1760 return 1; 1761 } 1762 1763 /* Try Base64u (with _u_nderscore) */ 1764 res = handshake_upenctest(dns_fd, pat64u); 1765 if (res < 0) { 1766 /* DNS swaps case, msg already printed; or Ctrl-C */ 1767 return 0; 1768 } else if (res > 0) { 1769 /* All okay, Base64u msg will be printed later */ 1770 return 2; 1771 } 1772 1773 /* if here, then nonthing worked */ 1774 fprintf(stderr, "Keeping upstream codec Base32\n"); 1775 return 0; 1776 } 1777 1778 static int 1779 handshake_downenctest(int dns_fd, char trycodec) 1780 /* Returns: 1781 0: not identical or error or timeout 1782 1: identical string returned 1783 */ 1784 { 1785 char in[4096]; 1786 int i; 1787 int read; 1788 char *s = DOWNCODECCHECK1; 1789 int slen = DOWNCODECCHECK1_LEN; 1790 1791 for (i=0; running && i<3 ;i++) { 1792 1793 send_downenctest(dns_fd, trycodec, 1, NULL, 0); 1794 1795 read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', i+1); 1796 1797 if (read == -2) 1798 return 0; /* hard error */ 1799 1800 if (read > 0 && read != slen) 1801 return 0; /* reply incorrect = unreliable */ 1802 1803 if (read > 0) { 1804 int k; 1805 for (k = 0; k < slen; k++) { 1806 if (in[k] != s[k]) { 1807 /* Definitely not reliable */ 1808 return 0; 1809 } 1810 } 1811 /* if still here, then all okay */ 1812 return 1; 1813 } 1814 1815 fprintf(stderr, "Retrying downstream codec test...\n"); 1816 } 1817 1818 /* timeout */ 1819 return 0; 1820 } 1821 1822 static char 1823 handshake_downenc_autodetect(int dns_fd) 1824 /* Returns codec char (or ' ' if no advanced codec works) */ 1825 { 1826 int base64ok = 0; 1827 int base64uok = 0; 1828 int base128ok = 0; 1829 1830 if (do_qtype == T_NULL) { 1831 /* no other choice than raw */ 1832 fprintf(stderr, "No alternative downstream codec available, using default (Raw)\n"); 1833 return ' '; 1834 } 1835 1836 fprintf(stderr, "Autodetecting downstream codec (use -O to override)\n"); 1837 1838 /* Try Base64 */ 1839 if (handshake_downenctest(dns_fd, 'S')) 1840 base64ok = 1; 1841 else if (running && handshake_downenctest(dns_fd, 'U')) 1842 base64uok = 1; 1843 1844 /* Try Base128 only if 64 gives us some perspective */ 1845 if (running && (base64ok || base64uok)) { 1846 if (handshake_downenctest(dns_fd, 'V')) 1847 base128ok = 1; 1848 } 1849 1850 /* If 128 works, then TXT may give us Raw as well */ 1851 if (running && (base128ok && do_qtype == T_TXT)) { 1852 if (handshake_downenctest(dns_fd, 'R')) 1853 return 'R'; 1854 } 1855 1856 if (!running) 1857 return ' '; 1858 1859 if (base128ok) 1860 return 'V'; 1861 if (base64ok) 1862 return 'S'; 1863 if (base64uok) 1864 return 'U'; 1865 1866 fprintf(stderr, "No advanced downstream codecs seem to work, using default (Base32)\n"); 1867 return ' '; 1868 } 1869 1870 static int 1871 handshake_qtypetest(int dns_fd, int timeout) 1872 /* Returns: 1873 0: doesn't work with this timeout 1874 1: works properly 1875 */ 1876 { 1877 char in[4096]; 1878 int read; 1879 char *s = DOWNCODECCHECK1; 1880 int slen = DOWNCODECCHECK1_LEN; 1881 int trycodec; 1882 int k; 1883 1884 if (do_qtype == T_NULL) 1885 trycodec = 'R'; 1886 else 1887 trycodec = 'T'; 1888 1889 /* We could use 'Z' bouncing here, but 'Y' also tests that 0-255 1890 byte values can be returned, which is needed for NULL to work. */ 1891 1892 send_downenctest(dns_fd, trycodec, 1, NULL, 0); 1893 1894 read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', timeout); 1895 1896 if (read != slen) 1897 return 0; /* incorrect */ 1898 1899 for (k = 0; k < slen; k++) { 1900 if (in[k] != s[k]) { 1901 /* corrupted */ 1902 return 0; 1903 } 1904 } 1905 1906 /* if still here, then all okay */ 1907 return 1; 1908 } 1909 1910 static int 1911 handshake_qtype_numcvt(int num) 1912 { 1913 switch (num) { 1914 case 0: return T_NULL; 1915 case 1: return T_TXT; 1916 case 2: return T_SRV; 1917 case 3: return T_MX; 1918 case 4: return T_CNAME; 1919 case 5: return T_A; 1920 } 1921 return T_UNSET; 1922 } 1923 1924 static int 1925 handshake_qtype_autodetect(int dns_fd) 1926 /* Returns: 1927 0: okay, do_qtype set 1928 1: problem, program exit 1929 */ 1930 { 1931 int highestworking = 100; 1932 int timeout; 1933 int qtypenum; 1934 1935 fprintf(stderr, "Autodetecting DNS query type (use -T to override)"); 1936 fflush(stderr); 1937 1938 /* Method: try all "interesting" qtypes with a 1-sec timeout, then try 1939 all "still-interesting" qtypes with a 2-sec timeout, etc. 1940 "Interesting" means: qtypes that (are expected to) have higher 1941 bandwidth than what we know is working already (highestworking). 1942 1943 Note that DNS relays may not immediately resolve the first (NULL) 1944 query in 1 sec, due to long recursive lookups, so we keep trying 1945 to see if things will start working after a while. 1946 */ 1947 1948 for (timeout = 1; running && timeout <= 3; timeout++) { 1949 for (qtypenum = 0; running && qtypenum < highestworking; qtypenum++) { 1950 do_qtype = handshake_qtype_numcvt(qtypenum); 1951 if (do_qtype == T_UNSET) 1952 break; /* this round finished */ 1953 1954 fprintf(stderr, "."); 1955 fflush(stderr); 1956 1957 if (handshake_qtypetest(dns_fd, timeout)) { 1958 /* okay */ 1959 highestworking = qtypenum; 1960 #if 0 1961 fprintf(stderr, " Type %s timeout %d works\n", 1962 get_qtype(), timeout); 1963 #endif 1964 break; 1965 /* try others with longer timeout */ 1966 } 1967 /* else: try next qtype with same timeout */ 1968 } 1969 if (highestworking == 0) 1970 /* good, we have NULL; abort immediately */ 1971 break; 1972 } 1973 1974 fprintf(stderr, "\n"); 1975 1976 if (!running) { 1977 warnx("Stopped while autodetecting DNS query type (try setting manually with -T)"); 1978 return 1; /* problem */ 1979 } 1980 1981 /* finished */ 1982 do_qtype = handshake_qtype_numcvt(highestworking); 1983 1984 if (do_qtype == T_UNSET) { 1985 /* also catches highestworking still 100 */ 1986 warnx("No suitable DNS query type found. Are you connected to a network?"); 1987 warnx("If you expect very long roundtrip delays, use -T explicitly."); 1988 warnx("(Also, connecting to an \"ancient\" version of iodined won't work.)"); 1989 return 1; /* problem */ 1990 } 1991 1992 /* "using qtype" message printed in handshake function */ 1993 return 0; /* okay */ 1994 } 1995 1996 static int 1997 handshake_edns0_check(int dns_fd) 1998 /* Returns: 1999 0: EDNS0 not supported; or Ctrl-C 2000 1: EDNS0 works 2001 */ 2002 { 2003 char in[4096]; 2004 int i; 2005 int read; 2006 char *s = DOWNCODECCHECK1; 2007 int slen = DOWNCODECCHECK1_LEN; 2008 char trycodec; 2009 2010 if (do_qtype == T_NULL) 2011 trycodec = 'R'; 2012 else 2013 trycodec = 'T'; 2014 2015 for (i=0; running && i<3 ;i++) { 2016 2017 send_downenctest(dns_fd, trycodec, 1, NULL, 0); 2018 2019 read = handshake_waitdns(dns_fd, in, sizeof(in), 'y', 'Y', i+1); 2020 2021 if (read == -2) 2022 return 0; /* hard error */ 2023 2024 if (read > 0 && read != slen) 2025 return 0; /* reply incorrect = unreliable */ 2026 2027 if (read > 0) { 2028 int k; 2029 for (k = 0; k < slen; k++) { 2030 if (in[k] != s[k]) { 2031 /* Definitely not reliable */ 2032 return 0; 2033 } 2034 } 2035 /* if still here, then all okay */ 2036 return 1; 2037 } 2038 2039 fprintf(stderr, "Retrying EDNS0 support test...\n"); 2040 } 2041 2042 /* timeout or Ctrl-C */ 2043 return 0; 2044 } 2045 2046 static void 2047 handshake_switch_codec(int dns_fd, int bits) 2048 { 2049 char in[4096]; 2050 int i; 2051 int read; 2052 struct encoder *tempenc; 2053 2054 if (bits == 5) 2055 tempenc = get_base32_encoder(); 2056 else if (bits == 6) 2057 tempenc = get_base64_encoder(); 2058 else if (bits == 26) /* "2nd" 6 bits per byte, with underscore */ 2059 tempenc = get_base64u_encoder(); 2060 else if (bits == 7) 2061 tempenc = get_base128_encoder(); 2062 else return; 2063 2064 fprintf(stderr, "Switching upstream to codec %s\n", tempenc->name); 2065 1338 2066 for (i=0; running && i<5 ;i++) { 1339 tv.tv_sec = i + 1;1340 tv.tv_usec = 0;1341 1342 send_case_check(dns_fd);1343 1344 FD_ZERO(&fds);1345 FD_SET(dns_fd, &fds);1346 1347 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);1348 1349 if(r > 0) {1350 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'z', 'Z');1351 1352 if (read > 0) {1353 if (read < (27 * 2)) {1354 fprintf(stderr, "Received short case check reply. Will use base32 encoder\n");1355 return case_preserved;1356 } else {1357 int k;1358 1359 /* TODO enhance this, base128 is probably also possible */1360 case_preserved = 1;1361 for (k = 0; k < 27 && case_preserved; k += 2) {1362 if (in[k] == in[k+1]) {1363 /* test string: zZ+-aAbBcCdDeE... */1364 case_preserved = 0;1365 }1366 }1367 return case_preserved;1368 }1369 } else {1370 fprintf(stderr, "Got error on case check, will use base32\n");1371 return case_preserved;1372 }1373 }1374 1375 fprintf(stderr, "Retrying case check...\n");1376 }1377 1378 fprintf(stderr, "No reply on case check, continuing\n");1379 return case_preserved;1380 }1381 1382 static void1383 handshake_switch_codec(int dns_fd)1384 {1385 struct timeval tv;1386 char in[4096];1387 fd_set fds;1388 int i;1389 int r;1390 int read;1391 1392 dataenc = get_base64_encoder();1393 fprintf(stderr, "Switching upstream to %s codec\n", dataenc->name);1394 /* Send to server that this user will use base64 from now on */1395 for (i=0; running && i<5 ;i++) {1396 int bits;1397 tv.tv_sec = i + 1;1398 tv.tv_usec = 0;1399 1400 bits = 6; /* base64 = 6 bits per byte */1401 2067 1402 2068 send_codec_switch(dns_fd, userid, bits); 1403 2069 1404 FD_ZERO(&fds); 1405 FD_SET(dns_fd, &fds); 1406 1407 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1408 1409 if(r > 0) { 1410 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 's', 'S'); 1411 2070 read = handshake_waitdns(dns_fd, in, sizeof(in), 's', 'S', i+1); 2071 2072 /*XXX START adjust indent 1 tab back*/ 1412 2073 if (read > 0) { 1413 2074 if (strncmp("BADLEN", in, 6) == 0) { … … 1423 2084 in[read] = 0; /* zero terminate */ 1424 2085 fprintf(stderr, "Server switched upstream to codec %s\n", in); 2086 dataenc = tempenc; 1425 2087 return; 1426 2088 } 1427 } 2089 /*XXX END adjust indent 1 tab back*/ 2090 1428 2091 fprintf(stderr, "Retrying codec switch...\n"); 1429 2092 } 2093 if (!running) 2094 return; 2095 1430 2096 fprintf(stderr, "No reply from server on codec switch. "); 1431 2097 1432 2098 codec_revert: 1433 fprintf(stderr, "Falling back to base32\n"); 1434 dataenc = get_base32_encoder(); 2099 fprintf(stderr, "Falling back to upstream codec %s\n", dataenc->name); 1435 2100 } 1436 2101 … … 1438 2103 handshake_switch_downenc(int dns_fd) 1439 2104 { 1440 struct timeval tv;1441 2105 char in[4096]; 1442 fd_set fds;1443 2106 int i; 1444 int r;1445 2107 int read; 1446 2108 char *dname; … … 1449 2111 if (downenc == 'S') 1450 2112 dname = "Base64"; 2113 else if (downenc == 'U') 2114 dname = "Base64u"; 2115 else if (downenc == 'V') 2116 dname = "Base128"; 1451 2117 else if (downenc == 'R') 1452 2118 dname = "Raw"; … … 1454 2120 fprintf(stderr, "Switching downstream to codec %s\n", dname); 1455 2121 for (i=0; running && i<5 ;i++) { 1456 tv.tv_sec = i + 1;1457 tv.tv_usec = 0;1458 2122 1459 2123 send_downenc_switch(dns_fd, userid); 1460 2124 1461 FD_ZERO(&fds); 1462 FD_SET(dns_fd, &fds); 1463 1464 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1465 1466 if(r > 0) { 1467 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'o', 'O'); 1468 2125 read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1); 2126 2127 /*XXX START adjust indent 1 tab back*/ 1469 2128 if (read > 0) { 1470 2129 if (strncmp("BADLEN", in, 6) == 0) { … … 1482 2141 return; 1483 2142 } 1484 } 2143 /*XXX END adjust indent 1 tab back*/ 2144 1485 2145 fprintf(stderr, "Retrying codec switch...\n"); 1486 2146 } 2147 if (!running) 2148 return; 2149 1487 2150 fprintf(stderr, "No reply from server on codec switch. "); 1488 2151 1489 2152 codec_revert: 1490 fprintf(stderr, "Falling back to base32\n");2153 fprintf(stderr, "Falling back to downstream codec Base32\n"); 1491 2154 } 1492 2155 … … 1494 2157 handshake_try_lazy(int dns_fd) 1495 2158 { 1496 struct timeval tv;1497 2159 char in[4096]; 1498 fd_set fds;1499 2160 int i; 1500 int r;1501 2161 int read; 1502 2162 1503 2163 fprintf(stderr, "Switching to lazy mode for low-latency\n"); 1504 for (i=0; running && i<3; i++) { 1505 tv.tv_sec = i + 1; 1506 tv.tv_usec = 0; 2164 for (i=0; running && i<5; i++) { 1507 2165 1508 2166 send_lazy_switch(dns_fd, userid); 1509 2167 1510 FD_ZERO(&fds); 1511 FD_SET(dns_fd, &fds); 1512 1513 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1514 1515 if(r > 0) { 1516 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'o', 'O'); 1517 2168 read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', i+1); 2169 2170 /*XXX START adjust indent 1 tab back*/ 1518 2171 if (read > 0) { 1519 2172 if (strncmp("BADLEN", in, 6) == 0) { … … 1532 2185 } 1533 2186 } 1534 } 2187 /*XXX END adjust indent 1 tab back*/ 2188 1535 2189 fprintf(stderr, "Retrying lazy mode switch...\n"); 1536 2190 } 1537 fprintf(stderr, "No reply from server on lazy switch, probably old server version. "); 2191 if (!running) 2192 return; 2193 2194 fprintf(stderr, "No reply from server on lazy switch. "); 1538 2195 1539 2196 codec_revert: … … 1547 2204 /* Used in the middle of data transfer, timing is different and no error msgs */ 1548 2205 { 1549 struct timeval tv;1550 2206 char in[4096]; 1551 fd_set fds;1552 2207 int i; 1553 int r;1554 2208 int read; 1555 2209 1556 2210 for (i=0; running && i<5; i++) { 1557 tv.tv_sec = 0;1558 tv.tv_usec = 500000;1559 2211 1560 2212 send_lazy_switch(dns_fd, userid); 1561 2213 1562 FD_ZERO(&fds); 1563 FD_SET(dns_fd, &fds); 1564 1565 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1566 1567 if(r > 0) { 1568 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'o', 'O'); 1569 1570 if (read > 0) { 1571 if (read == 4 && strncmp("Immediate", in, 9) == 0) { 1572 fprintf(stderr, "Server switched back to legacy mode.\n"); 2214 read = handshake_waitdns(dns_fd, in, sizeof(in), 'o', 'O', 1); 2215 2216 /*XXX START adjust indent 2 tabs back*/ 2217 if (read == 9 && strncmp("Immediate", in, 9) == 0) { 2218 warnx("Server switched back to legacy mode.\n"); 1573 2219 lazymode = 0; 1574 2220 selecttimeout = 1; 1575 2221 return; 1576 2222 } 1577 } 1578 } 1579 } 2223 /*XXX END adjust indent 2 tabs back*/ 2224 } 2225 if (!running) 2226 return; 2227 2228 warnx("No reply from server on legacy mode switch.\n"); 1580 2229 } 1581 2230 … … 1585 2234 { 1586 2235 int acked_fragsize = ((in[0] & 0xff) << 8) | (in[1] & 0xff); 1587 static int nocheck_warned = 0; 2236 int okay; 2237 int i; 2238 unsigned int v; 1588 2239 1589 2240 if (read >= 5 && strncmp("BADIP", in, 5) == 0) { … … 1614 2265 /* in[123] = 123; */ 1615 2266 2267 if ((in[2] & 0xff) != 107) { 2268 fprintf(stderr, "\n"); 2269 warnx("corruption at byte 2, this won't work. Try -O Base32, or other -T options."); 2270 *max_fragsize = -1; 2271 return 1; 2272 } 2273 1616 2274 /* Check for corruption */ 1617 if ((in[2] & 0xff) == 107) { 1618 int okay = 1; 1619 int i; 1620 unsigned int v = in[3] & 0xff; 1621 1622 for (i = 3; i < read; i++, v += 107) 1623 if ((in[i] & 0xff) != (v & 0xff)) { 2275 okay = 1; 2276 v = in[3] & 0xff; 2277 2278 /*XXX START adjust indent 1 tab back*/ 2279 for (i = 3; i < read; i++, v = (v + 107) & 0xff) 2280 if ((in[i] & 0xff) != v) { 1624 2281 okay = 0; 1625 2282 break; … … 1636 2293 } else { 1637 2294 fprintf(stderr, "%d corrupted at %d.. ", acked_fragsize, i); 1638 fflush(stderr);1639 2295 } 2296 fflush(stderr); 1640 2297 return 1; 1641 2298 } 1642 } /* always returns */ 1643 1644 /* here when uncheckable, so assume correct */ 1645 1646 if (read >= 3 && nocheck_warned == 0) { 1647 fprintf(stderr, "(Old server version, cannot check for corruption)\n"); 1648 fflush(stderr); 1649 nocheck_warned = 1; 1650 } 1651 fprintf(stderr, "%d ok.. ", acked_fragsize); 1652 fflush(stderr); 1653 *max_fragsize = acked_fragsize; 2299 /*XXX END adjust indent 1 tab back*/ 2300 2301 /* notreached */ 1654 2302 return 1; 1655 2303 } … … 1659 2307 handshake_autoprobe_fragsize(int dns_fd) 1660 2308 { 1661 struct timeval tv;1662 2309 char in[4096]; 1663 fd_set fds;1664 2310 int i; 1665 int r;1666 2311 int read; 1667 2312 int proposed_fragsize = 768; … … 1674 2319 /* stop the slow probing early when we have enough bytes anyway */ 1675 2320 for (i=0; running && i<3 ;i++) { 1676 tv.tv_sec = 1; 1677 tv.tv_usec = 0; 2321 1678 2322 send_fragsize_probe(dns_fd, proposed_fragsize); 1679 2323 1680 FD_ZERO(&fds); 1681 FD_SET(dns_fd, &fds); 1682 1683 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1684 1685 if(r > 0) { 1686 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'r', 'R'); 2324 read = handshake_waitdns(dns_fd, in, sizeof(in), 'r', 'R', 1); 1687 2325 2326 /*XXX START adjust indent 1 tab back*/ 1688 2327 if (read > 0) { 1689 2328 /* We got a reply */ … … 1691 2330 break; 1692 2331 } 1693 } 2332 /*XXX END adjust indent 1 tab back*/ 2333 1694 2334 fprintf(stderr, "."); 1695 2335 fflush(stderr); 1696 2336 } 2337 if (max_fragsize < 0) 2338 break; 2339 1697 2340 range >>= 1; 1698 2341 if (max_fragsize == proposed_fragsize) { … … 1712 2355 } 1713 2356 if (max_fragsize <= 2) { 1714 /* Tried all the way down to 2 and found no good size */ 2357 /* Tried all the way down to 2 and found no good size. 2358 But we _did_ do all handshake before this, so there must 2359 be some workable connection. */ 1715 2360 fprintf(stderr, "\n"); 1716 warnx("found no accepted fragment size. (Try forcing with -m, or try other -T or -O options)"); 2361 warnx("found no accepted fragment size."); 2362 warnx("try setting -M to 200 or lower, or try other -T or -O options."); 1717 2363 return 0; 1718 2364 } … … 1720 2366 fprintf(stderr, "will use %d-2=%d\n", max_fragsize, max_fragsize - 2); 1721 2367 1722 if (do_qtype != T_NULL && downenc == ' ') 1723 fprintf(stderr, "(Maybe other -O options will increase throughput)\n"); 2368 /* need 1200 / 16frags = 75 bytes fragsize */ 2369 if (max_fragsize < 82) { 2370 fprintf(stderr, "Note: this probably won't work well.\n"); 2371 fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n"); 2372 } else if (max_fragsize < 202 && 2373 (do_qtype == T_NULL || do_qtype == T_TXT || 2374 do_qtype == T_SRV || do_qtype == T_MX)) { 2375 fprintf(stderr, "Note: this isn't very much.\n"); 2376 fprintf(stderr, "Try setting -M to 200 or lower, or try other DNS types (-T option).\n"); 2377 } 1724 2378 1725 2379 return max_fragsize - 2; … … 1729 2383 handshake_set_fragsize(int dns_fd, int fragsize) 1730 2384 { 1731 struct timeval tv;1732 2385 char in[4096]; 1733 fd_set fds;1734 2386 int i; 1735 int r;1736 2387 int read; 1737 2388 1738 2389 fprintf(stderr, "Setting downstream fragment size to max %d...\n", fragsize); 1739 2390 for (i=0; running && i<5 ;i++) { 1740 tv.tv_sec = i + 1;1741 tv.tv_usec = 0;1742 2391 1743 2392 send_set_downstream_fragsize(dns_fd, fragsize); 1744 1745 FD_ZERO(&fds); 1746 FD_SET(dns_fd, &fds); 1747 1748 r = select(dns_fd + 1, &fds, NULL, NULL, &tv); 1749 1750 if(r > 0) { 1751 read = read_dns_namecheck(dns_fd, 0, in, sizeof(in), 'n', 'N'); 1752 2393 2394 read = handshake_waitdns(dns_fd, in, sizeof(in), 'n', 'N', i+1); 2395 2396 /*XXX START adjust indent 1 tab back*/ 1753 2397 if (read > 0) { 1754 2398 int accepted_fragsize; … … 1765 2409 return; 1766 2410 } 1767 } 2411 /*XXX END adjust indent 1 tab back*/ 2412 1768 2413 fprintf(stderr, "Retrying set fragsize...\n"); 1769 2414 } 2415 if (!running) 2416 return; 2417 1770 2418 fprintf(stderr, "No reply from server when setting fragsize. Keeping default.\n"); 1771 2419 } … … 1775 2423 { 1776 2424 int seed; 1777 int case_preserved;2425 int upcodec; 1778 2426 int r; 2427 2428 dnsc_use_edns0 = 0; 2429 2430 /* qtype message printed in handshake function */ 2431 if (do_qtype == T_UNSET) { 2432 r = handshake_qtype_autodetect(dns_fd); 2433 if (r) { 2434 return r; 2435 } 2436 } 2437 2438 fprintf(stderr, "Using DNS type %s queries\n", get_qtype()); 1779 2439 1780 2440 r = handshake_version(dns_fd, &seed); … … 1795 2455 fprintf(stderr, "Skipping raw mode\n"); 1796 2456 } 1797 case_preserved = handshake_case_check(dns_fd); 1798 1799 if (case_preserved) { 1800 handshake_switch_codec(dns_fd); 1801 } 2457 2458 dnsc_use_edns0 = 1; 2459 if (handshake_edns0_check(dns_fd) && running) { 2460 fprintf(stderr, "Using EDNS0 extension\n"); 2461 } else if (!running) { 2462 return -1; 2463 } else { 2464 fprintf(stderr, "DNS relay does not support EDNS0 extension\n"); 2465 dnsc_use_edns0 = 0; 2466 } 2467 2468 upcodec = handshake_upenc_autodetect(dns_fd); 2469 if (!running) 2470 return -1; 2471 2472 if (upcodec == 1) { 2473 handshake_switch_codec(dns_fd, 6); 2474 } else if (upcodec == 2) { 2475 handshake_switch_codec(dns_fd, 26); 2476 } else if (upcodec == 3) { 2477 handshake_switch_codec(dns_fd, 7); 2478 } 2479 if (!running) 2480 return -1; 2481 2482 if (downenc == ' ') { 2483 downenc = handshake_downenc_autodetect(dns_fd); 2484 } 2485 if (!running) 2486 return -1; 1802 2487 1803 2488 if (downenc != ' ') { 1804 2489 handshake_switch_downenc(dns_fd); 1805 2490 } 2491 if (!running) 2492 return -1; 1806 2493 1807 2494 if (lazymode) { 1808 2495 handshake_try_lazy(dns_fd); 1809 2496 } 2497 if (!running) 2498 return -1; 1810 2499 1811 2500 if (autodetect_frag_size) { … … 1817 2506 1818 2507 handshake_set_fragsize(dns_fd, fragsize); 2508 if (!running) 2509 return -1; 1819 2510 } 1820 2511 -
src/client.h
r3c4860 rb17790 28 28 void client_set_password(const char *cp); 29 29 void set_qtype(char *qtype); 30 char *get_qtype(); 30 31 void set_downenc(char *encoding); 31 32 void client_set_selecttimeout(int select_timeout); 32 33 void client_set_lazymode(int lazy_mode); 34 void client_set_hostname_maxlen(int i); 33 35 34 36 int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, int fragsize); -
src/common.h
r269499 rb17790 75 75 #endif 76 76 77 #define T_UNSET 65432 78 /* Unused RR type; "private use" range, see http://www.bind9.net/dns-parameters */ 79 77 80 struct packet 78 81 { … … 90 93 unsigned short rcode; 91 94 unsigned short id; 92 unsigned short iddupe; /* only used for dupe checking */93 95 struct in_addr destination; 94 96 struct sockaddr from; 95 97 int fromlen; 98 unsigned short id2; 99 struct sockaddr from2; 100 int fromlen2; 96 101 }; 97 102 -
src/dns.c
racd264 rb17790 40 40 #include "read.h" 41 41 42 int dnsc_use_edns0 = 1; 43 42 44 #define CHECKLEN(x) if (buflen - (p-buf) < (x)) return 0 43 45 … … 49 51 char *p; 50 52 int len; 53 int ancnt; 51 54 52 55 if (buflen < sizeof(HEADER)) … … 69 72 switch (qr) { 70 73 case QR_ANSWER: 71 header->ancount = htons(1);72 74 header->qdcount = htons(1); 73 75 … … 82 84 83 85 /* Answer section */ 84 CHECKLEN(10); 85 putshort(&p, name); 86 if (q->type == T_A) 87 putshort(&p, T_CNAME); /* answer CNAME to A question */ 88 else 89 putshort(&p, q->type); 90 putshort(&p, C_IN); 91 putlong(&p, 0); /* TTL */ 92 93 if (q->type == T_CNAME || q->type == T_A || q->type == T_MX) { 86 87 if (q->type == T_CNAME || q->type == T_A) { 94 88 /* data is expected to be like "Hblabla.host.name.com\0" */ 95 89 96 char *startp = p;90 char *startp; 97 91 int namelen; 98 92 93 CHECKLEN(10); 94 putshort(&p, name); 95 if (q->type == T_A) 96 /* answer CNAME to A question */ 97 putshort(&p, T_CNAME); 98 else 99 putshort(&p, q->type); 100 putshort(&p, C_IN); 101 putlong(&p, 0); /* TTL */ 102 103 startp = p; 99 104 p += 2; /* skip 2 bytes length */ 100 CHECKLEN(2);101 if (q->type == T_MX)102 putshort(&p, 10); /* preference */103 105 putname(&p, buflen - (p - buf), data); 104 106 CHECKLEN(0); … … 106 108 namelen -= 2; 107 109 putshort(&startp, namelen); 110 ancnt = 1; 111 } else if (q->type == T_MX || q->type == T_SRV) { 112 /* Data is expected to be like 113 "Hblabla.host.name.com\0Hanother.com\0\0" 114 For SRV, see RFC2782. 115 */ 116 117 char *mxdata = data; 118 char *startp; 119 int namelen; 120 121 ancnt = 1; 122 while (1) { 123 CHECKLEN(10); 124 putshort(&p, name); 125 putshort(&p, q->type); 126 putshort(&p, C_IN); 127 putlong(&p, 0); /* TTL */ 128 129 startp = p; 130 p += 2; /* skip 2 bytes length */ 131 CHECKLEN(2); 132 putshort(&p, 10 * ancnt); /* preference */ 133 134 if (q->type == T_SRV) { 135 /* weight, port (5060 = SIP) */ 136 CHECKLEN(4); 137 putshort(&p, 10); 138 putshort(&p, 5060); 139 } 140 141 putname(&p, buflen - (p - buf), mxdata); 142 CHECKLEN(0); 143 namelen = p - startp; 144 namelen -= 2; 145 putshort(&startp, namelen); 146 147 mxdata = mxdata + strlen(mxdata) + 1; 148 if (*mxdata == '\0') 149 break; 150 151 ancnt++; 152 } 108 153 } else if (q->type == T_TXT) { 109 154 /* TXT has binary or base-X data */ 110 char *startp = p;155 char *startp; 111 156 int txtlen; 112 157 158 CHECKLEN(10); 159 putshort(&p, name); 160 putshort(&p, q->type); 161 putshort(&p, C_IN); 162 putlong(&p, 0); /* TTL */ 163 164 startp = p; 113 165 p += 2; /* skip 2 bytes length */ 114 166 puttxtbin(&p, buflen - (p - buf), data, datalen); … … 117 169 txtlen -= 2; 118 170 putshort(&startp, txtlen); 171 ancnt = 1; 119 172 } else { 120 173 /* NULL has raw binary data */ 174 175 CHECKLEN(10); 176 putshort(&p, name); 177 putshort(&p, q->type); 178 putshort(&p, C_IN); 179 putlong(&p, 0); /* TTL */ 180 121 181 datalen = MIN(datalen, buflen - (p - buf)); 122 182 CHECKLEN(2); … … 125 185 putdata(&p, data, datalen); 126 186 CHECKLEN(0); 127 } 187 ancnt = 1; 188 } 189 header->ancount = htons(ancnt); 128 190 break; 129 191 case QR_QUERY: … … 131 193 132 194 header->qdcount = htons(1); 133 header->arcount = htons(1);134 195 135 196 datalen = MIN(datalen, buflen - (p - buf)); … … 142 203 /* EDNS0 to advertise maximum response length 143 204 (even CNAME/A/MX, 255+255+header would be >512) */ 205 if (dnsc_use_edns0) { 206 header->arcount = htons(1); 207 /*XXX START adjust indent 1 tab forward*/ 144 208 CHECKLEN(11); 145 209 putbyte(&p, 0x00); /* Root */ … … 149 213 putshort(&p, 0x8000); /* Z */ 150 214 putshort(&p, 0x0000); /* Data length */ 215 /*XXX END adjust indent 1 tab forward*/ 216 } 217 151 218 break; 152 219 } … … 160 227 dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain) 161 228 /* Only used when iodined gets an NS type query */ 229 /* Mostly same as dns_encode_a_response() below */ 162 230 { 163 231 HEADER *header; … … 166 234 short topname; 167 235 short nsname; 168 char * domain;236 char *ipp; 169 237 int domain_len; 170 238 char *p; … … 194 262 name = 0xc000 | ((p - buf) & 0x3fff); 195 263 196 domain = strstr(q->name, topdomain); 197 if (domain) { 198 domain_len = (int) (domain - q->name); 199 } else { 264 domain_len = strlen(q->name) - strlen(topdomain); 265 if (domain_len < 0 || domain_len == 1) 200 266 return -1; 201 } 202 /* pointer to start of topdomain */ 267 if (strcasecmp(q->name + domain_len, topdomain)) 268 return -1; 269 if (domain_len >= 1 && q->name[domain_len - 1] != '.') 270 return -1; 271 272 /* pointer to start of topdomain; instead of dots at the end 273 we have length-bytes in front, so total length is the same */ 203 274 topname = 0xc000 | ((p - buf + domain_len) & 0x3fff); 204 275 … … 234 305 235 306 /* ugly hack to output IP address */ 236 domain= (char *) &q->destination;307 ipp = (char *) &q->destination; 237 308 CHECKLEN(4); 238 putbyte(&p, *domain++); 239 putbyte(&p, *domain++); 240 putbyte(&p, *domain++); 241 putbyte(&p, *domain); 309 putbyte(&p, *(ipp++)); 310 putbyte(&p, *(ipp++)); 311 putbyte(&p, *(ipp++)); 312 putbyte(&p, *ipp); 313 314 len = p - buf; 315 return len; 316 } 317 318 int 319 dns_encode_a_response(char *buf, size_t buflen, struct query *q) 320 /* Only used when iodined gets an A type query for ns.topdomain or www.topdomain */ 321 /* Mostly same as dns_encode_ns_response() above */ 322 { 323 HEADER *header; 324 int len; 325 short name; 326 char *ipp; 327 char *p; 328 329 if (buflen < sizeof(HEADER)) 330 return 0; 331 332 memset(buf, 0, buflen); 333 334 header = (HEADER*)buf; 335 336 header->id = htons(q->id); 337 header->qr = 1; 338 header->opcode = 0; 339 header->aa = 1; 340 header->tc = 0; 341 header->rd = 0; 342 header->ra = 0; 343 344 p = buf + sizeof(HEADER); 345 346 header->qdcount = htons(1); 347 header->ancount = htons(1); 348 349 /* pointer to start of name */ 350 name = 0xc000 | ((p - buf) & 0x3fff); 351 352 /* Query section */ 353 putname(&p, buflen - (p - buf), q->name); /* Name */ 354 CHECKLEN(4); 355 putshort(&p, q->type); /* Type */ 356 putshort(&p, C_IN); /* Class */ 357 358 /* Answer section */ 359 CHECKLEN(12); 360 putshort(&p, name); /* Name */ 361 putshort(&p, q->type); /* Type */ 362 putshort(&p, C_IN); /* Class */ 363 putlong(&p, 3600); /* TTL */ 364 putshort(&p, 4); /* Data length */ 365 366 /* ugly hack to output IP address */ 367 ipp = (char *) &q->destination; 368 CHECKLEN(4); 369 putbyte(&p, *(ipp++)); 370 putbyte(&p, *(ipp++)); 371 putbyte(&p, *(ipp++)); 372 putbyte(&p, *ipp); 242 373 243 374 len = p - buf; … … 277 408 int rv; 278 409 410 q->id2 = 0; 279 411 rv = 0; 280 412 header = (HEADER*)packet; … … 325 457 326 458 if (ancount < 1) { 327 /* We may get both CNAME and A, then ancount=2 */ 459 /* DNS errors like NXDOMAIN have ancount=0 and 460 stop here. CNAME may also have A; MX/SRV may have 461 multiple results. */ 328 462 return -1; 329 463 } 330 464 331 /* Assume that first answer is NULL/CNAME that we wanted */ 332 readname(packet, packetlen, &data, name, sizeof(name)); 333 CHECKLEN(10); 334 readshort(packet, &data, &type); 335 readshort(packet, &data, &class); 336 readlong(packet, &data, &ttl); 337 readshort(packet, &data, &rlen); 338 465 /* Here type is still the question type */ 339 466 if (type == T_NULL) { 467 /* Assume that first answer is what we wanted */ 468 readname(packet, packetlen, &data, name, sizeof(name)); 469 CHECKLEN(10); 470 readshort(packet, &data, &type); 471 readshort(packet, &data, &class); 472 readlong(packet, &data, &ttl); 473 readshort(packet, &data, &rlen); 474 340 475 rv = MIN(rlen, sizeof(rdata)); 341 476 rv = readdata(packet, &data, rdata, rv); … … 347 482 } 348 483 } 349 if ((type == T_CNAME || type == T_MX) && buf) { 350 if (type == T_MX) 351 data += 2; /* skip preference */ 484 else if ((type == T_A || type == T_CNAME) && buf) { 485 /* Assume that first answer is what we wanted */ 486 readname(packet, packetlen, &data, name, sizeof(name)); 487 CHECKLEN(10); 488 readshort(packet, &data, &type); 489 readshort(packet, &data, &class); 490 readlong(packet, &data, &ttl); 491 readshort(packet, &data, &rlen); 492 352 493 memset(name, 0, sizeof(name)); 353 494 readname(packet, packetlen, &data, name, sizeof(name) - 1); … … 357 498 rv = strlen(buf); 358 499 } 359 if (type == T_TXT && buf) { 500 else if ((type == T_MX || type == T_SRV) && buf) { 501 /* We support 250 records, 250*(255+header) ~= 64kB. 502 Only exact 10-multiples are accepted, and gaps in 503 numbering are not jumped over (->truncated). 504 Hopefully DNS servers won't mess around too much. 505 */ 506 char names[250][QUERY_NAME_SIZE]; 507 char *rdatastart; 508 short pref; 509 int i; 510 int offset; 511 512 memset(names, 0, sizeof(names)); 513 514 for (i=0; i < ancount; i++) { 515 readname(packet, packetlen, &data, name, sizeof(name)); 516 CHECKLEN(12); 517 readshort(packet, &data, &type); 518 readshort(packet, &data, &class); 519 readlong(packet, &data, &ttl); 520 readshort(packet, &data, &rlen); 521 rdatastart = data; 522 readshort(packet, &data, &pref); 523 524 if (type == T_SRV) { 525 /* skip weight, port */ 526 data += 4; 527 CHECKLEN(0); 528 } 529 530 if (pref % 10 == 0 && pref >= 10 && 531 pref < 2500) { 532 readname(packet, packetlen, &data, 533 names[pref / 10 - 1], 534 QUERY_NAME_SIZE - 1); 535 names[pref / 10 - 1][QUERY_NAME_SIZE-1] = '\0'; 536 } 537 538 /* always trust rlen, not name encoding */ 539 data = rdatastart + rlen; 540 CHECKLEN(0); 541 } 542 543 /* output is like Hname10.com\0Hname20.com\0\0 */ 544 offset = 0; 545 i = 0; 546 while (names[i][0] != '\0') { 547 int l = MIN(strlen(names[i]), buflen-offset-2); 548 if (l <= 0) 549 break; 550 memcpy(buf + offset, names[i], l); 551 offset += l; 552 *(buf + offset) = '\0'; 553 offset++; 554 i++; 555 } 556 *(buf + offset) = '\0'; 557 rv = offset; 558 } 559 else if (type == T_TXT && buf) { 560 /* Assume that first answer is what we wanted */ 561 readname(packet, packetlen, &data, name, sizeof(name)); 562 CHECKLEN(10); 563 readshort(packet, &data, &type); 564 readshort(packet, &data, &class); 565 readlong(packet, &data, &ttl); 566 readshort(packet, &data, &rlen); 567 360 568 rv = readtxtbin(packet, &data, rlen, rdata, sizeof(rdata)); 361 569 if (rv >= 1) { … … 366 574 } 367 575 } 576 577 /* Here type is the answer type (note A->CNAME) */ 368 578 if (q != NULL) 369 579 q->type = type; -
src/dns.h
rb6fc3f rb17790 25 25 } qr_t; 26 26 27 extern int dnsc_use_edns0; 28 27 29 int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t); 28 30 int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain); 31 int dns_encode_a_response(char *buf, size_t buflen, struct query *q); 29 32 unsigned short dns_get_id(char *packet, size_t packetlen); 30 33 int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t); -
src/encoding.c
r93a313 rb17790 22 22 build_hostname(char *buf, size_t buflen, 23 23 const char *data, const size_t datalen, 24 const char *topdomain, struct encoder *encoder )24 const char *topdomain, struct encoder *encoder, int maxlen) 25 25 { 26 26 int encsize; … … 28 28 char *b; 29 29 30 space = MIN(0xFF, buflen) - strlen(topdomain) - 7; 30 space = MIN(maxlen, buflen) - strlen(topdomain) - 8; 31 /* 8 = 5 max header length + 1 dot before topdomain + 2 safety */ 32 31 33 if (!encoder->places_dots()) 32 34 space -= (space / 57); /* space for dots */ -
src/encoding.h
ra1a2e3 rb17790 18 18 #define _ENCODING_H_ 19 19 20 /* All-0, all-1, 01010101, 10101010: each 4 times to make sure the pattern 21 spreads across multiple encoded chars -> 16 bytes total. 22 Followed by 32 bytes from my /dev/random; should be enough. 23 */ 24 #define DOWNCODECCHECK1 "\000\000\000\000\377\377\377\377\125\125\125\125\252\252\252\252\201\143\310\322\307\174\262\027\137\117\316\311\111\055\122\041\141\251\161\040\045\263\006\163\346\330\104\060\171\120\127\277" 25 #define DOWNCODECCHECK1_LEN 48 26 20 27 struct encoder { 21 28 char name[8]; … … 28 35 }; 29 36 30 int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder * );37 int build_hostname(char *, size_t, const char *, const size_t, const char *, struct encoder *, int); 31 38 int unpack_data(char *, size_t, char *, size_t, struct encoder *); 32 39 int inline_dotify(char *, size_t); -
src/iodine.c
r1a26a9 rb17790 62 62 63 63 fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] " 64 "[-P password] [-m maxfragsize] [- T type] [-O enc] [-L 0|1] [-I sec] "64 "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " 65 65 "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); 66 66 exit(2); … … 73 73 fprintf(stderr, "iodine IP over DNS tunneling client\n"); 74 74 fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] " 75 "[-P password] [-m maxfragsize] [- T type] [-O enc] [-L 0|1] [-I sec] "75 "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] " 76 76 "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname); 77 fprintf(stderr, "Options to try if connection doesn't work:\n"); 78 fprintf(stderr, " -T force dns type: NULL, TXT, SRV, MX, CNAME, A (default: autodetect)\n"); 79 fprintf(stderr, " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n"); 80 fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n"); 81 fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n"); 82 fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n"); 83 fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n"); 84 fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n"); 85 fprintf(stderr, " -r to skip raw UDP mode attempt\n"); 86 fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); 87 fprintf(stderr, "Other options:\n"); 77 88 fprintf(stderr, " -v to print version info and exit\n"); 78 89 fprintf(stderr, " -h to print this help and exit\n"); 79 90 fprintf(stderr, " -f to keep running in foreground\n"); 80 fprintf(stderr, " -r to skip raw UDP mode attempt\n");81 91 fprintf(stderr, " -u name to drop privileges and run as user 'name'\n"); 82 92 fprintf(stderr, " -t dir to chroot to directory dir\n"); 83 93 fprintf(stderr, " -d device to set tunnel device name\n"); 84 fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");85 fprintf(stderr, " -m maxfragsize, to limit size of downstream packets\n");86 fprintf(stderr, " -T dns type: NULL (default, fastest), TXT, CNAME, A (CNAME answer), MX\n");87 fprintf(stderr, " -O downstream encoding (!NULL): Base32(default), Base64, or Raw (only TXT)\n");88 fprintf(stderr, " -L 1: try lazy mode for low-latency (default). 0: don't (implies -I1)\n");89 fprintf(stderr, " -I max interval between requests (default 4 sec) to prevent server timeouts\n");90 94 fprintf(stderr, " -z context, to apply specified SELinux context after initialization\n"); 91 95 fprintf(stderr, " -F pidfile to write pid to a file\n"); … … 132 136 int lazymode; 133 137 int selecttimeout; 138 int hostname_maxlen; 134 139 135 140 nameserv_addr = NULL; … … 153 158 lazymode = 1; 154 159 selecttimeout = 4; 160 hostname_maxlen = 0xFF; 155 161 156 162 #ifdef WINDOWS32 … … 169 175 #endif 170 176 171 while ((choice = getopt(argc, argv, "vfhru:t:d:P:m: F:T:O:L:I:")) != -1) {177 while ((choice = getopt(argc, argv, "vfhru:t:d:P:m:M:F:T:O:L:I:")) != -1) { 172 178 switch(choice) { 173 179 case 'v': … … 203 209 autodetect_frag_size = 0; 204 210 max_downstream_frag_size = atoi(optarg); 211 break; 212 case 'M': 213 hostname_maxlen = atoi(optarg); 214 if (hostname_maxlen > 255) 215 hostname_maxlen = 255; 216 if (hostname_maxlen < 10) 217 hostname_maxlen = 10; 205 218 break; 206 219 case 'z': … … 284 297 client_set_lazymode(lazymode); 285 298 client_set_topdomain(topdomain); 299 client_set_hostname_maxlen(hostname_maxlen); 286 300 287 301 if (username != NULL) { … … 316 330 signal(SIGTERM, sighandler); 317 331 332 fprintf(stderr, "Sending DNS queries for %s to %s\n", 333 topdomain, nameserv_addr); 334 318 335 if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) { 319 336 retval = 1; … … 321 338 } 322 339 323 if (client_get_conn() == CONN_DNS_NULL) { 324 fprintf(stderr, "Sending queries for %s to %s\n", topdomain, nameserv_addr); 325 } else { 340 if (client_get_conn() == CONN_RAW_UDP) { 326 341 fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr()); 327 342 } 343 344 fprintf(stderr, "Connection setup complete, transmitting data.\n"); 328 345 329 346 if (foreground == 0) -
src/iodined.c
rd87432 rb17790 52 52 #include "base32.h" 53 53 #include "base64.h" 54 #include "base64u.h" 55 #include "base128.h" 54 56 #include "user.h" 55 57 #include "login.h" … … 70 72 static struct encoder *b32; 71 73 static struct encoder *b64; 74 static struct encoder *b64u; 75 static struct encoder *b128; 72 76 static int created_users; 73 77 … … 118 122 struct sockaddr_in *tempin; 119 123 124 /* Note: duplicate in handle_raw_login() except IP-address check */ 125 120 126 if (userid < 0 || userid >= created_users ) { 121 127 return 1; … … 152 158 len += RAW_HDR_LEN; 153 159 packet[RAW_HDR_CMD] = cmd | (user & 0x0F); 160 161 if (debug >= 2) { 162 struct sockaddr_in *tempin; 163 tempin = (struct sockaddr_in *) &(q->from); 164 fprintf(stderr, "TX-raw: client %s, cmd %d, %d bytes\n", 165 inet_ntoa(tempin->sin_addr), cmd, len); 166 } 154 167 155 168 sendto(fd, packet, len, 0, &q->from, q->fromlen); … … 244 257 actually get an answer instead of silence. 245 258 246 We normally use either CMC (ping) or seqno/frag (upstream data) to prevent 247 cache hits on in-between caching DNS servers. Also, the iodine client is 248 designed to mostly operate properly when cached results are returned. 249 Two cache-hit situations: 250 - Repeated DNS query when our ack got lost: has same seqno/frag and doesn't 251 have CMC; but the client will not have sent any new data or pings 252 in-between, so this is always cacheable. Even in lazy mode, since we send 253 the first answer to the actual DNS query only on receipt of the first 254 client retransmit. 255 - Identical second+ fragment of mod-8 packets ago, same seqno/frag and no 256 TCP counter in those fragments to tell them apart. This is _not_ 257 cachable, so our cache length should never exceed 7 packets. 259 Because of the CMC in both ping and upstream data, unwanted cache hits 260 are prevented. Data-CMC is only 36 counts, so our cache length should 261 not exceed 36/2=18 packets. (This quick rule assumes all packets are 262 otherwise equal, which they arent: up/downstream seq/frag, tcp sequence 263 number, and of course data.) 258 264 */ 259 265 … … 303 309 304 310 /* okay, match */ 311 if (debug >= 1) 312 fprintf(stderr, "OUT user %d %s from dnscache\n", userid, q->name); 313 305 314 write_dns(dns_fd, q, users[userid].dnscache_answer[use], 306 315 users[userid].dnscache_answerlen[use], … … 316 325 317 326 #endif /* DNSCACHE_LEN */ 327 328 static inline void 329 save_to_qmem(unsigned char *qmem_cmc, unsigned short *qmem_type, int qmem_len, 330 int *qmem_lastfilled, unsigned char *cmc_to_add, 331 unsigned short type_to_add) 332 /* Remember query to check for duplicates */ 333 { 334 int fill; 335 336 fill = *qmem_lastfilled + 1; 337 if (fill >= qmem_len) 338 fill = 0; 339 340 memcpy(qmem_cmc + fill * 4, cmc_to_add, 4); 341 qmem_type[fill] = type_to_add; 342 *qmem_lastfilled = fill; 343 } 344 345 static inline void 346 save_to_qmem_pingordata(int userid, struct query *q) 347 { 348 /* Our CMC is a bit more than the "official" CMC; we store 4 bytes 349 just because we can, and because it may prevent some false matches. 350 For ping, we save the 4 decoded bytes: userid + seq/frag + CMC. 351 For data, we save the 4 _un_decoded chars in lowercase: seq/frag's 352 + 1 char CMC; that last char is non-Base32. 353 */ 354 355 char cmc[8]; 356 int i; 357 358 if (q->name[0] == 'P' || q->name[0] == 'p') { 359 /* Ping packet */ 360 361 size_t cmcsize = sizeof(cmc); 362 char *cp = strchr(q->name, '.'); 363 364 if (cp == NULL) 365 return; /* illegal hostname; shouldn't happen */ 366 367 /* We already unpacked in handle_null_request(), but that's 368 lost now... Note: b32 directly, we want no undotify here! */ 369 i = b32->decode(cmc, &cmcsize, q->name + 1, (cp - q->name) - 1); 370 371 if (i < 4) 372 return; /* illegal ping; shouldn't happen */ 373 374 save_to_qmem(users[userid].qmemping_cmc, 375 users[userid].qmemping_type, QMEMPING_LEN, 376 &users[userid].qmemping_lastfilled, 377 (void *) cmc, q->type); 378 } else { 379 /* Data packet, hopefully not illegal */ 380 if (strlen(q->name) < 5) 381 return; 382 383 /* We store CMC in lowercase; if routing via multiple parallel 384 DNS servers, one may do case-switch and another may not, 385 and we still want to detect duplicates. 386 Data-header is always base32, so case-swap won't hurt. 387 */ 388 for (i = 0; i < 4; i++) 389 if (q->name[i+1] >= 'A' && q->name[i+1] <= 'Z') 390 cmc[i] = q->name[i+1] + ('a' - 'A'); 391 else 392 cmc[i] = q->name[i+1]; 393 394 save_to_qmem(users[userid].qmemdata_cmc, 395 users[userid].qmemdata_type, QMEMDATA_LEN, 396 &users[userid].qmemdata_lastfilled, 397 (void *) cmc, q->type); 398 } 399 } 400 401 static int 402 answer_from_qmem(int dns_fd, struct query *q, unsigned char *qmem_cmc, 403 unsigned short *qmem_type, int qmem_len, 404 unsigned char *cmc_to_check) 405 /* Checks query memory and sends an (illegal) answer if this is a duplicate. 406 Returns: 1 = answer sent, drop this query, 0 = no answer sent, this is 407 not a duplicate. */ 408 { 409 int i; 410 411 for (i = 0; i < qmem_len ; i++) { 412 413 if (qmem_type[i] == T_UNSET) 414 continue; 415 if (qmem_type[i] != q->type) 416 continue; 417 if (memcmp(qmem_cmc + i * 4, cmc_to_check, 4)) 418 continue; 419 420 /* okay, match */ 421 if (debug >= 1) 422 fprintf(stderr, "OUT from qmem for %s == duplicate, sending illegal reply\n", q->name); 423 424 write_dns(dns_fd, q, "x", 1, 'T'); 425 426 q->id = 0; /* this query was used */ 427 return 1; 428 } 429 430 /* here only when no match found */ 431 return 0; 432 } 433 434 static inline int 435 answer_from_qmem_data(int dns_fd, int userid, struct query *q) 436 /* Quick helper function to keep handle_null_request() clean */ 437 { 438 char cmc[4]; 439 int i; 440 441 for (i = 0; i < 4; i++) 442 if (q->name[i+1] >= 'A' && q->name[i+1] <= 'Z') 443 cmc[i] = q->name[i+1] + ('a' - 'A'); 444 else 445 cmc[i] = q->name[i+1]; 446 447 return answer_from_qmem(dns_fd, q, users[userid].qmemdata_cmc, 448 users[userid].qmemdata_type, QMEMDATA_LEN, 449 (void *) cmc); 450 } 318 451 319 452 static int … … 374 507 write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc); 375 508 509 if (q->id2 != 0) { 510 q->id = q->id2; 511 q->fromlen = q->fromlen2; 512 memcpy(&(q->from), &(q->from2), q->fromlen2); 513 if (debug >= 1) 514 fprintf(stderr, "OUT again to last duplicate\n"); 515 write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc); 516 } 517 518 save_to_qmem_pingordata(userid, q); 519 376 520 #ifdef DNSCACHE_LEN 377 521 save_to_dnscache(userid, q, pkt, datalen + 2); … … 379 523 380 524 q->id = 0; /* this query is used */ 381 /* .iddupe is _not_ reset on purpose */382 525 383 526 if (datalen > 0 && datalen == users[userid].outpacket.len) { … … 505 648 506 649 /* Is packet done? */ 507 if (users[userid].outpacket.offset == users[userid].outpacket.len) {650 if (users[userid].outpacket.offset >= users[userid].outpacket.len) { 508 651 users[userid].outpacket.len = 0; 509 652 users[userid].outpacket.offset = 0; 510 653 users[userid].outpacket.fragment--; /* unneeded ++ above */ 511 /* last seqno/fragare always returned on pings */654 /* ^keep last seqno/frag, are always returned on pings */ 512 655 /* users[userid].outfragresent = 0; already above */ 513 656 … … 555 698 userid = find_available_user(); 556 699 if (userid >= 0) { 700 int i; 557 701 struct sockaddr_in *tempin; 558 702 … … 569 713 userid, inet_ntoa(tempin->sin_addr)); 570 714 users[userid].q.id = 0; 571 users[userid].q.iddupe = 0; 572 users[userid].q_prev.id = 0; 573 users[userid].q_prev.iddupe = 0; 715 users[userid].q.id2 = 0; 574 716 users[userid].q_sendrealsoon.id = 0; 717 users[userid].q_sendrealsoon.id2 = 0; 575 718 users[userid].q_sendrealsoon_new = 0; 576 719 users[userid].outpacket.len = 0; … … 593 736 #ifdef DNSCACHE_LEN 594 737 { 595 int i;596 738 for (i = 0; i < DNSCACHE_LEN; i++) { 597 739 users[userid].dnscache_q[i].id = 0; … … 601 743 users[userid].dnscache_lastfilled = 0; 602 744 #endif 745 for (i = 0; i < QMEMPING_LEN; i++) 746 users[userid].qmemping_type[i] = T_UNSET; 747 users[userid].qmemping_lastfilled = 0; 748 for (i = 0; i < QMEMDATA_LEN; i++) 749 users[userid].qmemdata_type[i] = T_UNSET; 750 users[userid].qmemdata_lastfilled = 0; 603 751 } else { 604 752 /* No space for another user */ … … 615 763 } else if(in[0] == 'L' || in[0] == 'l') { 616 764 read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); 765 if (read < 17) { 766 write_dns(dns_fd, q, "BADLEN", 6, 'T'); 767 return; 768 } 769 617 770 /* Login phase, handle auth */ 618 771 userid = unpacked[0]; … … 713 866 write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); 714 867 break; 868 case 26: /* "2nd" 6 bits per byte = base64u, with underscore */ 869 enc = get_base64u_encoder(); 870 user_switch_codec(userid, enc); 871 write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); 872 break; 873 case 7: /* 7 bits per byte = base128 */ 874 enc = get_base128_encoder(); 875 user_switch_codec(userid, enc); 876 write_dns(dns_fd, q, enc->name, strlen(enc->name), users[userid].downenc); 877 break; 715 878 default: 716 879 write_dns(dns_fd, q, "BADCODEC", 8, users[userid].downenc); … … 719 882 return; 720 883 } else if(in[0] == 'O' || in[0] == 'o') { 721 if (domain_len != 4) { /* len = 4, example: "O1T." */884 if (domain_len < 3) { /* len at least 3, example: "O1T" */ 722 885 write_dns(dns_fd, q, "BADLEN", 6, 'T'); 723 886 return; … … 742 905 write_dns(dns_fd, q, "Base64", 6, users[userid].downenc); 743 906 break; 907 case 'U': 908 case 'u': 909 users[userid].downenc = 'U'; 910 write_dns(dns_fd, q, "Base64u", 7, users[userid].downenc); 911 break; 912 case 'V': 913 case 'v': 914 users[userid].downenc = 'V'; 915 write_dns(dns_fd, q, "Base128", 7, users[userid].downenc); 916 break; 744 917 case 'R': 745 918 case 'r': … … 762 935 } 763 936 return; 937 } else if(in[0] == 'Y' || in[0] == 'y') { 938 int i; 939 char *datap; 940 int datalen; 941 942 if (domain_len < 6) { /* len at least 6, example: "YTxCMC" */ 943 write_dns(dns_fd, q, "BADLEN", 6, 'T'); 944 return; 945 } 946 947 i = b32_8to5(in[2]); /* check variant */ 948 949 switch (i) { 950 case 1: 951 datap = DOWNCODECCHECK1; 952 datalen = DOWNCODECCHECK1_LEN; 953 break; 954 default: 955 write_dns(dns_fd, q, "BADLEN", 6, 'T'); 956 return; 957 } 958 959 switch (in[1]) { 960 case 'T': 961 case 't': 962 if (q->type == T_TXT || 963 q->type == T_SRV || q->type == T_MX || 964 q->type == T_CNAME || q->type == T_A) { 965 write_dns(dns_fd, q, datap, datalen, 'T'); 966 return; 967 } 968 break; 969 case 'S': 970 case 's': 971 if (q->type == T_TXT || 972 q->type == T_SRV || q->type == T_MX || 973 q->type == T_CNAME || q->type == T_A) { 974 write_dns(dns_fd, q, datap, datalen, 'S'); 975 return; 976 } 977 break; 978 case 'U': 979 case 'u': 980 if (q->type == T_TXT || 981 q->type == T_SRV || q->type == T_MX || 982 q->type == T_CNAME || q->type == T_A) { 983 write_dns(dns_fd, q, datap, datalen, 'U'); 984 return; 985 } 986 break; 987 case 'V': 988 case 'v': 989 if (q->type == T_TXT || 990 q->type == T_SRV || q->type == T_MX || 991 q->type == T_CNAME || q->type == T_A) { 992 write_dns(dns_fd, q, datap, datalen, 'V'); 993 return; 994 } 995 break; 996 case 'R': 997 case 'r': 998 if (q->type == T_NULL || q->type == T_TXT) { 999 write_dns(dns_fd, q, datap, datalen, 'R'); 1000 return; 1001 } 1002 break; 1003 } 1004 1005 /* if still here, then codec not available */ 1006 write_dns(dns_fd, q, "BADCODEC", 8, 'T'); 1007 return; 1008 764 1009 } else if(in[0] == 'R' || in[0] == 'r') { 765 1010 int req_frag_size; 1011 1012 if (domain_len < 16) { /* we'd better have some chars for data... */ 1013 write_dns(dns_fd, q, "BADLEN", 6, 'T'); 1014 return; 1015 } 766 1016 767 1017 /* Downstream fragsize probe packet */ … … 778 1028 char buf[2048]; 779 1029 int i; 780 unsigned int v = ( unsigned int) rand();1030 unsigned int v = ((unsigned int) rand()) & 0xff ; 781 1031 782 1032 memset(buf, 0, sizeof(buf)); … … 785 1035 /* make checkable pseudo-random sequence */ 786 1036 buf[2] = 107; 787 for (i = 3; i < 2048; i++, v += 107)788 buf[i] = (char) (v & 0xff);1037 for (i = 3; i < 2048; i++, v = (v + 107) & 0xff) 1038 buf[i] = v; 789 1039 write_dns(dns_fd, q, buf, req_frag_size, users[userid].downenc); 790 1040 } … … 794 1044 795 1045 read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32); 1046 1047 if (read < 3) { 1048 write_dns(dns_fd, q, "BADLEN", 6, 'T'); 1049 return; 1050 } 1051 796 1052 /* Downstream fragsize packet */ 797 1053 userid = unpacked[0]; … … 836 1092 #ifdef DNSCACHE_LEN 837 1093 /* Check if cached */ 838 if (answer_from_dnscache(dns_fd, userid, q)) { 839 /* Answer sent. But if this is our currently waiting 840 request in the queue, invalidate now since we can't 841 be sure that our coming new answer will ever reach 842 client. Happens on 3+ retransmits in the "lost pings 843 problem" with agressive DNS server. 844 */ 845 if (users[userid].q.id != 0 && 846 q->type == users[userid].q.type && 847 !strcmp(q->name, users[userid].q.name)) 848 users[userid].q.id = 0; 1094 if (answer_from_dnscache(dns_fd, userid, q)) 849 1095 return; 850 }851 1096 #endif 852 1097 853 /* Dupe pruning */ 854 if (users[userid].q.iddupe != 0 && 1098 /* Check if duplicate (and not in full dnscache any more) */ 1099 if (answer_from_qmem(dns_fd, q, users[userid].qmemping_cmc, 1100 users[userid].qmemping_type, QMEMPING_LEN, 1101 (void *) unpacked)) 1102 return; 1103 1104 /* Check if duplicate of waiting queries; impatient DNS relays 1105 like to re-try early and often (with _different_ .id!) */ 1106 if (users[userid].q.id != 0 && 855 1107 q->type == users[userid].q.type && 856 1108 !strcmp(q->name, users[userid].q.name) && 857 1109 users[userid].lazy) { 858 /* We have this ping already. Aggressively impatient 859 DNS servers resend queries with _different_ id. 860 But hostname check is sufficient, includes CMC. 861 Just drop this ping. 862 If we already answered it (e.g. data available some 863 milliseconds ago), DNS server should have noticed 864 by now (race condition, happens rarely). 865 If we didn't answer yet, we'll do later (to the 866 first id, thank you very much). */ 1110 /* We have this ping already, and it's waiting to be 1111 answered. Always keep the last duplicate, since the 1112 relay may have forgotten its first version already. 1113 Our answer will go to both. 1114 (If we already sent an answer, qmem/cache will 1115 have triggered.) */ 867 1116 if (debug >= 2) { 868 fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, ignoring\n",1117 fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, remembering\n", 869 1118 userid); 870 1119 } 1120 users[userid].q.id2 = q->id; 1121 users[userid].q.fromlen2 = q->fromlen; 1122 memcpy(&(users[userid].q.from2), &(q->from), q->fromlen); 871 1123 return; 872 1124 } 873 1125 874 if (users[userid].q_prev.iddupe != 0 &&875 q->type == users[userid].q_prev.type &&876 !strcmp(q->name, users[userid].q_prev.name) &&877 users[userid].lazy) {878 /* Okay, even older ping that we already saw879 and probably answered just milliseconds ago.880 This is a race condition that agressive DNS servers881 actually train into; happens quite often.882 Just drop this new version. */883 /* If using dnscache, this new query probably got a884 cached answer already, and this shouldn't trigger. */885 if (debug >= 2) {886 fprintf(stderr, "PING pkt from user %d = dupe (previous) from impatient DNS server, ignoring\n",887 userid);888 }889 return;890 }891 892 1126 if (users[userid].q_sendrealsoon.id != 0 && 893 1127 q->type == users[userid].q_sendrealsoon.type && 894 1128 !strcmp(q->name, users[userid].q_sendrealsoon.name)) { 895 /* Outer select loop will send answer immediately. */ 1129 /* Outer select loop will send answer immediately, 1130 to both queries. */ 896 1131 if (debug >= 2) { 897 fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, ignoring\n",1132 fprintf(stderr, "PING pkt from user %d = dupe from impatient DNS server, remembering\n", 898 1133 userid); 899 1134 } 1135 users[userid].q_sendrealsoon.id2 = q->id; 1136 users[userid].q_sendrealsoon.fromlen2 = q->fromlen; 1137 memcpy(&(users[userid].q_sendrealsoon.from2), 1138 &(q->from), q->fromlen); 900 1139 return; 901 1140 } … … 935 1174 } 936 1175 937 /* Save previous query for dupe checking */938 memcpy(&(users[userid].q_prev), &(users[userid].q),939 sizeof(struct query));940 941 1176 /* Save new query and time info */ 942 1177 memcpy(&(users[userid].q), q, sizeof(struct query)); … … 956 1191 int upstream_ok = 1; 957 1192 int didsend = 0; 958 int thisisdupe = 0;959 1193 int code = -1; 960 1194 961 /* Need 4char header + >=1 char data */962 if (domain_len < 5)1195 /* Need 5char header + >=1 char data */ 1196 if (domain_len < 6) 963 1197 return; 964 1198 … … 988 1222 #ifdef DNSCACHE_LEN 989 1223 /* Check if cached */ 990 if (answer_from_dnscache(dns_fd, userid, q)) { 991 /* Answer sent. But if this is our currently waiting 992 request in the queue, invalidate now since we can't 993 be sure that our coming new answer will ever reach 994 client. Happens on 3+ retransmits in the "lost pings 995 problem" with agressive DNS server. 996 */ 997 if (users[userid].q.id != 0 && 998 q->type == users[userid].q.type && 999 !strcmp(q->name, users[userid].q.name)) 1000 users[userid].q.id = 0; 1224 if (answer_from_dnscache(dns_fd, userid, q)) 1001 1225 return; 1002 }1003 1226 #endif 1004 1227 1005 /* Dupe pruning */ 1006 if (users[userid].q.iddupe != 0 && 1007 q->id == users[userid].q.iddupe && 1228 /* Check if duplicate (and not in full dnscache any more) */ 1229 if (answer_from_qmem_data(dns_fd, userid, q)) 1230 return; 1231 1232 /* Check if duplicate of waiting queries; impatient DNS relays 1233 like to re-try early and often (with _different_ .id!) */ 1234 if (users[userid].q.id != 0 && 1008 1235 q->type == users[userid].q.type && 1009 !strcmp(q->name, users[userid].q.name) && 1236 !strcmp(q->name, users[userid].q.name) && 1010 1237 users[userid].lazy) { 1011 /* We have this exact query already, with same id. 1012 So this is surely a honest dupe. */ 1238 /* We have this packet already, and it's waiting to be 1239 answered. Always keep the last duplicate, since the 1240 relay may have forgotten its first version already. 1241 Our answer will go to both. 1242 (If we already sent an answer, qmem/cache will 1243 have triggered.) */ 1013 1244 if (debug >= 2) { 1014 fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, ignoring\n", 1015 userid); 1016 } 1017 return; 1018 } 1019 /* Note: Upstream data packet retransmits have exact same 1020 hostname, so can't reliably ignore the id here. 1021 And that's not even needed because of send_ping_soon in 1022 client. Nice. We still do need a queue-flush on data1-data1, 1023 see thisisdupe. 1024 But then there's the race condition in two variants: 1025 data1 - ping - data1 1026 data1 - data2 - data1 1027 These are surely dupes, irrespective of id, because client 1028 will only send ping/data2 when it has received our ack for 1029 data1. (Okay, and ping/data2 should be dupe-pruned 1030 themselves already...) 1031 Draw pictures if you don't understand immediately. 1032 */ 1033 /* If using dnscache, the new data1 probably got a 1034 cached answer already, and this shouldn't trigger. */ 1035 if (users[userid].q.iddupe != 0 && 1036 (q->type != users[userid].q.type || 1037 strcmp(q->name, users[userid].q.name)) && 1038 users[userid].q_prev.iddupe != 0 && 1039 q->type == users[userid].q_prev.type && 1040 !strcmp(q->name, users[userid].q_prev.name) && 1041 users[userid].lazy) { 1042 if (debug >= 2) { 1043 fprintf(stderr, "IN pkt from user %d = dupe (previous) from impatient DNS server, ignoring\n", 1245 fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, remembering\n", 1044 1246 userid); 1045 1247 } 1248 users[userid].q.id2 = q->id; 1249 users[userid].q.fromlen2 = q->fromlen; 1250 memcpy(&(users[userid].q.from2), &(q->from), q->fromlen); 1046 1251 return; 1047 1252 } … … 1050 1255 q->type == users[userid].q_sendrealsoon.type && 1051 1256 !strcmp(q->name, users[userid].q_sendrealsoon.name)) { 1052 /* Outer select loop will send answer immediately. */ 1257 /* Outer select loop will send answer immediately, 1258 to both queries. */ 1053 1259 if (debug >= 2) { 1054 fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, ignoring\n",1260 fprintf(stderr, "IN pkt from user %d = dupe from impatient DNS server, remembering\n", 1055 1261 userid); 1056 1262 } 1263 users[userid].q_sendrealsoon.id2 = q->id; 1264 users[userid].q_sendrealsoon.fromlen2 = q->fromlen; 1265 memcpy(&(users[userid].q_sendrealsoon.from2), 1266 &(q->from), q->fromlen); 1057 1267 return; 1058 1268 } 1059 1269 1060 /* We need to flush our queue on dupes, since our new answer1061 to the first query may/will be duplicated by DNS caches to1062 also answer the client's re-sent (=dupe) query.1063 (Caches take TTL=0 to mean: "good for current and earlier1064 queries") */1065 if (users[userid].q.iddupe != 0 &&1066 q->type == users[userid].q.type &&1067 !strcmp(q->name, users[userid].q.name))1068 thisisdupe = 1;1069 1070 1270 1071 1271 /* Decode data header */ … … 1123 1323 1124 1324 if (upstream_ok) { 1125 /* decode with this user s encoding */1126 read = unpack_data(unpacked, sizeof(unpacked), &(in[ 4]), domain_len - 4,1325 /* decode with this user's encoding */ 1326 read = unpack_data(unpacked, sizeof(unpacked), &(in[5]), domain_len - 5, 1127 1327 users[userid].encoder); 1128 1328 … … 1161 1361 - If we are in non-lazy mode, there should be no query 1162 1362 waiting, but if there is, send immediately. 1163 - If we are flushing queue due to dupe, send immediately.1164 1363 - In all other cases (mostly the last-fragment cases), 1165 1364 we can afford to wait just a tiny little while for the … … 1171 1370 (upstream_ok && !lastfrag && !didsend) || 1172 1371 (!upstream_ok && !didsend) || 1173 !users[userid].lazy || 1174 thisisdupe) { 1372 !users[userid].lazy) { 1175 1373 didsend = 1; 1176 1374 if (send_chunk_or_dataless(dns_fd, userid, &users[userid].q) == 1) … … 1187 1385 } 1188 1386 1189 /* Save previous query for dupe checking */1190 memcpy(&(users[userid].q_prev), &(users[userid].q),1191 sizeof(struct query));1192 1193 1387 /* Save new query and time info */ 1194 1388 memcpy(&(users[userid].q), q, sizeof(struct query)); … … 1199 1393 - If we have new data waiting and not yet sent above, 1200 1394 send immediately. 1201 - If we are flushing queue due to dupe, send immediately.1202 1395 - If this wasn't the last upstream fragment, then we expect 1203 1396 more, so ack immediately if we didn't already or are … … 1209 1402 - In all other cases, don't send anything now. 1210 1403 */ 1211 if ((users[userid].outpacket.len > 0 && !didsend) 1212 || thisisdupe) 1404 if (users[userid].outpacket.len > 0 && !didsend) 1213 1405 send_chunk_or_dataless(dns_fd, userid, &users[userid].q); 1214 1406 else if (!didsend || !users[userid].lazy) { … … 1228 1420 static void 1229 1421 handle_ns_request(int dns_fd, struct query *q) 1422 /* Mostly identical to handle_a_request() below */ 1230 1423 { 1231 1424 char buf[64*1024]; … … 1252 1445 if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { 1253 1446 warn("ns reply send error"); 1447 } 1448 } 1449 1450 static void 1451 handle_a_request(int dns_fd, struct query *q, int fakeip) 1452 /* Mostly identical to handle_ns_request() above */ 1453 { 1454 char buf[64*1024]; 1455 int len; 1456 1457 if (fakeip) { 1458 in_addr_t ip = inet_addr("127.0.0.1"); 1459 memcpy(&q->destination.s_addr, &ip, sizeof(in_addr_t)); 1460 1461 } else if (ns_ip != INADDR_ANY) { 1462 /* If ns_ip set, overwrite destination addr with it. 1463 * Destination addr will be sent as additional record (A, IN) */ 1464 memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t)); 1465 } 1466 1467 len = dns_encode_a_response(buf, sizeof(buf), q); 1468 if (len < 1) { 1469 warnx("dns_encode_a_response doesn't fit"); 1470 return; 1471 } 1472 1473 if (debug >= 2) { 1474 struct sockaddr_in *tempin; 1475 tempin = (struct sockaddr_in *) &(q->from); 1476 fprintf(stderr, "TX: client %s, type %d, name %s, %d bytes A reply\n", 1477 inet_ntoa(tempin->sin_addr), q->type, q->name, len); 1478 } 1479 if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) { 1480 warn("a reply send error"); 1254 1481 } 1255 1482 } … … 1340 1567 struct query q; 1341 1568 int read; 1342 char *domain;1343 1569 int domain_len; 1344 1570 int inside_topdomain; … … 1353 1579 inet_ntoa(tempin->sin_addr), q.type, q.name); 1354 1580 } 1355 1356 domain = strstr(q.name, topdomain); 1357 inside_topdomain = 0; 1358 if (domain) { 1359 domain_len = (int) (domain - q.name); 1360 if (domain_len + strlen(topdomain) == strlen(q.name)) { 1361 inside_topdomain = 1; 1362 } 1363 } 1364 1581 1582 domain_len = strlen(q.name) - strlen(topdomain); 1583 if (domain_len >= 0 && !strcasecmp(q.name + domain_len, topdomain)) 1584 inside_topdomain = 1; 1585 /* require dot before topdomain */ 1586 if (domain_len >= 1 && q.name[domain_len - 1] != '.') 1587 inside_topdomain = 0; 1588 1365 1589 if (inside_topdomain) { 1366 1590 /* This is a query we can handle */ 1591 1592 /* Handle A-type query for ns.topdomain, possibly caused 1593 by our proper response to any NS request */ 1594 if (domain_len == 3 && q.type == T_A && 1595 (q.name[0] == 'n' || q.name[0] == 'N') && 1596 (q.name[1] == 's' || q.name[1] == 'S') && 1597 q.name[2] == '.') { 1598 handle_a_request(dns_fd, &q, 0); 1599 return 0; 1600 } 1601 1602 /* Handle A-type query for www.topdomain, for anyone that's 1603 poking around */ 1604 if (domain_len == 4 && q.type == T_A && 1605 (q.name[0] == 'w' || q.name[0] == 'W') && 1606 (q.name[1] == 'w' || q.name[1] == 'W') && 1607 (q.name[2] == 'w' || q.name[2] == 'W') && 1608 q.name[3] == '.') { 1609 handle_a_request(dns_fd, &q, 1); 1610 return 0; 1611 } 1367 1612 1368 1613 switch (q.type) { … … 1371 1616 case T_A: 1372 1617 case T_MX: 1618 case T_SRV: 1373 1619 case T_TXT: 1374 1620 /* encoding is "transparent" here */ … … 1497 1743 } else { 1498 1744 /* send the compressed(!) packet to other client */ 1745 /*XXX START adjust indent 1 tab forward*/ 1746 if (users[touser].conn == CONN_DNS_NULL) { 1499 1747 if (users[touser].outpacket.len == 0) { 1500 1748 start_new_outpacket(touser, … … 1506 1754 send_chunk_or_dataless(dns_fd, touser, &users[touser].q_sendrealsoon); 1507 1755 else if (users[touser].q.id != 0) 1508 send_chunk_or_dataless(dns_fd, touser, &users[ userid].q);1756 send_chunk_or_dataless(dns_fd, touser, &users[touser].q); 1509 1757 #ifdef OUTPACKETQ_LEN 1510 1758 } else { … … 1514 1762 #endif 1515 1763 } 1764 } else{ /* CONN_RAW_UDP */ 1765 send_raw(dns_fd, users[userid].inpacket.data, 1766 users[userid].inpacket.len, touser, 1767 RAW_HDR_CMD_DATA, &users[touser].q); 1768 } 1769 /*XXX END adjust indent 1 tab forward*/ 1516 1770 } 1517 1771 } else { … … 1532 1786 if (len < 16) return; 1533 1787 1534 if (userid < 0 || userid > created_users) return; 1535 if (!users[userid].active) return; 1788 /* can't use check_user_and_ip() since IP address will be different, 1789 so duplicate here except IP address */ 1790 if (userid < 0 || userid >= created_users) return; 1791 if (!users[userid].active || users[userid].disabled) return; 1792 if (users[userid].last_pkt + 60 < time(NULL)) return; 1793 1794 if (debug >= 1) { 1795 fprintf(stderr, "IN login raw, len %d, from user %d\n", 1796 len, userid); 1797 } 1536 1798 1537 1799 /* User sends hash of seed + 1 */ … … 1550 1812 /* Correct hash, reply with hash of seed - 1 */ 1551 1813 user_set_conn_type(userid, CONN_RAW_UDP); 1552 users[userid].last_pkt = time(NULL);1553 1814 login_calculate(myhash, 16, password, users[userid].seed - 1); 1554 1815 send_raw(fd, myhash, 16, userid, RAW_HDR_CMD_LOGIN, q); … … 1590 1851 users[userid].last_pkt = time(NULL); 1591 1852 memcpy(&(users[userid].q), q, sizeof(struct query)); 1853 1854 if (debug >= 1) { 1855 fprintf(stderr, "IN ping raw, from user %d\n", userid); 1856 } 1592 1857 1593 1858 /* Send ping reply */ … … 1691 1956 } 1692 1957 1958 static size_t 1959 write_dns_nameenc(char *buf, size_t buflen, char *data, int datalen, char downenc) 1960 /* Returns #bytes of data that were encoded */ 1961 { 1962 static int td1 = 0; 1963 static int td2 = 0; 1964 size_t space; 1965 char *b; 1966 1967 /* Make a rotating topdomain to prevent filtering */ 1968 td1+=3; 1969 td2+=7; 1970 if (td1>=26) td1-=26; 1971 if (td2>=25) td2-=25; 1972 1973 /* encode data,datalen to CNAME/MX answer 1974 (adapted from build_hostname() in encoding.c) 1975 */ 1976 1977 space = MIN(0xFF, buflen) - 4 - 2; 1978 /* -1 encoding type, -3 ".xy", -2 for safety */ 1979 1980 memset(buf, 0, sizeof(buf)); 1981 1982 if (downenc == 'S') { 1983 buf[0] = 'i'; 1984 if (!b64->places_dots()) 1985 space -= (space / 57); /* space for dots */ 1986 b64->encode(buf+1, &space, data, datalen); 1987 if (!b64->places_dots()) 1988 inline_dotify(buf, buflen); 1989 } else if (downenc == 'U') { 1990 buf[0] = 'j'; 1991 if (!b64u->places_dots()) 1992 space -= (space / 57); /* space for dots */ 1993 b64u->encode(buf+1, &space, data, datalen); 1994 if (!b64u->places_dots()) 1995 inline_dotify(buf, buflen); 1996 } else if (downenc == 'V') { 1997 buf[0] = 'k'; 1998 if (!b128->places_dots()) 1999 space -= (space / 57); /* space for dots */ 2000 b128->encode(buf+1, &space, data, datalen); 2001 if (!b128->places_dots()) 2002 inline_dotify(buf, buflen); 2003 } else { 2004 buf[0] = 'h'; 2005 if (!b32->places_dots()) 2006 space -= (space / 57); /* space for dots */ 2007 b32->encode(buf+1, &space, data, datalen); 2008 if (!b32->places_dots()) 2009 inline_dotify(buf, buflen); 2010 } 2011 2012 /* Add dot (if it wasn't there already) and topdomain */ 2013 b = buf; 2014 b += strlen(buf) - 1; 2015 if (*b != '.') 2016 *++b = '.'; 2017 b++; 2018 2019 *b = 'a' + td1; 2020 b++; 2021 *b = 'a' + td2; 2022 b++; 2023 *b = '\0'; 2024 2025 return space; 2026 } 2027 1693 2028 static void 1694 2029 write_dns(int fd, struct query *q, char *data, int datalen, char downenc) … … 1697 2032 int len = 0; 1698 2033 1699 if (q->type == T_CNAME || q->type == T_A || q->type == T_MX) { 1700 static int td1 = 0; 1701 static int td2 = 0; 2034 if (q->type == T_CNAME || q->type == T_A) { 1702 2035 char cnamebuf[1024]; /* max 255 */ 1703 size_t space; 1704 char *b; 1705 1706 /* Make a rotating topdomain to prevent filtering */ 1707 td1+=3; 1708 td2+=7; 1709 if (td1>=26) td1-=26; 1710 if (td2>=25) td2-=25; 1711 1712 /* encode data,datalen to CNAME/MX answer */ 1713 /* (adapted from build_hostname() in iodine.c) */ 1714 1715 space = MIN(0xFF, sizeof(cnamebuf)) - 4 - 2; 1716 /* -1 encoding type, -3 ".xy", -2 for safety */ 1717 1718 memset(cnamebuf, 0, sizeof(cnamebuf)); 1719 1720 if (downenc == 'S') { 1721 cnamebuf[0] = 'I'; 1722 if (!b64->places_dots()) 1723 space -= (space / 57); /* space for dots */ 1724 b64->encode(cnamebuf+1, &space, data, datalen); 1725 if (!b64->places_dots()) 1726 inline_dotify(cnamebuf, sizeof(cnamebuf)); 1727 } else { 1728 cnamebuf[0] = 'H'; 1729 if (!b32->places_dots()) 1730 space -= (space / 57); /* space for dots */ 1731 b32->encode(cnamebuf+1, &space, data, datalen); 1732 if (!b32->places_dots()) 1733 inline_dotify(cnamebuf, sizeof(cnamebuf)); 1734 } 1735 1736 /* Add dot (if it wasn't there already) and topdomain */ 1737 b = cnamebuf; 1738 b += strlen(cnamebuf); 1739 if (*b != '.') 1740 *b++ = '.'; 1741 1742 *b = 'a' + td1; 1743 b++; 1744 *b = 'a' + td2; 1745 b++; 2036 2037 write_dns_nameenc(cnamebuf, sizeof(cnamebuf), 2038 data, datalen, downenc); 2039 2040 len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, cnamebuf, 2041 sizeof(cnamebuf)); 2042 } else if (q->type == T_MX || q->type == T_SRV) { 2043 char mxbuf[64*1024]; 2044 char *b = mxbuf; 2045 int offset = 0; 2046 int res; 2047 2048 while (1) { 2049 res = write_dns_nameenc(b, sizeof(mxbuf) - (b - mxbuf), 2050 data + offset, 2051 datalen - offset, downenc); 2052 if (res < 1) { 2053 /* nothing encoded */ 2054 b++; /* for final \0 */ 2055 break; 2056 } 2057 2058 b = b + strlen(b) + 1; 2059 2060 offset += res; 2061 if (offset >= datalen) 2062 break; 2063 } 2064 2065 /* Add final \0 */ 1746 2066 *b = '\0'; 1747 2067 1748 len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, cnamebuf, sizeof(cnamebuf));1749 }1750 else if (q->type == T_TXT) {2068 len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, mxbuf, 2069 sizeof(mxbuf)); 2070 } else if (q->type == T_TXT) { 1751 2071 /* TXT with base32 */ 1752 2072 char txtbuf[64*1024]; … … 1756 2076 1757 2077 if (downenc == 'S') { 1758 txtbuf[0] = ' S'; /* plain base64(Sixty-four) */2078 txtbuf[0] = 's'; /* plain base64(Sixty-four) */ 1759 2079 len = b64->encode(txtbuf+1, &space, data, datalen); 1760 2080 } 2081 else if (downenc == 'U') { 2082 txtbuf[0] = 'u'; /* Base64 with Underscore */ 2083 len = b64u->encode(txtbuf+1, &space, data, datalen); 2084 } 2085 else if (downenc == 'V') { 2086 txtbuf[0] = 'v'; /* Base128 */ 2087 len = b128->encode(txtbuf+1, &space, data, datalen); 2088 } 1761 2089 else if (downenc == 'R') { 1762 txtbuf[0] = ' R'; /* Raw binary data */2090 txtbuf[0] = 'r'; /* Raw binary data */ 1763 2091 len = MIN(datalen, sizeof(txtbuf) - 1); 1764 2092 memcpy(txtbuf + 1, data, len); 1765 2093 } else { 1766 txtbuf[0] = ' T'; /* plain base32(Thirty-two) */2094 txtbuf[0] = 't'; /* plain base32(Thirty-two) */ 1767 2095 len = b32->encode(txtbuf+1, &space, data, datalen); 1768 2096 } … … 1816 2144 fprintf(stderr, " -f to keep running in foreground\n"); 1817 2145 fprintf(stderr, " -D to increase debug level\n"); 2146 fprintf(stderr, " (using -DD in UTF-8 terminal: \"LC_ALL=C luit iodined -DD ...\")\n"); 1818 2147 fprintf(stderr, " -u name to drop privileges and run as user 'name'\n"); 1819 2148 fprintf(stderr, " -t dir to chroot to directory dir\n"); … … 1882 2211 bind_enable = 0; 1883 2212 bind_fd = 0; 1884 mtu = 1200; 2213 mtu = 1130; /* Very many relays give fragsize 1150 or slightly 2214 higher for NULL; tun/zlib adds ~17 bytes. */ 1885 2215 listen_ip = INADDR_ANY; 1886 2216 port = 53; … … 1894 2224 b32 = get_base32_encoder(); 1895 2225 b64 = get_base64_encoder(); 2226 b64u = get_base64u_encoder(); 2227 b128 = get_base128_encoder(); 1896 2228 1897 2229 retval = 0; -
src/user.h
r60dfbf rb17790 25 25 26 26 #define DNSCACHE_LEN 4 27 /* Undefine to disable. MUST be less than 7; also see comments in iodined.c */ 27 /* Undefine to disable. Should be less than 18; also see comments in iodined.c */ 28 29 30 #define QMEMPING_LEN 30 31 /* Max advisable: 64k/2 = 32000. Total mem usage: QMEMPING_LEN * USERS * 6 bytes */ 32 33 #define QMEMDATA_LEN 15 34 /* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */ 28 35 29 36 struct user { … … 36 43 struct in_addr host; 37 44 struct query q; 38 struct query q_prev;39 45 struct query q_sendrealsoon; 40 46 int q_sendrealsoon_new; … … 49 55 enum connection conn; 50 56 int lazy; 57 unsigned char qmemping_cmc[QMEMPING_LEN * 4]; 58 unsigned short qmemping_type[QMEMPING_LEN]; 59 int qmemping_lastfilled; 60 unsigned char qmemdata_cmc[QMEMDATA_LEN * 4]; 61 unsigned short qmemdata_type[QMEMDATA_LEN]; 62 int qmemdata_lastfilled; 51 63 #ifdef OUTPACKETQ_LEN 52 64 struct packet outpacketq[OUTPACKETQ_LEN]; -
src/version.h
r27fc03 rb17790 20 20 /* This is the version of the network protocol 21 21 It is usually equal to the latest iodine version number */ 22 #define VERSION 0x0000050 122 #define VERSION 0x00000502 23 23 24 24 #endif /* _VERSION_H_ */
Note: See TracChangeset
for help on using the changeset viewer.
