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.
This commit is contained in:
Erik Ekman 2012-09-03 10:34:27 +02:00
parent 9443f3bbe9
commit 43e4fb5448
3 changed files with 74 additions and 2 deletions

View file

@ -6,6 +6,7 @@ iodine - http://code.kryo.se/iodine
CHANGES: CHANGES:
trunk: trunk:
- Add automated lookup of external ip (via -n auto).
2010-02-06: 0.6.0-rc1 "Hotspotify" 2010-02-06: 0.6.0-rc1 "Hotspotify"
- Fixed tunnel not working on Windows. - Fixed tunnel not working on Windows.

View file

@ -58,7 +58,11 @@ iodine, iodined \- tunnel IPv4 over DNS
.B ] [-p .B ] [-p
.I port .I port
.B ] [-n .B ] [-n
(
.B auto
|
.I external_ip .I external_ip
)
.B ] [-b .B ] [-b
.I dnsport .I dnsport
.B ] [-P .B ] [-P
@ -260,9 +264,11 @@ as 'dnsport'.
.B Note: .B Note:
You must make sure the dns requests are forwarded to this port yourself. You must make sure the dns requests are forwarded to this port yourself.
.TP .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 The IP address to return in NS responses. Default is to return the address used
as destination in the query. 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 .TP
.B -b dnsport .B -b dnsport
If this port is specified, all incoming requests not inside the tunnel domain If this port is specified, all incoming requests not inside the tunnel domain

View file

@ -93,6 +93,54 @@ static int read_dns(int, int, struct query *);
static void write_dns(int, struct query *, char *, int, char); static void write_dns(int, struct query *, char *, int, char);
static void handle_full_packet(int, int, int); 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 static void
sigint(int sig) sigint(int sig)
{ {
@ -2196,6 +2244,7 @@ main(int argc, char **argv)
int mtu; int mtu;
int skipipconfig; int skipipconfig;
char *netsize; char *netsize;
int ns_get_externalip;
int retval; int retval;
#ifndef WINDOWS32 #ifndef WINDOWS32
@ -2213,6 +2262,7 @@ main(int argc, char **argv)
listen_ip = INADDR_ANY; listen_ip = INADDR_ANY;
port = 53; port = 53;
ns_ip = INADDR_ANY; ns_ip = INADDR_ANY;
ns_get_externalip = 0;
check_ip = 1; check_ip = 1;
skipipconfig = 0; skipipconfig = 0;
debug = 0; debug = 0;
@ -2281,7 +2331,11 @@ main(int argc, char **argv)
port = atoi(optarg); port = atoi(optarg);
break; break;
case 'n': case 'n':
ns_ip = inet_addr(optarg); if (optarg && strcmp("auto", optarg) == 0) {
ns_get_externalip = 1;
} else {
ns_ip = inet_addr(optarg);
}
break; break;
case 'b': case 'b':
bind_enable = 1; bind_enable = 1;
@ -2391,6 +2445,17 @@ main(int argc, char **argv)
usage(); 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) { if (ns_ip == INADDR_NONE) {
warnx("Bad IP address to return as nameserver."); warnx("Bad IP address to return as nameserver.");
usage(); usage();