Skip to content

Commit

Permalink
SIGHUP support
Browse files Browse the repository at this point in the history
  • Loading branch information
root4root committed Nov 10, 2018
1 parent 661724e commit 8977bbd
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 102 deletions.
41 changes: 21 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
# tuninetd

Is a simple Linux daemon for tun/tap devices, similar to inetd by its logic, but for mentioned interfaceces, instead of a ports.
Simple yet powerful tun/tap event emitter. Could be used like VPN dispatcher...

### How it works:
First, you create and configure tun/tap device, then run **tuninetd**. It start listening on that interface, until network packet will be received.
Next, interface will be released and certain command is executed. From now on, daemon in monitoring state.
After N seconds of interface idle, tuninetd send "stop" command by path, that you define, and start listening interface by its own again.

Since, **tuninetd** based on **libpcap**, you can specify filter to trigging "start" event and monitoring iddle (i.e. cutoff unwanted traffic).
To test/debug filters rules - use tcpdump, because it built upon the same library.
You should create and configure tun/tap device, then run **tuninetd**. It starts listening on that interface until network traffic will be detected. After that, interface will be released and certain command executed. From now on daemon is in monitoring state.
After N seconds of interface idle, tuninetd send "stop" command by path that you define and start listening interface by its own again.

Since **tuninetd** based on **libpcap**, you can specify filter to trigging "start" and monitoring iddle (i.e. cutoff unwanted traffic). To test/debug pcap rules you might use tcpdump which is based on the same library.

**! OR !**

You can simply use netfilter nfgroup (*iptables NFLOG target*), for reading packets from. No binding to interface and no libpcap usage. This is more lightweight mode and because of that - more reliable. Option available since v1.1.0.
You can simply use netfilter nfgroup (*iptables NFLOG target*), for reading packets from. No need binding to tun/tap interface nor heavy libpcap sensor. This is more lightweight mode and because of that - more reliable. Option available since v1.1.0.


**tuninetd** allows you deploy "VPN by demand" or any other "by demand" services, which is the main idea of the project.
**tuninetd** allows deploy "VPN by demand" or any other "by demand" services, which is the main idea of the project.

### Installation:
If you're using Debian/Ubuntu, check deb-packages folder. Choose appropriate architecture, then run following command with root privileges:
If you're using Debian/Ubuntu please check deb-packages folder. Choose appropriate architecture, then run following command with root privileges:
```sh
# dpkg -i tuninetd_ver_arch.deb
# apt-get -f install
```
To install it from sources, download src folder. In case Debian/Ubuntu, you should also install **build-essential**, **libpcap-dev** and **libnetfilter-log-dev** packages first. To build tuninetd, run:<br/>
To install from sources download src folder. In case Debian/Ubuntu, you should also install **build-essential**, **libpcap-dev** and **libnetfilter-log-dev** packages first. To build tuninetd just run:<br/>
```sh
# cd /download/folder/src
# make
```
After that, bin folder should appears, which contains tuninetd.

Congrats! Tuninend is ready to use. Check ./bin folder. :)

### Usage:

Expand All @@ -41,30 +40,32 @@ tuninetd {-i \<ifname> | -n \<nflog-group>} -c \<path> [-m \<iftype>] [-f \<filt
**-f \<filter>**: specify pcap filter, similar to tcpdump<br/>
**-t \<ttl>**: seconds of interface (traffic) idle, before 'stop' command (default is 600).<br/>
**-d**: demonize process<br/>
**-h**: prints this help text
**-h**: prints this help

`--- If tuninetd stuck in start condition for any reason, you can reset to "standby" (i.e. stop state) with SIGHUP. ---`

### Examples:
Before launching as daemon, make sure there is no errors occurs. In daemon mode, tuninetd write status messages and errors to syslog.
Before launching as daemon make sure there is no errors occurs. In daemon mode tuninetd write status messages and errors to syslog.

```sh
# tuninetd -i tun0 -c /test/runtunnel.sh -f "! host 1.2.3.4" -t 3600 -d
# tuninetd -n 2 -c /test/runtunnel.sh -t 3600 -d
```

You can find example script 'runtunnel.sh', within examples folder.
Check ```example``` folder to find some shell scripts.

To create and up tun device, could be used next commands:
To create and bring up ```tun``` device, could be used following commands:
```sh
# ip tuntap add name tun0 mode tun
# ip link tun0 up
# ip link set tun0 up
```

For more information about routing and configuring net devices, please check official documentation.
For more information about routing and configuring net devices, I strongly suggest LARCT how-to.

*! Notice, that the modern Linux distributions periodically send 'icmpv6 router solicitation' packets, which cause tuninetd state changing (call of 'start' script). This situation affects to tun/tap mode without filter (-f) applied.*
*! Notice ! Modern Linux distributions periodically send 'icmpv6 router solicitation' packets, which cause tuninetd keep or change its status (calling 'start' script for example). This situation appears in tun/tap mode without pcap filter applied.*

### License:
MIT
### Author:
Paul aka root4root \<root4root at gmail dot com><br/>
**Any suggestions will be appreciated.**
**Any comment/suggestions are welcomed.**
Binary file added deb-packages/tuninetd_1.2.0_amd64.deb
Binary file not shown.
5 changes: 4 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
first: main.c
all: default
default: main.c
[ -d ./bin ] || mkdir -p ./bin
gcc -o ./bin/tuninetd main.c -lpthread -lpcap -lnetfilter_log
clean:
rm -rf ./bin
84 changes: 23 additions & 61 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,50 +1,13 @@
#include <fcntl.h>
#include <pthread.h>
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <syslog.h>
#include <unistd.h>

//#include <sys/types.h>
#include <libnetfilter_log/libnetfilter_log.h>
//#include <sys/socket.h>

#define BUFSIZE 2000

short int debug = 0;
short int status = 0;
unsigned long ts = 0;
unsigned long curts = 0;

char progname[] = "tuninetd";

struct globcfg_t {
short int isdaemon;
pid_t pid;
char *cmd_path;
char *cmd_path_start;
char *cmd_path_stop;
char *pcap_filter;
char *dev_name;
long nf_group;
int dev_mode;
int ttl;
} globcfg;

#include "utils.c"
#include "tun.c"
#include "pcap.c"
#include "nflog.c"
#include "main.h"

int main(int argc, char *argv[])
{
int x, y, opt=0;
int opt = 0;

struct timespec tim;

tim.tv_sec = 1;
tim.tv_nsec = 0;

static const char *optString = "i:t:c:f:m:n:dh";

Expand Down Expand Up @@ -117,6 +80,12 @@ int main(int argc, char *argv[])
exit(1);
}

if (pthread_mutex_init(&lock, NULL) != 0)
{
my_err("Mutex init failed. Abort.");
exit(1);
}

if (globcfg.isdaemon == 1) {
globcfg.pid = fork();

Expand All @@ -138,14 +107,10 @@ int main(int argc, char *argv[])
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
} else
my_info("Started with pid %d", getpid());

pthread_t pcap_x_thread;
pthread_t tun_x_thread;
pthread_t nflog_x_thread;

pthread_attr_t attr;

pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

Expand All @@ -158,22 +123,19 @@ int main(int argc, char *argv[])
pthread_create(&nflog_x_thread, &attr, nflog_x, &y);
}

