From 43e4fb5448ee539fd184d12b8fdef9c4966551f3 Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Mon, 3 Sep 2012 10:34:27 +0200 Subject: [PATCH] Add automatic external IP lookup via '-n auto' Leonard Lausen proposed iodined should use externalip.net api to find external ip. Use -n auto to trigger a lookup. --- CHANGELOG | 1 + man/iodine.8 | 8 +++++- src/iodined.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7171fbb..7e40660 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ iodine - http://code.kryo.se/iodine CHANGES: trunk: + - Add automated lookup of external ip (via -n auto). 2010-02-06: 0.6.0-rc1 "Hotspotify" - Fixed tunnel not working on Windows. diff --git a/man/iodine.8 b/man/iodine.8 index 87f5d95..f551399 100644 --- a/man/iodine.8 +++ b/man/iodine.8 @@ -58,7 +58,11 @@ iodine, iodined \- tunnel IPv4 over DNS .B ] [-p .I port .B ] [-n +( +.B auto +| .I external_ip +) .B ] [-b .I dnsport .B ] [-P @@ -260,9 +264,11 @@ as 'dnsport'. .B Note: You must make sure the dns requests are forwarded to this port yourself. .TP -.B -n external_ip +.B -n auto|external_ip The IP address to return in NS responses. Default is to return the address used as destination in the query. +If external_ip is 'auto', iodined will use externalip.net web service to +retrieve the external IP of the host and use that for NS responses. .TP .B -b dnsport If this port is specified, all incoming requests not inside the tunnel domain diff --git a/src/iodined.c b/src/iodined.c index 3bfbd4e..b3b0607 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -93,6 +93,54 @@ static int read_dns(int, int, struct query *); static void write_dns(int, struct query *, char *, int, char); static void handle_full_packet(int, int, int); +/* Ask externalip.net webservice to get external ip */ +static int get_external_ip(struct in_addr *ip) +{ + int sock; + struct addrinfo *addr; + int res; + const char *getstr = "GET /ip/ HTTP/1.1\r\nHost: api.externalip.net\r\n\r\n"; + char buf[512]; + char *b; + int len; + + res = getaddrinfo("api.externalip.net", "80", NULL, &addr); + if (res < 0) return 1; + + sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (sock < 0) { + freeaddrinfo(addr); + return 2; + } + + res = connect(sock, addr->ai_addr, addr->ai_addrlen); + freeaddrinfo(addr); + if (res < 0) return 3; + + res = write(sock, getstr, strlen(getstr)); + if (res != strlen(getstr)) return 4; + + res = read(sock, buf, sizeof(buf)); + if (res < 0) return 5; + len = res; + + res = close(sock); + if (res < 0) return 6; + + b = buf; + while (len > 9) { + /* Look for split between headers and data */ + if (strncmp("\r\n\r\n", b, 4) == 0) break; + b++; + len--; + } + if (len < 10) return 7; + b += 4; + + res = inet_aton(b, ip); + return (res == 0); +} + static void sigint(int sig) { @@ -2196,6 +2244,7 @@ main(int argc, char **argv) int mtu; int skipipconfig; char *netsize; + int ns_get_externalip; int retval; #ifndef WINDOWS32 @@ -2213,6 +2262,7 @@ main(int argc, char **argv) listen_ip = INADDR_ANY; port = 53; ns_ip = INADDR_ANY; + ns_get_externalip = 0; check_ip = 1; skipipconfig = 0; debug = 0; @@ -2281,7 +2331,11 @@ main(int argc, char **argv) port = atoi(optarg); break; case 'n': - ns_ip = inet_addr(optarg); + if (optarg && strcmp("auto", optarg) == 0) { + ns_get_externalip = 1; + } else { + ns_ip = inet_addr(optarg); + } break; case 'b': bind_enable = 1; @@ -2391,6 +2445,17 @@ main(int argc, char **argv) usage(); } + if (ns_get_externalip) { + struct in_addr extip; + int res = get_external_ip(&extip); + if (res) { + fprintf(stderr, "Failed to get external IP via web service.\n"); + exit(3); + } + ns_ip = extip.s_addr; + fprintf(stderr, "Using %s as external IP.\n", inet_ntoa(extip)); + } + if (ns_ip == INADDR_NONE) { warnx("Bad IP address to return as nameserver."); usage();