mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-25 11:05:15 +00:00
Added command line options for TCP forwarding - untested
This commit is contained in:
parent
0c33c81e3d
commit
b1d7a78adf
88
src/iodine.c
88
src/iodine.c
@ -27,6 +27,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
@ -137,8 +138,8 @@ static struct client_instance preset_fast = {
|
|||||||
.max_downstream_frag_size = 1176,
|
.max_downstream_frag_size = 1176,
|
||||||
.compression_up = 1,
|
.compression_up = 1,
|
||||||
.compression_down = 1,
|
.compression_down = 1,
|
||||||
.windowsize_up = 64,
|
.windowsize_up = 30,
|
||||||
.windowsize_down = 32,
|
.windowsize_down = 30,
|
||||||
.hostname_maxlen = 0xFF,
|
.hostname_maxlen = 0xFF,
|
||||||
.downenc = ' ',
|
.downenc = ' ',
|
||||||
.do_qtype = T_UNSET,
|
.do_qtype = T_UNSET,
|
||||||
@ -216,7 +217,7 @@ print_usage()
|
|||||||
|
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-Y preset] [-V sec] [-X port] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
fprintf(stderr, "Usage: %s [-v] [-h] [-Y preset] [-V sec] [-X port] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
|
||||||
"[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] "
|
"[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] "
|
||||||
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-R rdomain] "
|
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-R port[,host] ] "
|
||||||
"[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [...]]]\n", __progname);
|
"[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [...]]]\n", __progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +262,7 @@ help()
|
|||||||
fprintf(stderr, " -W upstream fragment window size (default: 8 frags)\n");
|
fprintf(stderr, " -W upstream fragment window size (default: 8 frags)\n");
|
||||||
fprintf(stderr, " -i server-side request timeout in lazy mode (default: auto)\n");
|
fprintf(stderr, " -i server-side request timeout in lazy mode (default: auto)\n");
|
||||||
fprintf(stderr, " -j downstream fragment ACK timeout, implies -i4 (default: 2 sec)\n");
|
fprintf(stderr, " -j downstream fragment ACK timeout, implies -i4 (default: 2 sec)\n");
|
||||||
|
//fprintf(stderr, " --nodrop disable TCP packet-dropping optimisations\n");
|
||||||
fprintf(stderr, " -c 1: use downstream compression (default), 0: disable\n");
|
fprintf(stderr, " -c 1: use downstream compression (default), 0: disable\n");
|
||||||
fprintf(stderr, " -C 1: use upstream compression (default), 0: disable\n\n");
|
fprintf(stderr, " -C 1: use upstream compression (default), 0: disable\n\n");
|
||||||
|
|
||||||
@ -268,9 +270,6 @@ help()
|
|||||||
fprintf(stderr, " -v, --version print version info and exit\n");
|
fprintf(stderr, " -v, --version print version info and exit\n");
|
||||||
fprintf(stderr, " -h, --help print this help and exit\n");
|
fprintf(stderr, " -h, --help print this help and exit\n");
|
||||||
fprintf(stderr, " -V, --stats print connection statistics at given intervals (default: 5 sec)\n");
|
fprintf(stderr, " -V, --stats print connection statistics at given intervals (default: 5 sec)\n");
|
||||||
/*fprintf(stderr, " -X skip tun device and forward data to/from stdin/out, telling iodined to\n");
|
|
||||||
fprintf(stderr, " connect to the specified port listening on the server host.\n");
|
|
||||||
fprintf(stderr, " Can be used with SSH ProxyCommand option. (-X 22)\n");*/
|
|
||||||
fprintf(stderr, " -f keep running in foreground\n");
|
fprintf(stderr, " -f keep running in foreground\n");
|
||||||
fprintf(stderr, " -D enable debug mode (add more D's to increase debug level)\n");
|
fprintf(stderr, " -D enable debug mode (add more D's to increase debug level)\n");
|
||||||
fprintf(stderr, " -d set tunnel device name\n");
|
fprintf(stderr, " -d set tunnel device name\n");
|
||||||
@ -278,6 +277,11 @@ help()
|
|||||||
fprintf(stderr, " -F write PID to specified file\n");
|
fprintf(stderr, " -F write PID to specified file\n");
|
||||||
fprintf(stderr, " -Y, --preset use a set of predefined options for DNS tunnel (can be overridden manually)\n");
|
fprintf(stderr, " -Y, --preset use a set of predefined options for DNS tunnel (can be overridden manually)\n");
|
||||||
print_presets(6);
|
print_presets(6);
|
||||||
|
fprintf(stderr, " -R, --remote [host:]port skip tun device and forward data to/from\n");
|
||||||
|
fprintf(stderr, " stdin/out, telling iodined to forward data to a remote port\n");
|
||||||
|
fprintf(stderr, " locally or to a specific host (accessed by server). Implies --nodrop.\n");
|
||||||
|
fprintf(stderr, " To specify an IPv6 address, host must be enclosed in square brackets.\n");
|
||||||
|
fprintf(stderr, " Can be used with SSH ProxyCommand option. ('iodine -R 22 ...')\n");
|
||||||
fprintf(stderr, " --chroot chroot to given directory\n");
|
fprintf(stderr, " --chroot chroot to given directory\n");
|
||||||
fprintf(stderr, " --context apply specified SELinux context after initialization\n");
|
fprintf(stderr, " --context apply specified SELinux context after initialization\n");
|
||||||
fprintf(stderr, " --rdomain use specified routing domain (OpenBSD only)\n\n");
|
fprintf(stderr, " --rdomain use specified routing domain (OpenBSD only)\n\n");
|
||||||
@ -314,6 +318,8 @@ main(int argc, char **argv)
|
|||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
|
|
||||||
|
char *remote_host_str = NULL, *remote_port_str = NULL;
|
||||||
|
|
||||||
char *nameserv_host = NULL;
|
char *nameserv_host = NULL;
|
||||||
struct sockaddr_storage nameservaddr;
|
struct sockaddr_storage nameservaddr;
|
||||||
int nameservaddr_len = 0;
|
int nameservaddr_len = 0;
|
||||||
@ -331,6 +337,9 @@ main(int argc, char **argv)
|
|||||||
__progname++;
|
__progname++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define OPT_RDOMAIN 0x80
|
||||||
|
#define OPT_NODROP 0x81
|
||||||
|
|
||||||
/* each option has format:
|
/* each option has format:
|
||||||
* char *name, int has_arg, int *flag, int val */
|
* char *name, int has_arg, int *flag, int val */
|
||||||
static struct option iodine_args[] = {
|
static struct option iodine_args[] = {
|
||||||
@ -338,10 +347,12 @@ main(int argc, char **argv)
|
|||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"stats", optional_argument, 0, 'V'},
|
{"stats", optional_argument, 0, 'V'},
|
||||||
{"context", required_argument, 0, 'z'},
|
{"context", required_argument, 0, 'z'},
|
||||||
{"rdomain", required_argument, 0, 'R'},
|
{"rdomain", required_argument, 0, OPT_RDOMAIN},
|
||||||
{"chrootdir", required_argument, 0, 't'},
|
{"chrootdir", required_argument, 0, 't'},
|
||||||
{"proxycommand", no_argument, 0, 'X'},
|
|
||||||
{"preset", required_argument, 0, 'Y'},
|
{"preset", required_argument, 0, 'Y'},
|
||||||
|
{"proxycommand", no_argument, 0, 'R'},
|
||||||
|
// {"nodrop", no_argument, 0, OPT_NODROP},
|
||||||
|
{"remote", required_argument, 0, 'R'},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -349,9 +360,10 @@ main(int argc, char **argv)
|
|||||||
* This is so that all options override preset values regardless of order in command line */
|
* This is so that all options override preset values regardless of order in command line */
|
||||||
int optind_orig = optind, preset_id = -1;
|
int optind_orig = optind, preset_id = -1;
|
||||||
|
|
||||||
static char *iodine_args_short = "46vfDhrX:Y:s:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:";
|
static char *iodine_args_short = "46vfDhrY:s:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:";
|
||||||
|
|
||||||
while ((choice = getopt_long(argc, argv, iodine_args_short, iodine_args, NULL))) {
|
while ((choice = getopt_long(argc, argv, iodine_args_short, iodine_args, NULL))) {
|
||||||
|
/* Check if preset has been found yet so we don't process any other options */
|
||||||
if (preset_id < 0) {
|
if (preset_id < 0) {
|
||||||
if (choice == -1) {
|
if (choice == -1) {
|
||||||
/* reached end of command line and no preset specified - use default */
|
/* reached end of command line and no preset specified - use default */
|
||||||
@ -391,6 +403,9 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Once a preset is used, it is copied into memory. This way other
|
||||||
|
* options can override preset values regardless of order in command line */
|
||||||
|
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case '4':
|
case '4':
|
||||||
nameserv_family = AF_INET;
|
nameserv_family = AF_INET;
|
||||||
@ -430,10 +445,51 @@ main(int argc, char **argv)
|
|||||||
device = optarg;
|
device = optarg;
|
||||||
break;
|
break;
|
||||||
#ifdef OPENBSD
|
#ifdef OPENBSD
|
||||||
case 'R':
|
case OPT_RDOMAIN:
|
||||||
rtable = atoi(optarg);
|
rtable = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case 'R':
|
||||||
|
/* Argument format: [host:]port */
|
||||||
|
if (!optarg) break;
|
||||||
|
|
||||||
|
if (strrchr(optarg, ':')) {
|
||||||
|
remote_port_str = strrchr(optarg, ':') + 1;
|
||||||
|
if (optarg[0] == '[') {
|
||||||
|
/* IPv6 address enclosed in square brackets */
|
||||||
|
remote_host_str = optarg + 1;
|
||||||
|
/* replace closing bracket with null terminator */
|
||||||
|
*strchr(remote_host_str, ']') = 0;
|
||||||
|
this.remote_forward_addr.ss_family = AF_INET6;
|
||||||
|
retval = inet_pton(AF_INET6, remote_host_str,
|
||||||
|
&((struct sockaddr_in6 *) &this.remote_forward_addr)->sin6_addr);
|
||||||
|
} else {
|
||||||
|
remote_host_str = optarg;
|
||||||
|
/* replace separator with null terminator */
|
||||||
|
*strchr(remote_host_str, ':') = 0;
|
||||||
|
this.remote_forward_addr.ss_family = AF_INET;
|
||||||
|
retval = inet_aton(remote_host_str,
|
||||||
|
&((struct sockaddr_in *) &this.remote_forward_addr)->sin_addr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no address specified, optarg is port */
|
||||||
|
remote_port_str = optarg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse port */
|
||||||
|
this.remote_forward_port = atoi(remote_port_str);
|
||||||
|
if (this.remote_forward_port < 0 || this.remote_forward_port > 65535)
|
||||||
|
this.remote_forward_port = -1;
|
||||||
|
|
||||||
|
if (retval <= 0) {
|
||||||
|
errx(12, "Invalid remote TCP forwarding specification! Check help for info.");
|
||||||
|
usage();
|
||||||
|
/* not reached */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPT_NODROP:
|
||||||
|
// TODO implement TCP-over-tun optimisations
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
strncpy(this.password, optarg, sizeof(this.password));
|
strncpy(this.password, optarg, sizeof(this.password));
|
||||||
this.password[sizeof(this.password)-1] = 0;
|
this.password[sizeof(this.password)-1] = 0;
|
||||||
@ -509,8 +565,6 @@ main(int argc, char **argv)
|
|||||||
case 'Y':
|
case 'Y':
|
||||||
/* Already processed preset: ignore */
|
/* Already processed preset: ignore */
|
||||||
continue;
|
continue;
|
||||||
case 'X':
|
|
||||||
// TODO implement option for remote host/port to pipe stdin/out
|
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
@ -533,6 +587,12 @@ main(int argc, char **argv)
|
|||||||
this.foreground = 1;
|
this.foreground = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.remote_forward_port == -1) {
|
||||||
|
fprintf(stderr, "Remote TCP port must be between 1 and 65535.");
|
||||||
|
usage();
|
||||||
|
/* not reached */
|
||||||
|
}
|
||||||
|
|
||||||
this.nameserv_hosts_len = argc - 1;
|
this.nameserv_hosts_len = argc - 1;
|
||||||
if (this.nameserv_hosts_len <= 0)
|
if (this.nameserv_hosts_len <= 0)
|
||||||
/* if no hosts specified, use resolv.conf */
|
/* if no hosts specified, use resolv.conf */
|
||||||
@ -652,6 +712,10 @@ main(int argc, char **argv)
|
|||||||
(a != this.nameserv_addrs_len - 1) ? ", " : "");
|
(a != this.nameserv_addrs_len - 1) ? ", " : "");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
if (this.remote_forward_port)
|
||||||
|
fprintf(stderr, "Requesting TCP data forwarding from server to %s:%d\n",
|
||||||
|
format_addr(&this.remote_forward_addr, sizeof(struct sockaddr_storage)), this.remote_forward_port);
|
||||||
|
|
||||||
if (client_handshake()) {
|
if (client_handshake()) {
|
||||||
retval = 1;
|
retval = 1;
|
||||||
goto cleanup2;
|
goto cleanup2;
|
||||||
|
@ -170,8 +170,8 @@ static void
|
|||||||
print_usage() {
|
print_usage() {
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
fprintf(stderr, "Usage: %s [-v] [-h] [-4] [-6] [-c] [-s] [-f] [-D] "
|
fprintf(stderr, "Usage: %s [options] [-v] [-h] [-4] [-6] [-c] [-s] [-f] [-D] "
|
||||||
"[-u user] [-t chrootdir] [-d device] [-m mtu] [-z context] "
|
"[-u user] [-d device] [-m mtu] "
|
||||||
"[-l ipv4 listen address] [-L ipv6 listen address] [-p port] "
|
"[-l ipv4 listen address] [-L ipv6 listen address] [-p port] "
|
||||||
"[-n external ip] [-b dnsport] [-P password] [-F pidfile] "
|
"[-n external ip] [-b dnsport] [-P password] [-F pidfile] "
|
||||||
"[-i max idle time] tunnel_ip[/netmask] topdomain\n", __progname);
|
"[-i max idle time] tunnel_ip[/netmask] topdomain\n", __progname);
|
||||||
@ -198,10 +198,10 @@ help() {
|
|||||||
fprintf(stderr, " -D increase debug level\n");
|
fprintf(stderr, " -D increase debug level\n");
|
||||||
fprintf(stderr, " (using -DD in UTF-8 terminal: \"LC_ALL=C luit iodined -DD ...\")\n");
|
fprintf(stderr, " (using -DD in UTF-8 terminal: \"LC_ALL=C luit iodined -DD ...\")\n");
|
||||||
fprintf(stderr, " -u, --user drop privileges and run as user\n");
|
fprintf(stderr, " -u, --user drop privileges and run as user\n");
|
||||||
fprintf(stderr, " -t, --chrootdir chroot to directory after init\n");
|
fprintf(stderr, " --chrootdir chroot to directory after init\n");
|
||||||
fprintf(stderr, " -d specify tunnel device name\n");
|
fprintf(stderr, " -d specify tunnel device name\n");
|
||||||
fprintf(stderr, " -m, --mtu specify tunnel device mtu\n");
|
fprintf(stderr, " -m, --mtu specify tunnel device mtu\n");
|
||||||
fprintf(stderr, " -z, --context apply SELinux context after initialization\n");
|
fprintf(stderr, " --context apply SELinux context after initialization\n");
|
||||||
fprintf(stderr, " -l, --listen4 IPv4 address to listen on for incoming dns traffic "
|
fprintf(stderr, " -l, --listen4 IPv4 address to listen on for incoming dns traffic "
|
||||||
"(default 0.0.0.0)\n");
|
"(default 0.0.0.0)\n");
|
||||||
fprintf(stderr, " -L, --listen6 IPv6 address to listen on for incoming dns traffic "
|
fprintf(stderr, " -L, --listen6 IPv6 address to listen on for incoming dns traffic "
|
||||||
@ -209,6 +209,8 @@ help() {
|
|||||||
fprintf(stderr, " -p port to listen on for incoming dns traffic (default 53)\n");
|
fprintf(stderr, " -p port to listen on for incoming dns traffic (default 53)\n");
|
||||||
fprintf(stderr, " -n, --nsip ip to respond with to NS queries\n");
|
fprintf(stderr, " -n, --nsip ip to respond with to NS queries\n");
|
||||||
fprintf(stderr, " -b, --forwardto forward normal DNS queries to a UDP port on localhost\n");
|
fprintf(stderr, " -b, --forwardto forward normal DNS queries to a UDP port on localhost\n");
|
||||||
|
fprintf(stderr, " -A, --localforward allow TCP data pipe to local ports only (default: disabled)\n");
|
||||||
|
fprintf(stderr, " -R, --remoteforward allow TCP data pipe to remote hosts (default: disabled)\n");
|
||||||
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n");
|
||||||
fprintf(stderr, " -F, --pidfile write pid to a file\n");
|
fprintf(stderr, " -F, --pidfile write pid to a file\n");
|
||||||
fprintf(stderr, " -i, --idlequit maximum idle time before shutting down\n");
|
fprintf(stderr, " -i, --idlequit maximum idle time before shutting down\n");
|
||||||
@ -315,6 +317,8 @@ main(int argc, char **argv)
|
|||||||
{"mtu", required_argument, 0, 'm'},
|
{"mtu", required_argument, 0, 'm'},
|
||||||
{"idlequit", required_argument, 0, 'i'},
|
{"idlequit", required_argument, 0, 'i'},
|
||||||
{"forwardto", required_argument, 0, 'b'},
|
{"forwardto", required_argument, 0, 'b'},
|
||||||
|
{"localforward", no_argument, 0, 'A'},
|
||||||
|
{"remoteforward", no_argument, 0, 'R'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"context", required_argument, 0, 'z'},
|
{"context", required_argument, 0, 'z'},
|
||||||
{"chrootdir", required_argument, 0, 't'},
|
{"chrootdir", required_argument, 0, 't'},
|
||||||
@ -322,7 +326,7 @@ main(int argc, char **argv)
|
|||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *iodined_args_short = "46vcsfhDu:t:d:m:l:L:p:n:b:P:z:F:i:";
|
static char *iodined_args_short = "46vcsfhDARu:t:d:m:l:L:p:n:b:P:z:F:i:";
|
||||||
|
|
||||||
server.running = 1;
|
server.running = 1;
|
||||||
|
|
||||||
@ -384,6 +388,13 @@ main(int argc, char **argv)
|
|||||||
server.bind_enable = 1;
|
server.bind_enable = 1;
|
||||||
server.bind_port = atoi(optarg);
|
server.bind_port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'A':
|
||||||
|
server.allow_forward_local_port = 1;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
server.allow_forward_local_port = 1;
|
||||||
|
server.allow_forward_remote = 1;
|
||||||
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
pidfile = optarg;
|
pidfile = optarg;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user