2 * Copyright (c) 2006 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
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.
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.
21 #include <netinet/in.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
39 #define MAX(a,b) ((a)>(b)?(a):(b))
44 struct packet packetbuf;
45 struct packet outpacket;
59 tunnel(int tun_fd, int dns_fd)
61 struct in_addr clientip;
83 if(outpacket.len == 0)
87 i = select(MAX(tun_fd, dns_fd) + 1, &fds, NULL, NULL, &tv);
97 dnsd_send(dns_fd, &q, outpacket.data, outpacket.len);
102 if(FD_ISSET(tun_fd, &fds)) {
103 read = read_tun(tun_fd, in, sizeof(in));
107 outlen = sizeof(out);
108 compress2(out, &outlen, in, read, 9);
109 memcpy(outpacket.data, out, outlen);
110 outpacket.len = outlen;
112 if(FD_ISSET(dns_fd, &fds)) {
113 read = dnsd_read(dns_fd, &q, in, sizeof(in));
117 if(in[0] == 'H' || in[0] == 'h') {
119 clientip.s_addr = my_ip + inet_addr("0.0.0.1");
121 tmp[0] = strdup(inet_ntoa(myip));
122 tmp[1] = strdup(inet_ntoa(clientip));
124 read = snprintf(out, sizeof(out), "%s-%s-%d",
125 tmp[0], tmp[1], my_mtu);
127 dnsd_send(dns_fd, &q, out, read);
132 } else if((in[0] >= '0' && in[0] <= '9')
133 || (in[0] >= 'a' && in[0] <= 'f')
134 || (in[0] >= 'A' && in[0] <= 'F')) {
135 if ((in[0] >= '0' && in[0] <= '9'))
137 if ((in[0] >= 'a' && in[0] <= 'f'))
138 code = in[0] - 'a' + 10;
139 if ((in[0] >= 'A' && in[0] <= 'F'))
140 code = in[0] - 'A' + 10;
142 memcpy(packetbuf.data + packetbuf.offset, in + 1, read - 1);
143 packetbuf.len += read - 1;
144 packetbuf.offset += read - 1;
147 outlen = sizeof(out);
148 uncompress(out, &outlen, packetbuf.data, packetbuf.len);
150 write_tun(tun_fd, out, outlen);
152 packetbuf.len = packetbuf.offset = 0;
155 if (outpacket.len > 0) {
156 dnsd_send(dns_fd, &q, outpacket.data, outpacket.len);
169 extern char *__progname;
171 printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] [-m mtu] [-l ip address to listen on] [-p port]"
172 " tunnel_ip topdomain\n", __progname);
178 extern char *__progname;
180 printf("iodine IP over DNS tunneling server\n");
181 printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] [-m mtu] [-l ip address to listen on] [-p port]"
182 " tunnel_ip topdomain\n", __progname);
183 printf(" -v to print version info and exit\n");
184 printf(" -h to print this help and exit\n");
185 printf(" -f to keep running in foreground\n");
186 printf(" -u name to drop privileges and run as user 'name'\n");
187 printf(" -t dir to chroot to directory dir\n");
188 printf(" -d device to set tunnel device name\n");
189 printf(" -m mtu to set tunnel device mtu\n");
190 printf(" -l ip address to listen on for incoming dns traffic (default 0.0.0.0)\n");
191 printf(" -p port to listen on for incoming dns traffic (default 53)\n");
192 printf("tunnel_ip is the IP number of the local tunnel interface.\n");
193 printf("topdomain is the FQDN that is delegated to this server.\n");
199 printf("iodine IP over DNS tunneling server\n");
200 printf("version: 0.3.4 from 2006-11-08\n");
205 main(int argc, char **argv)
224 listen_ip = INADDR_ANY;
228 packetbuf.offset = 0;
232 while ((choice = getopt(argc, argv, "vfhu:t:d:m:l:p:")) != -1) {
256 listen_ip = inet_addr(optarg);
270 if (geteuid() != 0) {
271 printf("Run as root and you'll be happy.\n");
279 pw = getpwnam(username);
281 printf("User %s does not exist!\n", username);
287 printf("Bad MTU given.\n");
291 if (listen_ip == INADDR_NONE) {
292 printf("Bad IP address to listen on.\n");
296 if ((tun_fd = open_tun(device)) == -1)
298 if (tun_setip(argv[0]) != 0 || tun_setmtu(mtu) != 0)
300 if ((dnsd_fd = open_dns(argv[1], port, listen_ip)) == -1)
303 my_ip = inet_addr(argv[0]);
306 printf("Listening to dns for domain %s\n", argv[1]);
309 if (chroot(newroot) != 0 || chdir("/") != 0)
310 err(1, "%s", newroot);
316 printf("Detaching from terminal...\n");
322 signal(SIGINT, sigint);
324 if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
325 printf("Could not switch to user %s!\n", username);
330 tunnel(tun_fd, dnsd_fd);