mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-24 18:45:12 +00:00
Look up external IP via DNS instead of HTTP
Use myip.opendns.com via their resolver. The code is now TCP free again :)
This commit is contained in:
parent
e8a4c66719
commit
2032b44949
@ -13,11 +13,11 @@ master:
|
|||||||
- README converted to markdown by Nicolas Braud-Santoni.
|
- README converted to markdown by Nicolas Braud-Santoni.
|
||||||
- Linux: use pkg-config for systemd support flags.
|
- Linux: use pkg-config for systemd support flags.
|
||||||
Patch by Jason A. Donenfeld.
|
Patch by Jason A. Donenfeld.
|
||||||
- Change external IP webservice to ipify.org
|
|
||||||
- Add support for IPv6 in the server.
|
- Add support for IPv6 in the server.
|
||||||
Raw mode will be with same protocol as used for login.
|
Raw mode will be with same protocol as used for login.
|
||||||
Traffic inside tunnel is still IPv4.
|
Traffic inside tunnel is still IPv4.
|
||||||
- Update android build to support 5.0 (Lollipop) and newer.
|
- Update android build to support 5.0 (Lollipop) and newer.
|
||||||
|
- Change external IP lookup to using myip.opendns.com via DNS.
|
||||||
|
|
||||||
2014-06-16: 0.7.0 "Kryoptonite"
|
2014-06-16: 0.7.0 "Kryoptonite"
|
||||||
- Partial IPv6 support (#107)
|
- Partial IPv6 support (#107)
|
||||||
|
@ -286,7 +286,7 @@ You must make sure the dns requests are forwarded to this port yourself.
|
|||||||
.B -n auto|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 ipify.org web service to
|
If external_ip is 'auto', iodined will use the opendns.com DNS service to
|
||||||
retrieve the external IP of the host and use that for NS responses.
|
retrieve the external IP of the host and use that for NS responses.
|
||||||
.TP
|
.TP
|
||||||
.B -b dnsport
|
.B -b dnsport
|
||||||
|
15
src/dns.c
15
src/dns.c
@ -492,6 +492,8 @@ int dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet,
|
|||||||
readlong(packet, &data, &ttl);
|
readlong(packet, &data, &ttl);
|
||||||
readshort(packet, &data, &rlen);
|
readshort(packet, &data, &rlen);
|
||||||
|
|
||||||
|
if (type == T_CNAME) {
|
||||||
|
/* For tunnels, query type A has CNAME type answer */
|
||||||
memset(name, 0, sizeof(name));
|
memset(name, 0, sizeof(name));
|
||||||
readname(packet, packetlen, &data, name, sizeof(name) - 1);
|
readname(packet, packetlen, &data, name, sizeof(name) - 1);
|
||||||
name[sizeof(name)-1] = '\0';
|
name[sizeof(name)-1] = '\0';
|
||||||
@ -499,6 +501,19 @@ int dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet,
|
|||||||
buf[buflen - 1] = '\0';
|
buf[buflen - 1] = '\0';
|
||||||
rv = strlen(buf);
|
rv = strlen(buf);
|
||||||
}
|
}
|
||||||
|
if (type == T_A) {
|
||||||
|
/* Answer type A includes only 4 bytes.
|
||||||
|
Not used for tunneling. */
|
||||||
|
rv = MIN(rlen, sizeof(rdata));
|
||||||
|
rv = readdata(packet, &data, rdata, rv);
|
||||||
|
if (rv >= 2 && buf) {
|
||||||
|
rv = MIN(rv, buflen);
|
||||||
|
memcpy(buf, rdata, rv);
|
||||||
|
} else {
|
||||||
|
rv = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if ((type == T_MX || type == T_SRV) && buf) {
|
else if ((type == T_MX || type == T_SRV) && buf) {
|
||||||
/* We support 250 records, 250*(255+header) ~= 64kB.
|
/* We support 250 records, 250*(255+header) ~= 64kB.
|
||||||
Only exact 10-multiples are accepted, and gaps in
|
Only exact 10-multiples are accepted, and gaps in
|
||||||
|
@ -123,57 +123,57 @@ get_dns_fd(struct dnsfd *fds, struct sockaddr_storage *addr)
|
|||||||
return fds->v4fd;
|
return fds->v4fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ask ipify.org webservice to get external ip */
|
/* Ask opendns.com DNS service for external ip */
|
||||||
static int
|
static int
|
||||||
get_external_ip(struct in_addr *ip)
|
get_external_ip(struct in_addr *ip)
|
||||||
{
|
{
|
||||||
int sock;
|
static const char target[] = "myip.opendns.com";
|
||||||
struct addrinfo *addr;
|
struct query query;
|
||||||
|
int attempt;
|
||||||
int res;
|
int res;
|
||||||
const char *getstr = "GET / HTTP/1.0\r\n"
|
int fd;
|
||||||
/* HTTP 1.0 to avoid chunked transfer coding */
|
int out_len = 0;
|
||||||
"Host: api.ipify.org\r\n\r\n";
|
memset(&query, 0, sizeof(query));
|
||||||
char buf[512];
|
|
||||||
char *b;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
res = getaddrinfo("api.ipify.org", "80", NULL, &addr);
|
query.type = T_A;
|
||||||
|
res = get_addr("resolver1.opendns.com", 53, AF_INET, 0, &query.destination);
|
||||||
if (res < 0) return 1;
|
if (res < 0) return 1;
|
||||||
|
query.dest_len = res;
|
||||||
|
|
||||||
sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
fd = open_dns_from_host(NULL, 0, AF_INET, AI_PASSIVE);
|
||||||
if (sock < 0) {
|
if (fd < 0) return 2;
|
||||||
freeaddrinfo(addr);
|
|
||||||
return 2;
|
for (attempt = 0; attempt < 3; attempt++) {
|
||||||
|
char buf[64*1024];
|
||||||
|
int buflen;
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (attempt) fprintf(stderr, "Retrying external IP lookup\n");
|
||||||
|
query.id = rand();
|
||||||
|
buflen = sizeof(buf);
|
||||||
|
buflen = dns_encode(buf, buflen, &query, QR_QUERY, target, strlen(target));
|
||||||
|
if (buflen < 0) continue;
|
||||||
|
|
||||||
|
sendto(fd, buf, buflen, 0, (struct sockaddr*)&query.destination, query.dest_len);
|
||||||
|
|
||||||
|
tv.tv_sec = 1 + attempt;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
res = select(fd + 1, &fds, NULL, NULL, &tv);
|
||||||
|
if (res > 0) {
|
||||||
|
buflen = sizeof(buf);
|
||||||
|
buflen = recv(fd, buf, buflen, 0);
|
||||||
|
if (buflen > 0) {
|
||||||
|
out_len = dns_decode((char *)ip, sizeof(struct in_addr), &query, QR_ANSWER, buf, buflen);
|
||||||
|
if (out_len > 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = connect(sock, addr->ai_addr, addr->ai_addrlen);
|
close_dns(fd);
|
||||||
freeaddrinfo(addr);
|
return (out_len != sizeof(struct in_addr));
|
||||||
if (res < 0) return 3;
|
|
||||||
|
|
||||||
res = write(sock, getstr, strlen(getstr));
|
|
||||||
if (res != strlen(getstr)) return 4;
|
|
||||||
|
|
||||||
/* Zero buf before receiving, leave at least one zero at the end */
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
res = read(sock, buf, sizeof(buf) - 1);
|
|
||||||
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
|
||||||
@ -2616,7 +2616,7 @@ main(int argc, char **argv)
|
|||||||
struct in_addr extip;
|
struct in_addr extip;
|
||||||
int res = get_external_ip(&extip);
|
int res = get_external_ip(&extip);
|
||||||
if (res) {
|
if (res) {
|
||||||
fprintf(stderr, "Failed to get external IP via web service.\n");
|
fprintf(stderr, "Failed to get external IP via DNS query.\n");
|
||||||
exit(3);
|
exit(3);
|
||||||
}
|
}
|
||||||
ns_ip = extip.s_addr;
|
ns_ip = extip.s_addr;
|
||||||
|
Loading…
Reference in New Issue
Block a user