source: src/iodined.c @ 94f412

Revision 94f412, 28.3 KB checked in by Erik Ekman <yarrick@…>, 4 years ago (diff)

Dont need plibc

  • Property mode set to 100644
Line 
1/*
2 * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <stdio.h>
18#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
21#include <signal.h>
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/param.h>
25#include <sys/time.h>
26#include <fcntl.h>
27#include <time.h>
28#include <zlib.h>
29
30#ifdef WINDOWS32
31#include "windows.h"
32#include <winsock.h>
33#else
34#include <arpa/nameser.h>
35#ifdef DARWIN
36#include <arpa/nameser8_compat.h>
37#endif
38#define _XPG4_2
39#include <sys/socket.h>
40#include <err.h>
41#include <arpa/inet.h>
42#include <netinet/in.h>
43#include <netinet/in_systm.h>
44#include <netinet/ip.h>
45#include <grp.h>
46#include <sys/uio.h>
47#include <pwd.h>
48#include <netdb.h>
49#endif
50
51#include "common.h"
52#include "dns.h"
53#include "encoding.h"
54#include "base32.h"
55#include "base64.h"
56#include "user.h"
57#include "login.h"
58#include "tun.h"
59#include "fw_query.h"
60#include "version.h"
61
62static int running = 1;
63static char *topdomain;
64static char password[33];
65static struct encoder *b32;
66static int created_users;
67
68static int check_ip;
69static int my_mtu;
70static in_addr_t my_ip;
71static int netmask;
72
73static in_addr_t ns_ip;
74
75static int bind_port;
76static int debug;
77
78#if !defined(BSD) && !defined(__GLIBC__)
79static char *__progname;
80#endif
81
82static int read_dns(int, struct query *);
83static void write_dns(int, struct query *, char *, int);
84
85static void
86sigint(int sig)
87{
88        running = 0;
89}
90
91static int
92check_user_and_ip(int userid, struct query *q)
93{
94        struct sockaddr_in *tempin;
95
96        if (userid < 0 || userid >= created_users ) {
97                return 1;
98        }
99        if (!users[userid].active) {
100                return 1;
101        }
102
103        /* return early if IP checking is disabled */
104        if (!check_ip) {
105                return 0;
106        }
107
108        tempin = (struct sockaddr_in *) &(q->from);
109        return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
110}
111
112static int
113tunnel_tun(int tun_fd, int dns_fd)
114{
115        unsigned long outlen;
116        struct ip *header;
117        char out[64*1024];
118        char in[64*1024];
119        int userid;
120        int read;
121
122        if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0)
123                return 0;
124       
125        /* find target ip in packet, in is padded with 4 bytes TUN header */
126        header = (struct ip*) (in + 4);
127        userid = find_user_by_ip(header->ip_dst.s_addr);
128        if (userid < 0)
129                return 0;
130
131        outlen = sizeof(out);
132        compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
133
134        /* if another packet is queued, throw away this one. TODO build queue */
135        if (users[userid].outpacket.len == 0) {
136                memcpy(users[userid].outpacket.data, out, outlen);
137                users[userid].outpacket.len = outlen;
138                users[userid].outpacket.offset = 0;
139                users[userid].outpacket.sentlen = 0;
140                users[userid].outpacket.seqno = (++users[userid].outpacket.seqno & 7);
141                users[userid].outpacket.fragment = 0;
142                return outlen;
143        } else {
144                return 0;
145        }
146}
147
148typedef enum {
149        VERSION_ACK,
150        VERSION_NACK,
151        VERSION_FULL
152} version_ack_t;
153
154static void
155send_version_response(int fd, version_ack_t ack, uint32_t payload, int userid, struct query *q)
156{
157        char out[9];
158       
159        switch (ack) {
160        case VERSION_ACK:
161                strncpy(out, "VACK", sizeof(out));
162                break;
163        case VERSION_NACK:
164                strncpy(out, "VNAK", sizeof(out));
165                break;
166        case VERSION_FULL:
167                strncpy(out, "VFUL", sizeof(out));
168                break;
169        }
170       
171        out[4] = ((payload >> 24) & 0xff);
172        out[5] = ((payload >> 16) & 0xff);
173        out[6] = ((payload >> 8) & 0xff);
174        out[7] = ((payload) & 0xff);
175        out[8] = userid & 0xff;
176
177        write_dns(fd, q, out, sizeof(out));
178}
179
180static void
181send_chunk(int dns_fd, int userid) {
182        char pkt[4096];
183        int datalen;
184        int last;
185
186        datalen = MIN(users[userid].fragsize, users[userid].outpacket.len - users[userid].outpacket.offset);
187
188        if (datalen && users[userid].outpacket.sentlen > 0 &&
189                        (
190                        users[userid].outpacket.seqno != users[userid].out_acked_seqno ||
191                        users[userid].outpacket.fragment != users[userid].out_acked_fragment
192                        )
193                ) {
194
195                /* Still waiting on latest ack, send nothing */
196                datalen = 0;
197                last = 0;
198                /* TODO : count down and discard packet if no acks arrive within X queries */
199        } else {
200                memcpy(&pkt[2], &users[userid].outpacket.data[users[userid].outpacket.offset], datalen);
201                users[userid].outpacket.sentlen = datalen;
202                last = (users[userid].outpacket.len == users[userid].outpacket.offset + users[userid].outpacket.sentlen);
203
204                /* Increase fragment# when sending data with offset */
205                if (users[userid].outpacket.offset && datalen)
206                        users[userid].outpacket.fragment++;
207        }
208
209        /* Build downstream data header (see doc/proto_xxxxxxxx.txt) */
210
211        /* First byte is 1 bit compression flag, 3 bits upstream seqno, 4 bits upstream fragment */
212        pkt[0] = (1<<7) | ((users[userid].inpacket.seqno & 7) << 4) | (users[userid].inpacket.fragment & 15);
213        /* Second byte is 3 bits downstream seqno, 4 bits downstream fragment, 1 bit last flag */
214        pkt[1] = ((users[userid].outpacket.seqno & 7) << 5) |
215                ((users[userid].outpacket.fragment & 15) << 1) | (last & 1);
216
217        if (debug >= 1) {
218                printf("OUT  pkt seq# %d, frag %d (last=%d), offset %d, fragsize %d, total %d, to user %d\n",
219                        users[userid].outpacket.seqno & 7, users[userid].outpacket.fragment & 15,
220                        last, users[userid].outpacket.offset, datalen, users[userid].outpacket.len, userid);
221        }
222        write_dns(dns_fd, &users[userid].q, pkt, datalen + 2);
223        users[userid].q.id = 0;
224
225        if (users[userid].outpacket.len > 0 &&
226                users[userid].outpacket.len == users[userid].outpacket.sentlen) {
227
228                /* Whole packet was sent in one chunk, dont wait for ack */
229                users[userid].outpacket.len = 0;
230                users[userid].outpacket.offset = 0;
231                users[userid].outpacket.sentlen = 0;
232        }
233}
234
235static void
236update_downstream_seqno(int dns_fd, int userid, int down_seq, int down_frag)
237{
238        /* If we just read a new packet from tun we have not sent a fragment of, just send it */
239        if (users[userid].outpacket.len > 0 && users[userid].outpacket.sentlen == 0) {
240                send_chunk(dns_fd, userid);
241                return;
242        }
243
244        /* otherwise, check if we received ack on a fragment and can send next */
245        if (users[userid].outpacket.len > 0 &&
246                users[userid].outpacket.seqno == down_seq && users[userid].outpacket.fragment == down_frag) {
247
248                if (down_seq != users[userid].out_acked_seqno || down_frag != users[userid].out_acked_fragment) {
249                        /* Received ACK on downstream fragment */
250                        users[userid].outpacket.offset += users[userid].outpacket.sentlen;
251                        users[userid].outpacket.sentlen = 0;
252
253                        /* Is packet done? */
254                        if (users[userid].outpacket.offset == users[userid].outpacket.len) {
255                                users[userid].outpacket.len = 0;
256                                users[userid].outpacket.offset = 0;
257                                users[userid].outpacket.sentlen = 0;
258                        }
259
260                        users[userid].out_acked_seqno = down_seq;
261                        users[userid].out_acked_fragment = down_frag;
262
263                        /* Send reply if waiting */
264                        if (users[userid].outpacket.len > 0) {
265                                send_chunk(dns_fd, userid);
266                        }
267                }
268        }
269}
270
271static void
272handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
273{
274        struct in_addr tempip;
275        struct ip *hdr;
276        unsigned long outlen;
277        char in[512];
278        char logindata[16];
279        char out[64*1024];
280        char unpacked[64*1024];
281        char *tmp[2];
282        int userid;
283        int touser;
284        int version;
285        int code;
286        int read;
287
288        userid = -1;
289
290        memcpy(in, q->name, MIN(domain_len, sizeof(in)));
291
292        if(in[0] == 'V' || in[0] == 'v') {
293                read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
294                /* Version greeting, compare and send ack/nak */
295                if (read > 4) {
296                        /* Received V + 32bits version */
297                        version = (((unpacked[0] & 0xff) << 24) |
298                                           ((unpacked[1] & 0xff) << 16) |
299                                           ((unpacked[2] & 0xff) << 8) |
300                                           ((unpacked[3] & 0xff)));
301                }
302
303                if (version == VERSION) {
304                        userid = find_available_user();
305                        if (userid >= 0) {
306                                struct sockaddr_in *tempin;
307
308                                users[userid].seed = rand();
309                                /* Store remote IP number */
310                                tempin = (struct sockaddr_in *) &(q->from);
311                                memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
312                               
313                                memcpy(&(users[userid].q), q, sizeof(struct query));
314                                users[userid].encoder = get_base32_encoder();
315                                send_version_response(dns_fd, VERSION_ACK, users[userid].seed, userid, q);
316                                users[userid].q.id = 0;
317                        } else {
318                                /* No space for another user */
319                                send_version_response(dns_fd, VERSION_FULL, created_users, 0, q);
320                        }
321                } else {
322                        send_version_response(dns_fd, VERSION_NACK, VERSION, 0, q);
323                }
324                return;
325        } else if(in[0] == 'L' || in[0] == 'l') {
326                read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
327                /* Login phase, handle auth */
328                userid = unpacked[0];
329
330                if (check_user_and_ip(userid, q) != 0) {
331                        write_dns(dns_fd, q, "BADIP", 5);
332                        return;
333                } else {
334                        users[userid].last_pkt = time(NULL);
335                        login_calculate(logindata, 16, password, users[userid].seed);
336
337                        if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
338                                /* Login ok, send ip/mtu/netmask info */
339
340                                tempip.s_addr = my_ip;
341                                tmp[0] = strdup(inet_ntoa(tempip));
342                                tempip.s_addr = users[userid].tun_ip;
343                                tmp[1] = strdup(inet_ntoa(tempip));
344
345                                read = snprintf(out, sizeof(out), "%s-%s-%d-%d",
346                                                tmp[0], tmp[1], my_mtu, netmask);
347
348                                write_dns(dns_fd, q, out, read);
349                                q->id = 0;
350
351                                free(tmp[1]);
352                                free(tmp[0]);
353                        } else {
354                                write_dns(dns_fd, q, "LNAK", 4);
355                        }
356                }
357                return;
358        } else if(in[0] == 'Z' || in[0] == 'z') {
359                /* Check for case conservation and chars not allowed according to RFC */
360
361                /* Reply with received hostname as data */
362                write_dns(dns_fd, q, in, domain_len);
363                return;
364        } else if(in[0] == 'S' || in[0] == 's') {
365                int codec;
366                struct encoder *enc;
367                if (domain_len != 4) { /* len = 4, example: "S15." */
368                        write_dns(dns_fd, q, "BADLEN", 6);
369                        return;
370                }
371
372                userid = b32_8to5(in[1]);
373               
374                if (check_user_and_ip(userid, q) != 0) {
375                        write_dns(dns_fd, q, "BADIP", 5);
376                        return; /* illegal id */
377                }
378               
379                codec = b32_8to5(in[2]);
380
381                switch (codec) {
382                case 5: /* 5 bits per byte = base32 */
383                        enc = get_base32_encoder();
384                        user_switch_codec(userid, enc);
385                        write_dns(dns_fd, q, enc->name, strlen(enc->name));
386                        break;
387                case 6: /* 6 bits per byte = base64 */
388                        enc = get_base64_encoder();
389                        user_switch_codec(userid, enc);
390                        write_dns(dns_fd, q, enc->name, strlen(enc->name));
391                        break;
392                default:
393                        write_dns(dns_fd, q, "BADCODEC", 8);
394                        break;
395                }
396                return;
397        } else if(in[0] == 'R' || in[0] == 'r') {
398                int req_frag_size;
399
400                /* Downstream fragsize probe packet */
401                userid = (b32_8to5(in[1]) >> 1) & 15;
402                if (check_user_and_ip(userid, q) != 0) {
403                        write_dns(dns_fd, q, "BADIP", 5);
404                        return; /* illegal id */
405                }
406                               
407                req_frag_size = ((b32_8to5(in[1]) & 1) << 10) | ((b32_8to5(in[2]) & 31) << 5) | (b32_8to5(in[3]) & 31);
408                if (req_frag_size < 2 || req_frag_size > 2047) {       
409                        write_dns(dns_fd, q, "BADFRAG", 7);
410                } else {
411                        char buf[2048];
412
413                        memset(buf, 0, sizeof(buf));
414                        buf[0] = (req_frag_size >> 8) & 0xff;
415                        buf[1] = req_frag_size & 0xff;
416                        write_dns(dns_fd, q, buf, req_frag_size);
417                }
418                return;
419        } else if(in[0] == 'N' || in[0] == 'n') {
420                int max_frag_size;
421
422                read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
423                /* Downstream fragsize packet */
424                userid = unpacked[0];
425                if (check_user_and_ip(userid, q) != 0) {
426                        write_dns(dns_fd, q, "BADIP", 5);
427                        return; /* illegal id */
428                }
429                               
430                max_frag_size = ((unpacked[1] & 0xff) << 8) | (unpacked[2] & 0xff);
431                if (max_frag_size < 2) {       
432                        write_dns(dns_fd, q, "BADFRAG", 7);
433                } else {
434                        users[userid].fragsize = max_frag_size;
435                        write_dns(dns_fd, q, &unpacked[1], 2);
436                }
437                return;
438        } else if(in[0] == 'P' || in[0] == 'p') {
439                int dn_seq;
440                int dn_frag;
441               
442                read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
443                /* Ping packet, store userid */
444                userid = unpacked[0];
445                if (check_user_and_ip(userid, q) != 0) {
446                        write_dns(dns_fd, q, "BADIP", 5);
447                        return; /* illegal id */
448                }
449                               
450                if (debug >= 1) {
451                        printf("PING pkt from user %d\n", userid);
452                }
453
454                if (users[userid].q.id != 0) {
455                        /* Send reply on earlier query before overwriting */
456                        send_chunk(dns_fd, userid);
457                }
458
459                dn_seq = unpacked[1] >> 4;
460                dn_frag = unpacked[1] & 15;
461                memcpy(&(users[userid].q), q, sizeof(struct query));
462                users[userid].last_pkt = time(NULL);
463
464                /* Update seqno and maybe send immediate response packet */
465                update_downstream_seqno(dns_fd, userid, dn_seq, dn_frag);
466        } else if((in[0] >= '0' && in[0] <= '9')
467                        || (in[0] >= 'a' && in[0] <= 'f')
468                        || (in[0] >= 'A' && in[0] <= 'F')) {
469                if ((in[0] >= '0' && in[0] <= '9'))
470                        code = in[0] - '0';
471                if ((in[0] >= 'a' && in[0] <= 'f'))
472                        code = in[0] - 'a' + 10;
473                if ((in[0] >= 'A' && in[0] <= 'F'))
474                        code = in[0] - 'A' + 10;
475
476                userid = code;
477                /* Check user and sending ip number */
478                if (check_user_and_ip(userid, q) != 0) {
479                        write_dns(dns_fd, q, "BADIP", 5);
480                } else {
481                        /* Decode data header */
482                        int up_seq = (b32_8to5(in[1]) >> 2) & 7;
483                        int up_frag = ((b32_8to5(in[1]) & 3) << 2) | ((b32_8to5(in[2]) >> 3) & 3);
484                        int dn_seq = (b32_8to5(in[2]) & 7);
485                        int dn_frag = b32_8to5(in[3]) >> 1;
486                        int lastfrag = b32_8to5(in[3]) & 1;
487
488                        if (users[userid].q.id != 0) {
489                                /* Send reply on earlier query before overwriting */
490                                send_chunk(dns_fd, userid);
491                        }
492
493                        /* Update query and time info for user */
494                        users[userid].last_pkt = time(NULL);
495                        memcpy(&(users[userid].q), q, sizeof(struct query));
496
497                        if (up_seq == users[userid].inpacket.seqno &&
498                                up_frag <= users[userid].inpacket.fragment) {
499                                /* Got repeated old packet, skip it */
500                                if (debug >= 1) {
501                                        printf("IN   pkt seq# %d, frag %d, dropped duplicate\n",
502                                                up_seq, up_frag);
503                                }
504                                /* Update seqno and maybe send immediate response packet */
505                                update_downstream_seqno(dns_fd, userid, dn_seq, dn_frag);
506                                return;
507                        }
508                        if (up_seq != users[userid].inpacket.seqno) {
509                                /* New packet has arrived */
510                                users[userid].inpacket.seqno = up_seq;
511                                users[userid].inpacket.len = 0;
512                                users[userid].inpacket.offset = 0;
513                        }
514                        users[userid].inpacket.fragment = up_frag;
515
516                        /* decode with this users encoding */
517                        read = unpack_data(unpacked, sizeof(unpacked), &(in[4]), domain_len - 4,
518                                           users[userid].encoder);
519
520                        /* copy to packet buffer, update length */
521                        memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read);
522                        users[userid].inpacket.len += read;
523                        users[userid].inpacket.offset += read;
524
525                        if (debug >= 1) {
526                                printf("IN   pkt seq# %d, frag %d (last=%d), fragsize %d, total %d, from user %d\n",
527                                        up_seq, up_frag, lastfrag, read, users[userid].inpacket.len, userid);
528                        }
529
530                        if (lastfrag & 1) { /* packet is complete */
531                                int ret;
532                                outlen = sizeof(out);
533                                ret = uncompress((uint8_t*)out, &outlen,
534                                           (uint8_t*)users[userid].inpacket.data, users[userid].inpacket.len);
535
536                                if (ret == Z_OK) {
537                                        hdr = (struct ip*) (out + 4);
538                                        touser = find_user_by_ip(hdr->ip_dst.s_addr);
539
540                                        if (touser == -1) {
541                                                /* send the uncompressed packet to tun device */
542                                                write_tun(tun_fd, out, outlen);
543                                        } else {
544                                                /* send the compressed packet to other client
545                                                 * if another packet is queued, throw away this one. TODO build queue */
546                                                if (users[touser].outpacket.len == 0) {
547                                                        memcpy(users[touser].outpacket.data, users[userid].inpacket.data, users[userid].inpacket.len);
548                                                        users[touser].outpacket.len = users[userid].inpacket.len;
549                                                }
550                                        }
551                                } else {
552                                        printf("Discarded data, uncompress() result: %d\n", ret);
553                                }
554                                users[userid].inpacket.len = users[userid].inpacket.offset = 0;
555                        }
556                        /* Update seqno and maybe send immediate response packet */
557                        update_downstream_seqno(dns_fd, userid, dn_seq, dn_frag);
558                }
559        }
560}
561
562static void
563handle_ns_request(int dns_fd, struct query *q)
564{
565        char buf[64*1024];
566        int len;
567
568        if (ns_ip != INADDR_ANY) {
569                memcpy(&q->destination.s_addr, &ns_ip, sizeof(in_addr_t));
570        }
571
572        len = dns_encode_ns_response(buf, sizeof(buf), q, topdomain);
573       
574        if (debug >= 2) {
575                struct sockaddr_in *tempin;
576                tempin = (struct sockaddr_in *) &(q->from);
577                printf("TX: client %s, type %d, name %s, %d bytes NS reply\n",
578                        inet_ntoa(tempin->sin_addr), q->type, q->name, len);
579        }
580        if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
581                warn("ns reply send error");
582        }
583}
584
585static void
586forward_query(int bind_fd, struct query *q)
587{
588        char buf[64*1024];
589        int len;
590        struct fw_query fwq;
591        struct sockaddr_in *myaddr;
592        in_addr_t newaddr;
593
594        len = dns_encode(buf, sizeof(buf), q, QR_QUERY, q->name, strlen(q->name));
595
596        /* Store sockaddr for q->id */
597        memcpy(&(fwq.addr), &(q->from), q->fromlen);
598        fwq.addrlen = q->fromlen;
599        fwq.id = q->id;
600        fw_query_put(&fwq);
601
602        newaddr = inet_addr("127.0.0.1");
603        myaddr = (struct sockaddr_in *) &(q->from);
604        memcpy(&(myaddr->sin_addr), &newaddr, sizeof(in_addr_t));
605        myaddr->sin_port = htons(bind_port);
606       
607        if (debug >= 2) {
608                printf("TX: NS reply \n");
609        }
610
611        if (sendto(bind_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
612                warn("forward query error");
613        }
614}
615 
616static int
617tunnel_bind(int bind_fd, int dns_fd)
618{
619        char packet[64*1024];
620        struct sockaddr_in from;
621        int fromlen;
622        struct fw_query *query;
623        short id;
624        int r;
625
626        fromlen = sizeof(struct sockaddr);
627        r = recvfrom(bind_fd, packet, sizeof(packet), 0,
628                (struct sockaddr*)&from, &fromlen);
629
630        if (r <= 0)
631                return 0;
632
633        id = dns_get_id(packet, r);
634       
635        if (debug >= 2) {
636                printf("RX: Got response on query %u from DNS\n", (id & 0xFFFF));
637        }
638
639        /* Get sockaddr from id */
640        fw_query_get(id, &query);
641        if (!query && debug >= 2) {
642                printf("Lost sender of id %u, dropping reply\n", (id & 0xFFFF));
643                return 0;
644        }
645
646        if (debug >= 2) {
647                struct sockaddr_in *in;
648                in = (struct sockaddr_in *) &(query->addr);
649                printf("TX: client %s id %u, %d bytes\n",
650                        inet_ntoa(in->sin_addr), (id & 0xffff), r);
651        }
652       
653        if (sendto(dns_fd, packet, r, 0, (const struct sockaddr *) &(query->addr),
654                query->addrlen) <= 0) {
655                warn("forward reply error");
656        }
657
658        return 0;
659}
660
661static int
662tunnel_dns(int tun_fd, int dns_fd, int bind_fd)
663{
664        struct query q;
665        int read;
666        char *domain;
667        int domain_len;
668        int inside_topdomain;
669
670        if ((read = read_dns(dns_fd, &q)) <= 0)
671                return 0;
672
673        if (debug >= 2) {
674                struct sockaddr_in *tempin;
675                tempin = (struct sockaddr_in *) &(q.from);
676                printf("RX: client %s, type %d, name %s\n",
677                        inet_ntoa(tempin->sin_addr), q.type, q.name);
678        }
679       
680        domain = strstr(q.name, topdomain);
681        inside_topdomain = 0;
682        if (domain) {
683                domain_len = (int) (domain - q.name);
684                if (domain_len + strlen(topdomain) == strlen(q.name)) {
685                        inside_topdomain = 1;
686                }
687        }
688       
689        if (inside_topdomain) {
690                /* This is a query we can handle */
691                switch (q.type) {
692                case T_NULL:
693                        handle_null_request(tun_fd, dns_fd, &q, domain_len);
694                        break;
695                case T_NS:
696                        handle_ns_request(dns_fd, &q);
697                        break;
698                default:
699                        break;
700                }
701        } else {
702                /* Forward query to other port ? */
703                if (bind_fd) {
704                        forward_query(bind_fd, &q);
705                }
706        }
707        return 0;
708}
709
710static int
711tunnel(int tun_fd, int dns_fd, int bind_fd)
712{
713        struct timeval tv;
714        fd_set fds;
715        int i;
716
717        while (running) {
718                int maxfd;
719                if (users_waiting_on_reply()) {
720                        tv.tv_sec = 0;
721                        tv.tv_usec = 15000;
722                } else {
723                        tv.tv_sec = 1;
724                        tv.tv_usec = 0;
725                }
726
727                FD_ZERO(&fds);
728
729                FD_SET(dns_fd, &fds);
730                maxfd = dns_fd;
731
732                if (bind_fd) {
733                        /* wait for replies from real DNS */
734                        FD_SET(bind_fd, &fds);
735                        maxfd = MAX(bind_fd, maxfd);
736                }
737
738                /* TODO : use some kind of packet queue */
739                if(!all_users_waiting_to_send()) {
740                        FD_SET(tun_fd, &fds);
741                        maxfd = MAX(tun_fd, maxfd);
742                }
743
744                i = select(maxfd + 1, &fds, NULL, NULL, &tv);
745               
746                if(i < 0) {
747                        if (running)
748                                warn("select");
749                        return 1;
750                }
751
752                if (i==0) {     
753                        int j;
754                        for (j = 0; j < USERS; j++) {
755                                if (users[j].q.id != 0) {
756                                        send_chunk(dns_fd, j);
757                                }
758                        }
759                } else {
760                        if(FD_ISSET(tun_fd, &fds)) {
761                                tunnel_tun(tun_fd, dns_fd);
762                                continue;
763                        }
764                        if(FD_ISSET(dns_fd, &fds)) {
765                                tunnel_dns(tun_fd, dns_fd, bind_fd);
766                                continue;
767                        }
768                        if(FD_ISSET(bind_fd, &fds)) {
769                                tunnel_bind(bind_fd, dns_fd);
770                                continue;
771                        }
772                }
773        }
774
775        return 0;
776}
777
778static int
779read_dns(int fd, struct query *q)
780{
781        struct sockaddr_in from;
782        socklen_t addrlen;
783        char packet[64*1024];
784        int r;
785#ifndef WINDOWS32
786        char address[96];
787        struct msghdr msg;
788        struct iovec iov;
789        struct cmsghdr *cmsg;
790
791        addrlen = sizeof(struct sockaddr);
792        iov.iov_base = packet;
793        iov.iov_len = sizeof(packet);
794
795        msg.msg_name = (caddr_t) &from;
796        msg.msg_namelen = (unsigned) addrlen;
797        msg.msg_iov = &iov;
798        msg.msg_iovlen = 1;
799        msg.msg_control = address;
800        msg.msg_controllen = sizeof(address);
801        msg.msg_flags = 0;
802       
803        r = recvmsg(fd, &msg, 0);
804#else
805        addrlen = sizeof(struct sockaddr);
806        r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
807#endif /* !WINDOWS32 */
808
809        if (r > 0) {
810                dns_decode(NULL, 0, q, QR_QUERY, packet, r);
811                memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
812                q->fromlen = addrlen;
813               
814#ifndef WINDOWS32
815                for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
816                        cmsg = CMSG_NXTHDR(&msg, cmsg)) {
817                       
818                        if (cmsg->cmsg_level == IPPROTO_IP &&
819                                cmsg->cmsg_type == DSTADDR_SOCKOPT) {
820                               
821                                q->destination = *dstaddr(cmsg);
822                                break;
823                        }
824                }
825#endif
826
827                return strlen(q->name);
828        } else if (r < 0) {
829                /* Error */
830                warn("read dns");
831        }
832
833        return 0;
834}
835
836static void
837write_dns(int fd, struct query *q, char *data, int datalen)
838{
839        char buf[64*1024];
840        int len;
841
842        len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, data, datalen);
843       
844        if (debug >= 2) {
845                struct sockaddr_in *tempin;
846                tempin = (struct sockaddr_in *) &(q->from);
847                printf("TX: client %s, type %d, name %s, %d bytes data\n",
848                        inet_ntoa(tempin->sin_addr), q->type, q->name, datalen);
849        }
850
851        sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen);
852}
853
854static void
855usage() {
856        extern char *__progname;
857
858        printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
859                "[-t chrootdir] [-d device] [-m mtu] "
860                "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
861                " tunnel_ip[/netmask] topdomain\n", __progname);
862        exit(2);
863}
864
865static void
866help() {
867        extern char *__progname;
868
869        printf("iodine IP over DNS tunneling server\n");
870        printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] "
871                "[-t chrootdir] [-d device] [-m mtu] "
872                "[-l ip address to listen on] [-p port] [-n external ip] [-b dnsport] [-P password]"
873                " tunnel_ip[/netmask] topdomain\n", __progname);
874        printf("  -v to print version info and exit\n");
875        printf("  -h to print this help and exit\n");
876        printf("  -c to disable check of client IP/port on each request\n");
877        printf("  -s to skip creating and configuring the tun device, "
878                "which then has to be created manually\n");
879        printf("  -f to keep running in foreground\n");
880        printf("  -D to increase debug level\n");
881        printf("  -u name to drop privileges and run as user 'name'\n");
882        printf("  -t dir to chroot to directory dir\n");
883        printf("  -d device to set tunnel device name\n");
884        printf("  -m mtu to set tunnel device mtu\n");
885        printf("  -l ip address to listen on for incoming dns traffic "
886                "(default 0.0.0.0)\n");
887        printf("  -p port to listen on for incoming dns traffic (default 53)\n");
888        printf("  -n ip to respond with to NS queries\n");
889        printf("  -b port to forward normal DNS queries to (on localhost)\n");
890        printf("  -P password used for authentication (max 32 chars will be used)\n");
891        printf("tunnel_ip is the IP number of the local tunnel interface.\n");
892        printf("   /netmask sets the size of the tunnel network.\n");
893        printf("topdomain is the FQDN that is delegated to this server.\n");
894        exit(0);
895}
896
897static void
898version() {
899        char *svnver;
900        svnver = "$Rev$ from $Date$";
901        printf("iodine IP over DNS tunneling server\n");
902        printf("SVN version: %s\n", svnver);
903        exit(0);
904}
905
906int
907main(int argc, char **argv)
908{
909        in_addr_t listen_ip;
910#ifndef WINDOWS32
911        struct passwd *pw;
912#endif
913        int foreground;
914        char *username;
915        char *newroot;
916        char *device;
917        int dnsd_fd;
918        int tun_fd;
919
920        /* settings for forwarding normal DNS to
921         * local real DNS server */
922        int bind_fd;
923        int bind_enable;
924       
925        int choice;
926        int port;
927        int mtu;
928        int skipipconfig;
929        char *netsize;
930
931        username = NULL;
932        newroot = NULL;
933        device = NULL;
934        foreground = 0;
935        bind_enable = 0;
936        bind_fd = 0;
937        mtu = 1024;
938        listen_ip = INADDR_ANY;
939        port = 53;
940        ns_ip = INADDR_ANY;
941        check_ip = 1;
942        skipipconfig = 0;
943        debug = 0;
944        netmask = 27;
945
946        b32 = get_base32_encoder();
947
948#if !defined(BSD) && !defined(__GLIBC__)
949        __progname = strrchr(argv[0], '/');
950        if (__progname == NULL)
951                __progname = argv[0];
952        else
953                __progname++;
954#endif
955
956        memset(password, 0, sizeof(password));
957        srand(time(NULL));
958        fw_query_init();
959       
960        while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:")) != -1) {
961                switch(choice) {
962                case 'v':
963                        version();
964                        break;
965                case 'c':
966                        check_ip = 0;
967                        break;
968                case 's':
969                        skipipconfig = 1;
970                        break;
971                case 'f':
972                        foreground = 1;
973                        break;
974                case 'h':
975                        help();
976                        break;
977                case 'D':
978                        debug++;
979                        break;
980                case 'u':
981                        username = optarg;
982                        break;
983                case 't':
984                        newroot = optarg;
985                        break;
986                case 'd':
987                        device = optarg;
988                        break;
989                case 'm':
990                        mtu = atoi(optarg);
991                        break;
992                case 'l':
993                        listen_ip = inet_addr(optarg);
994                        break;
995                case 'p':
996                        port = atoi(optarg);
997                        break;
998                case 'n':
999                        ns_ip = inet_addr(optarg);
1000                        break;
1001                case 'b':
1002                        bind_enable = 1;
1003                        bind_port = atoi(optarg);
1004                        break;
1005                case 'P':
1006                        strncpy(password, optarg, sizeof(password));
1007                        password[sizeof(password)-1] = 0;
1008                       
1009                        /* XXX: find better way of cleaning up ps(1) */
1010                        memset(optarg, 0, strlen(optarg));
1011                        break;
1012                default:
1013                        usage();
1014                        break;
1015                }
1016        }
1017
1018        argc -= optind;
1019        argv += optind;
1020
1021        check_superuser(usage);
1022
1023        if (argc != 2)
1024                usage();
1025       
1026        netsize = strchr(argv[0], '/');
1027        if (netsize) {
1028                *netsize = 0;
1029                netsize++;
1030                netmask = atoi(netsize);
1031        }
1032
1033        my_ip = inet_addr(argv[0]);
1034       
1035        if (my_ip == INADDR_NONE) {
1036                warnx("Bad IP address to use inside tunnel.\n");
1037                usage();
1038        }
1039
1040        topdomain = strdup(argv[1]);
1041        if(strlen(topdomain) <= 128) {
1042                if(check_topdomain(topdomain)) {
1043                        warnx("Topdomain contains invalid characters.\n");
1044                        usage();
1045                }
1046        } else {
1047                warnx("Use a topdomain max 128 chars long.\n");
1048                usage();
1049        }
1050
1051        if (username != NULL) {
1052#ifndef WINDOWS32
1053                if ((pw = getpwnam(username)) == NULL) {
1054                        warnx("User %s does not exist!\n", username);
1055                        usage();
1056                }
1057#endif
1058        }
1059
1060        if (mtu <= 0) {
1061                warnx("Bad MTU given.\n");
1062                usage();
1063        }
1064       
1065        if(port < 1 || port > 65535) {
1066                warnx("Bad port number given.\n");
1067                usage();
1068        }
1069       
1070        if(bind_enable) {
1071                if (bind_port < 1 || bind_port > 65535 || bind_port == port) {
1072                        warnx("Bad DNS server port number given.\n");
1073                        usage();
1074                        /* NOTREACHED */
1075                }
1076                printf("Requests for domains outside of %s will be forwarded to port %d\n",
1077                        topdomain, bind_port);
1078        }
1079       
1080        if (port != 53) {
1081                printf("ALERT! Other dns servers expect you to run on port 53.\n");
1082                printf("You must manually forward port 53 to port %d for things to work.\n", port);
1083        }
1084
1085        if (debug) {
1086                printf("Debug level %d enabled, will stay in foreground.\n", debug);
1087                printf("Add more -D switches to set higher debug level.\n");
1088                foreground = 1;
1089        }
1090
1091        if (listen_ip == INADDR_NONE) {
1092                warnx("Bad IP address to listen on.\n");
1093                usage();
1094        }
1095       
1096        if (ns_ip == INADDR_NONE) {
1097                warnx("Bad IP address to return as nameserver.\n");
1098                usage();
1099        }
1100        if (netmask > 30 || netmask < 8) {
1101                warnx("Bad netmask (%d bits). Use 8-30 bits.\n", netmask);
1102                usage();
1103        }
1104       
1105        if (strlen(password) == 0)
1106                read_password(password, sizeof(password));
1107
1108        if ((tun_fd = open_tun(device)) == -1)
1109                goto cleanup0;
1110        if (!skipipconfig)
1111                if (tun_setip(argv[0], netmask) != 0 || tun_setmtu(mtu) != 0)
1112                        goto cleanup1;
1113        if ((dnsd_fd = open_dns(port, listen_ip)) == -1)
1114                goto cleanup2;
1115        if (bind_enable)
1116                if ((bind_fd = open_dns(0, INADDR_ANY)) == -1)
1117                        goto cleanup3;
1118
1119        my_mtu = mtu;
1120
1121        created_users = init_users(my_ip, netmask);
1122       
1123        if (created_users < USERS) {
1124                printf("Limiting to %d simultaneous users because of netmask /%d\n",
1125                        created_users, netmask);
1126        }
1127        printf("Listening to dns for domain %s\n", topdomain);
1128
1129        if (foreground == 0)
1130                do_detach();
1131       
1132        if (newroot != NULL)
1133                do_chroot(newroot);
1134
1135        signal(SIGINT, sigint);
1136        if (username != NULL) {
1137#ifndef WINDOWS32
1138                gid_t gids[1];
1139                gids[0] = pw->pw_gid;
1140                if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
1141                        warnx("Could not switch to user %s!\n", username);
1142                        usage();
1143                }
1144#endif
1145        }
1146       
1147        tunnel(tun_fd, dnsd_fd, bind_fd);
1148
1149cleanup3:
1150        close_dns(bind_fd);
1151cleanup2:
1152        close_dns(dnsd_fd);
1153cleanup1:
1154        close_tun(tun_fd);     
1155cleanup0:
1156
1157        return 0;
1158}
Note: See TracBrowser for help on using the repository browser.