if (signal(SIGHUP, sig_handler) == SIG_ERR)
my_info("Can't catch SIGHUP\n");


while (1) {
usleep(1000000);

nanosleep(&tim, NULL);

curts = time(NULL);

if (ts != 0 && status == 1 && ((curts - ts) >= globcfg.ttl) ) {
my_info("CORE: executing STOP command...");

if (system(globcfg.cmd_path_stop) != 0) {
my_err("Warning! Executable command doesn't return 0 (%s)", globcfg.cmd_path_stop);
}

status = 0;

if (globcfg.nf_group < 0) {
pthread_create(&tun_x_thread, &attr, tun_x, &y);
}
switch_guard(OFF);
}
}

Expand Down
65 changes: 65 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <fcntl.h>
#include <pthread.h>
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <syslog.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>

#include <libnetfilter_log/libnetfilter_log.h>


#define BUFSIZE 2000
#define ON 1
#define OFF 0

int x, y;

short int debug = 0;
short int status = 0;
unsigned long ts = 0;
unsigned long curts = 0;

char progname[] = "tuninetd";

struct globcfg_t {
short int isdaemon;
pid_t pid;
char *cmd_path;
char *cmd_path_start;
char *cmd_path_stop;
char *pcap_filter;
char *dev_name;
long nf_group;
int dev_mode;
int ttl;
} globcfg;

pthread_t pcap_x_thread;
pthread_t tun_x_thread;
pthread_t nflog_x_thread;

pthread_attr_t attr;
pthread_mutex_t lock;

void do_debug(char *msg, ...);
void my_err(char *msg, ...);
void my_info(char *msg, ...);
void switch_state(short action);
void switch_guard(short action);

void *tun_x(void *x_void_ptr);
void *nflog_x(void *x_void_ptr);
void *pcap_x(void *x_void_ptr);

#include "utils.c"
#include "tun.c"
#include "pcap.c"
#include "nflog.c"
13 changes: 3 additions & 10 deletions src/nflog.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
static int callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *ldata, void *data)
{
if (status == 0) {

if (status == OFF) {
my_info("NFLOG module: executing START command...");

if (system(globcfg.cmd_path_start) != 0) {
my_err("Warning! Executable command doesn't return 0 (%s)", globcfg.cmd_path_start);
}

status = 1;
switch_guard(ON);
}

ts = curts;

}

void *nflog_x(void *x_void_ptr)
Expand Down Expand Up @@ -41,7 +34,7 @@ void *nflog_x(void *x_void_ptr)
}
qh = nflog_bind_group(h, globcfg.nf_group);
if (!qh) {
my_err("no handle for group 0");
my_err("no handle for group %i", globcfg.nf_group);
exit(1);
}

Expand Down
19 changes: 9 additions & 10 deletions src/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ void *tun_x(void *x_void_ptr)
int nread;
char buffer[BUFSIZE];

struct timespec tim;

tim.tv_sec = 0;
tim.tv_nsec = 15000000;


if ( (tap_fd = tun_alloc(globcfg.dev_name, globcfg.dev_mode | IFF_NO_PI)) < 0 ) {
my_err("Fatal error. Connecting to tun/tap interface %s failed.", globcfg.dev_name);
Expand All @@ -53,27 +58,21 @@ void *tun_x(void *x_void_ptr)
nread = cread(tap_fd, buffer, BUFSIZE);

if (globcfg.pcap_filter != NULL) {
usleep(15000); //Wait for libpcap timeout.
nanosleep(&tim, NULL);
if ( (curts - ts) < 2 ) {
do_debug("Read %d bytes from the tap interface\n", nread);
break;
}
} else {
break;
break;
}
}

ts = time(NULL);

status = 1;

close(tap_fd);

my_info("TUN/TAP module: executing START command...");

if (system(globcfg.cmd_path_start) != 0) {
my_err("Warning! Executable command doesn't return 0 (%s)", globcfg.cmd_path_start);
}

switch_guard(ON);

return 0;
}
Loading

0 comments on commit 8977bbd

Please sign in to comment.