diff --git a/README.md b/README.md index 61ab5ad..1c76829 100644 --- a/README.md +++ b/README.md @@ -123,8 +123,9 @@ end of the tunnel. In this case, `ping 192.168.99.1` from the iodine client, and #### IPv6 The data inside the tunnel is IPv4 only. -The server listens to both IPv4 and IPv6 for incoming requests. Raw mode -will be attempted on the same protocol as used for the login. +The server listens to both IPv4 and IPv6 for incoming requests by default. +Use options `-4` or `-6` to only listen on one protocol. Raw mode will be +attempted on the same protocol as used for the login. The client can use IPv4 or IPv6 nameservers to connect to iodined. The relay nameservers will translate between protocols automatically if needed. Use diff --git a/man/iodine.8 b/man/iodine.8 index 3a8cea6..0eb9b9b 100644 --- a/man/iodine.8 +++ b/man/iodine.8 @@ -45,7 +45,7 @@ iodine, iodined \- tunnel IPv4 over DNS .B iodined [-h] -.B iodined [-c] [-s] [-f] [-D] [-u +.B iodined [-4] [-6] [-c] [-s] [-f] [-D] [-u .I user .B ] [-t .I chrootdir @@ -112,6 +112,12 @@ Print usage info and exit. .B -f Keep running in foreground. .TP +.B -4 +Force/allow only IPv4 DNS queries +.TP +.B -6 +Force/allow only IPv6 DNS queries +.TP .B -u user Drop privileges and run as user 'user' after setting up tunnel. .TP @@ -135,12 +141,6 @@ Apply SELinux 'context' after initialization. Create 'pidfile' and write process id in it. .SS Client Options: .TP -.B -4 -Force IPv4 DNS queries -.TP -.B -6 -Force IPv6 DNS queries -.TP .B -r Skip raw UDP mode. If not used, iodine will try getting the public IP address of the iodined host and test if it is reachable directly. If it is, traffic diff --git a/src/iodined.c b/src/iodined.c index c78361c..51b9c13 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -2290,7 +2290,8 @@ static void print_usage() { extern char *__progname; - fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " + fprintf(stderr, "Usage: %s [-v] [-h] " + "[-4] [-6] [-c] [-s] [-f] [-D] [-u user] " "[-t chrootdir] [-d device] [-m mtu] [-z context] " "[-l ipv4 listen address] [-L ipv6 listen address] " "[-p port] [-n external ip] [-b dnsport] " @@ -2310,6 +2311,8 @@ help() { print_usage(); fprintf(stderr, " -v to print version info and exit\n"); fprintf(stderr, " -h to print this help and exit\n"); + fprintf(stderr, " -4 to listen only on IPv4\n"); + fprintf(stderr, " -6 to listen only on IPv6\n"); fprintf(stderr, " -c to disable check of client IP/port on each request\n"); fprintf(stderr, " -s to skip creating and configuring the tun device, " "which then has to be created manually\n"); @@ -2378,6 +2381,7 @@ main(int argc, char **argv) char *context; char *device; char *pidfile; + int addrfamily; struct dnsfd dns_fds; int tun_fd; @@ -2420,6 +2424,7 @@ main(int argc, char **argv) port = 53; ns_ip = INADDR_ANY; ns_get_externalip = 0; + addrfamily = AF_UNSPEC; check_ip = 1; skipipconfig = 0; debug = 0; @@ -2449,8 +2454,14 @@ main(int argc, char **argv) srand(time(NULL)); fw_query_init(); - while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) { + while ((choice = getopt(argc, argv, "46vcsfhDu:t:d:m:l:L:p:n:b:P:z:F:i:")) != -1) { switch(choice) { + case '4': + addrfamily = AF_INET; + break; + case '6': + addrfamily = AF_INET6; + break; case 'v': version(); break; @@ -2669,11 +2680,14 @@ main(int argc, char **argv) dns_fds.v4fd = SD_LISTEN_FDS_START; } else { #endif - if ((dns_fds.v4fd = open_dns(&dns4addr, dns4addr_len)) < 0) { + if ((addrfamily == AF_UNSPEC || addrfamily == AF_INET) && + (dns_fds.v4fd = open_dns(&dns4addr, dns4addr_len)) < 0) { + retval = 1; goto cleanup; } - if ((dns_fds.v6fd = open_dns(&dns6addr, dns6addr_len)) < 0) { + if ((addrfamily == AF_UNSPEC || addrfamily == AF_INET6) && + (dns_fds.v6fd = open_dns(&dns6addr, dns6addr_len)) < 0) { retval = 1; goto cleanup; }