From 27fb4c75cd6f7c20b5052b3bfdf40a3ae0ff4d34 Mon Sep 17 00:00:00 2001 From: Michael Scherer Date: Mon, 23 Dec 2013 10:48:46 +0100 Subject: [PATCH 1/3] Add support to have on demand socket activation of iodine --- src/iodined.c | 24 ++++++++++++++++++++++-- src/osflags | 10 ++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/iodined.c b/src/iodined.c index b3b0607..6dfa34d 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -59,6 +59,10 @@ #include "fw_query.h" #include "version.h" +#ifdef HAVE_SYSTEMD +# include +#endif + #ifdef WINDOWS32 WORD req_version = MAKEWORD(2, 2); WSADATA wsa_data; @@ -2246,6 +2250,9 @@ main(int argc, char **argv) char *netsize; int ns_get_externalip; int retval; +#ifdef HAVE_SYSTEMD + int nb_fds; +#endif #ifndef WINDOWS32 pw = NULL; @@ -2487,10 +2494,23 @@ main(int argc, char **argv) } free((void*) other_ip); } - if ((dnsd_fd = open_dns(port, listen_ip)) == -1) { +#ifdef HAVE_SYSTEMD + nb_fds = sd_listen_fds(0); + if (nb_fds > 1) { retval = 1; - goto cleanup2; + warnx("Too many file descriptors received!\n"); + goto cleanup1; + } else if (nb_fds == 1) { + dnsd_fd = SD_LISTEN_FDS_START; + } else { +#endif + if ((dnsd_fd = open_dns(port, listen_ip)) == -1) { + retval = 1; + goto cleanup2; + } +#ifdef HAVE_SYSTEMD } +#endif if (bind_enable) { if ((bind_fd = open_dns(0, INADDR_ANY)) == -1) { retval = 1; diff --git a/src/osflags b/src/osflags index 6f0cf51..2d8a03b 100755 --- a/src/osflags +++ b/src/osflags @@ -17,7 +17,10 @@ link) echo '-lws2_32 -liphlpapi'; ;; Linux) - [ -e /usr/include/selinux/selinux.h ] && echo '-lselinux'; + FLAGS=""; + [ -e /usr/include/selinux/selinux.h ] && FLAGS="$FLAGS -lselinux"; + [ -e /usr/include/systemd/sd-daemon.h ] && FLAGS="$FLAGS -lsystemd-daemon"; + echo $FLAGS; ;; esac ;; @@ -30,7 +33,10 @@ cflags) echo '-Dsocklen_t=int'; ;; Linux) - [ -e /usr/include/selinux/selinux.h ] && echo '-DHAVE_SETCON'; + FLAGS=""; + [ -e /usr/include/selinux/selinux.h ] && FLAGS="$FLAGS -DHAVE_SETCON"; + [ -e /usr/include/systemd/sd-daemon.h ] && FLAGS="$FLAGS -DHAVE_SYSTEMD"; + echo $FLAGS; ;; esac ;; From 717f1d5d26198c7e0795ce011e26758a4a85744d Mon Sep 17 00:00:00 2001 From: Michael Scherer Date: Mon, 23 Dec 2013 22:50:58 +0100 Subject: [PATCH 2/3] Add examples of iodine-server systemd unit --- doc/iodine-server.service | 11 +++++++++++ doc/iodine-server.socket | 8 ++++++++ 2 files changed, 19 insertions(+) create mode 100644 doc/iodine-server.service create mode 100644 doc/iodine-server.socket diff --git a/doc/iodine-server.service b/doc/iodine-server.service new file mode 100644 index 0000000..64d2ecc --- /dev/null +++ b/doc/iodine-server.service @@ -0,0 +1,11 @@ +[Unit] +Description=Iodine Server +After=local-fs.target network.target + +[Service] +EnvironmentFile=-/etc/sysconfig/iodine-server +ExecStart=/usr/local/bin/iodined -i 30 -f $OPTIONS +StandardOutput=syslog + +[Install] +WantedBy=multi-user.target diff --git a/doc/iodine-server.socket b/doc/iodine-server.socket new file mode 100644 index 0000000..d6c57b8 --- /dev/null +++ b/doc/iodine-server.socket @@ -0,0 +1,8 @@ +[Unit] +Description=Iodine socket + +[Socket] +ListenDatagram=53 + +[Install] +WantedBy=sockets.target From abd276ed9e7ca868616954b41f67a0b99a67a4c3 Mon Sep 17 00:00:00 2001 From: Michael Scherer Date: Mon, 23 Dec 2013 21:58:28 +0100 Subject: [PATCH 3/3] Add idle option, so we can stop iodine and start it on demand with systemd --- man/iodine.8 | 6 ++++++ src/iodined.c | 30 ++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/man/iodine.8 b/man/iodine.8 index f551399..349ba6f 100644 --- a/man/iodine.8 +++ b/man/iodine.8 @@ -71,6 +71,8 @@ iodine, iodined \- tunnel IPv4 over DNS .I context .B ] [-F .I pidfile +.B ] [-i +.I max_idle_time .B ] .I tunnel_ip .B [ @@ -278,6 +280,10 @@ same as 'port'. .B Note: The forwarding is not fully transparent, and not advised for use in production environments. +.TP +.B -i max_idle_time +Make the server stop itself after max_idle_time seconds if no traffic have been received. +This should be combined with systemd or upstart on demand activation for being effective. .SS Client Arguments: .TP .B nameserver diff --git a/src/iodined.c b/src/iodined.c index 6dfa34d..8dc37e1 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -1688,12 +1688,13 @@ tunnel_dns(int tun_fd, int dns_fd, int bind_fd) } static int -tunnel(int tun_fd, int dns_fd, int bind_fd) +tunnel(int tun_fd, int dns_fd, int bind_fd, int max_idle_time) { struct timeval tv; fd_set fds; int i; int userid; + time_t last_action = time(NULL); while (running) { int maxfd; @@ -1744,8 +1745,20 @@ tunnel(int tun_fd, int dns_fd, int bind_fd) return 1; } - if (i==0) { - /* timeout; whatever; doesn't matter anymore */ + if (i==0) { + if (max_idle_time) { + /* only trigger the check if that's worth ( ie, no need to loop over if there + is something to send */ + if (last_action + max_idle_time < time(NULL)) { + for (userid = 0; userid < created_users; userid++) { + last_action = ( users[userid].last_pkt > last_action ) ? users[userid].last_pkt : last_action; + } + if (last_action + max_idle_time < time(NULL)) { + fprintf(stderr, "Idling since too long, shutting down...\n"); + running = 0; + } + } + } } else { if (FD_ISSET(tun_fd, &fds)) { tunnel_tun(tun_fd, dns_fd); @@ -2172,7 +2185,7 @@ usage() { fprintf(stderr, "Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] " "[-t chrootdir] [-d device] [-m mtu] [-z context] " "[-l ip address to listen on] [-p port] [-n external ip] " - "[-b dnsport] [-P password] [-F pidfile] " + "[-b dnsport] [-P password] [-F pidfile] [-i max idle time] " "tunnel_ip[/netmask] topdomain\n", __progname); exit(2); } @@ -2206,6 +2219,7 @@ help() { fprintf(stderr, " -b port to forward normal DNS queries to (on localhost)\n"); fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n"); fprintf(stderr, " -F pidfile to write pid to a file\n"); + fprintf(stderr, " -i maximum idle time before shutting down\n"); fprintf(stderr, "tunnel_ip is the IP number of the local tunnel interface.\n"); fprintf(stderr, " /netmask sets the size of the tunnel network.\n"); fprintf(stderr, "topdomain is the FQDN that is delegated to this server.\n"); @@ -2250,6 +2264,7 @@ main(int argc, char **argv) char *netsize; int ns_get_externalip; int retval; + int max_idle_time = 0; #ifdef HAVE_SYSTEMD int nb_fds; #endif @@ -2299,7 +2314,7 @@ main(int argc, char **argv) srand(time(NULL)); fw_query_init(); - while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:")) != -1) { + while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:n:b:P:z:F:i:")) != -1) { switch(choice) { case 'v': version(); @@ -2351,6 +2366,9 @@ main(int argc, char **argv) case 'F': pidfile = optarg; break; + case 'i': + max_idle_time = atoi(optarg); + break; case 'P': strncpy(password, optarg, sizeof(password)); password[sizeof(password)-1] = 0; @@ -2559,7 +2577,7 @@ main(int argc, char **argv) syslog(LOG_INFO, "started, listening on port %d", port); - tunnel(tun_fd, dnsd_fd, bind_fd); + tunnel(tun_fd, dnsd_fd, bind_fd, max_idle_time); syslog(LOG_INFO, "stopping"); cleanup3: