From ba92f4c28564e2e898b365c6aabdaf76a14007d0 Mon Sep 17 00:00:00 2001 From: Sasan Jalali Date: Thu, 13 Sep 2018 04:02:49 +0430 Subject: [PATCH 1/3] added -i option --- Makefile.am | 7 ++++++- configure.ac | 12 ++++++++++- doc/knock.1.in | 5 +++++ src/interface.h | 7 +++++++ src/interface_getifaddrs.c | 34 +++++++++++++++++++++++++++++++ src/interface_ioctl.c | 41 ++++++++++++++++++++++++++++++++++++++ src/knock.c | 27 ++++++++++++++++++++++++- 7 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 src/interface.h create mode 100644 src/interface_getifaddrs.c create mode 100644 src/interface_ioctl.c diff --git a/Makefile.am b/Makefile.am index c5b15ab..cbf297e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,7 +13,12 @@ endif dist_doc_DATA = README.md TODO ChangeLog COPYING -knock_SOURCES = src/knock.c +knock_SOURCES = src/knock.c src/interface.h +if USE_GETIFADDRS +knock_SOURCES += src/interface_getifaddrs.c +else +knock_SOURCES += src/interface_ioctl.c +endif knockd_SOURCES = src/knockd.c src/list.c src/list.h src/knock_helper_ipt.sh %.1: %.1.in diff --git a/configure.ac b/configure.ac index 02e3012..bfa6eea 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT([knock], [0.7.8], [https://github.com/jvinet/knock/issues]) +AC_INIT([knock], [0.7.9], [https://github.com/jvinet/knock/issues]) AM_INIT_AUTOMAKE([dist-xz no-dist-gzip foreign subdir-objects]) AC_CONFIG_HEADER([config.h]) @@ -10,12 +10,22 @@ AC_USE_SYSTEM_EXTENSIONS AC_ARG_ENABLE([knockd], [AS_HELP_STRING([--disable-knockd], [Disable building knockd (requires libpcap) @<:@default=enabled@:>@])]) +AC_ARG_ENABLE([getifaddrs], + [AS_HELP_STRING([--disable-getifaddrs], [Disable using getifaddrs from glib @<:@default=enabled@:>@])]) + AS_IF([test "x$enable_knockd" != "xno"], [ AC_CHECK_LIB([pcap], [pcap_dispatch], , [AC_MSG_ERROR([you need the libpcap library to build knockd])]) ]) +AS_IF([test "x$enable_getifaddrs" != "xno"], [ + AC_CHECK_FUNC([getifaddrs], + [AC_DEFINE([HAVE_GETIFADDRS],[],[Use getifaddrs function])], + [AC_MSG_ERROR([can not find getifaddrs function.])]) +]) + AM_CONDITIONAL([BUILD_KNOCKD], [test "x$enable_knockd" != "xno"]) +AM_CONDITIONAL([USE_GETIFADDRS], [test "x$enable_getifaddrs" != "xno"]) AC_CONFIG_FILES([Makefile]) diff --git a/doc/knock.1.in b/doc/knock.1.in index 3205faa..1f4347d 100644 --- a/doc/knock.1.in +++ b/doc/knock.1.in @@ -21,6 +21,11 @@ where a router mistakes your stream of SYN packets as a port scan and blocks them. If the packet rate is slowed with \-\-delay, then the router should let the packets through. .TP +.B "\-i , \-\-delay " +Use network interface for knocks, like eth0. This option can be useful +when a system has more than one network interface with different gateways +(multihomed). +.TP .B "\-v, \-\-verbose" Output verbose status messages. .TP diff --git a/src/interface.h b/src/interface.h new file mode 100644 index 0000000..67840f9 --- /dev/null +++ b/src/interface.h @@ -0,0 +1,7 @@ +#include +#include + +#ifndef MY_INTERFACE +#define MY_INTERFACE +bool get_interface_addr4(const char *if_name,struct in_addr *if_addr); +#endif // MY_INTERFACE diff --git a/src/interface_getifaddrs.c b/src/interface_getifaddrs.c new file mode 100644 index 0000000..79f74dd --- /dev/null +++ b/src/interface_getifaddrs.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include "interface.h" + +bool get_interface_addr4(const char *if_name,struct in_addr *if_addr) { + struct ifaddrs *addrs=NULL,*tmp=NULL; + bool found=false; + getifaddrs(&addrs); + tmp=addrs; + while(tmp) { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) { +#ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wcast-align" +#endif + struct sockaddr_in *addr_in = (struct sockaddr_in *)tmp->ifa_addr; +#ifdef __clang__ + #pragma clang diagnostic pop +#endif + if (strcmp(if_name,tmp->ifa_name) == 0 ) { + if_addr->s_addr = addr_in->sin_addr.s_addr; + found=true; + break; + } + } + tmp = tmp->ifa_next; + } + freeifaddrs(addrs); + return found; +} diff --git a/src/interface_ioctl.c b/src/interface_ioctl.c new file mode 100644 index 0000000..7a4d3af --- /dev/null +++ b/src/interface_ioctl.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "interface.h" +#include + +bool get_interface_addr4(const char *if_name,struct in_addr *if_addr) { + struct ifreq ifr; + int s; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if(s < 0) { + printf("%s is %d\n",strerror(errno),s); + return(false); + } + + memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)-1); + printf("%s\n",ifr.ifr_name); + ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; + if(ioctl(s, SIOCGIFADDR, &ifr)==-1) { + close(s); + return(false); + } + close(s); +#ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wcast-align" +#endif + struct sockaddr_in *addr_in = (struct sockaddr_in *)&ifr.ifr_addr; +#ifdef __clang__ + #pragma clang diagnostic pop +#endif + if_addr->s_addr = addr_in->sin_addr.s_addr; + return(true); +} diff --git a/src/knock.c b/src/knock.c index 319e51d..8bc0b08 100644 --- a/src/knock.c +++ b/src/knock.c @@ -34,6 +34,7 @@ #include #include #include +#include "interface.h" static char version[] = "0.7"; @@ -54,6 +55,8 @@ int main(int argc, char** argv) int sd; struct hostent* host; struct sockaddr_in addr; + struct sockaddr_in bind_addr; + bool do_bind=false; int opt, optidx = 1; static struct option opts[] = { @@ -62,10 +65,11 @@ int main(int argc, char** argv) {"delay", required_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, + {"interface", required_argument, 0, 'i'}, {0, 0, 0, 0} }; - while((opt = getopt_long(argc, argv, "vud:hV", opts, &optidx))) { + while((opt = getopt_long(argc, argv, "vud:hVi:", opts, &optidx))) { if(opt < 0) { break; } @@ -74,6 +78,17 @@ int main(int argc, char** argv) case 'v': o_verbose = 1; break; case 'u': o_udp = 1; break; case 'd': o_delay = (int)atoi(optarg); break; + case 'i': + memset(&bind_addr,0,sizeof(struct sockaddr_in)); + if ( get_interface_addr4(optarg,&bind_addr.sin_addr) ) { + do_bind=true; + bind_addr.sin_family=AF_INET; + bind_addr.sin_port=0; + } else { + fprintf(stderr,"error: interface %s not found.\n",optarg); + exit(1); + } + break; case 'V': ver(); case 'h': /* fallthrough */ default: usage(); @@ -126,10 +141,19 @@ int main(int argc, char** argv) flags = fcntl(sd, F_GETFL, 0); fcntl(sd, F_SETFL, flags | O_NONBLOCK); } + if (do_bind) { + int tmp = bind(sd,(struct sockaddr *)&bind_addr,sizeof(bind_addr)); + if (tmp !=0 ) { + fprintf(stderr,"error can not bind to specified interface.\n"); + exit(1); + } + } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = *((long*)host->h_addr_list[0]); addr.sin_port = htons(port); + if (do_bind) + vprint("using %s:%u addr: ",inet_ntoa(bind_addr.sin_addr),bind_addr.sin_port); if(o_udp || proto == PROTO_UDP) { vprint("hitting udp %s:%u\n", inet_ntoa(addr.sin_addr), port); sendto(sd, "", 1, 0, (struct sockaddr*)&addr, sizeof(addr)); @@ -160,6 +184,7 @@ void usage() { printf("options:\n"); printf(" -u, --udp make all ports hits use UDP (default is TCP)\n"); printf(" -d, --delay wait milliseconds between port hits\n"); + printf(" -i, --interface use interface for port hits\n"); printf(" -v, --verbose be verbose\n"); printf(" -V, --version display version\n"); printf(" -h, --help this help\n"); From 86382d7524b629d2a34f49948195167d9300ce8c Mon Sep 17 00:00:00 2001 From: Sasan Jalali Date: Mon, 17 Sep 2018 15:05:01 +0430 Subject: [PATCH 2/3] corrected a typo --- doc/knock.1.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/knock.1.in b/doc/knock.1.in index 1f4347d..76bc378 100644 --- a/doc/knock.1.in +++ b/doc/knock.1.in @@ -21,7 +21,7 @@ where a router mistakes your stream of SYN packets as a port scan and blocks them. If the packet rate is slowed with \-\-delay, then the router should let the packets through. .TP -.B "\-i , \-\-delay " +.B "\-i , \-\-interface " Use network interface for knocks, like eth0. This option can be useful when a system has more than one network interface with different gateways (multihomed). From 08398278fc89ea3e506632608907174daba79ecb Mon Sep 17 00:00:00 2001 From: Sasan Jalali Date: Thu, 21 Feb 2019 01:54:59 +0330 Subject: [PATCH 3/3] added basic systemd support. --- Makefile.am | 8 +++++++- knockd.service | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 knockd.service diff --git a/Makefile.am b/Makefile.am index cbf297e..a7e2e8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,6 +9,12 @@ sbin_PROGRAMS = knockd dist_sbin_SCRIPTS = src/knock_helper_ipt.sh man_MANS += doc/knockd.1 sysconf_DATA = knockd.conf +unit_file = knockd.service +unit_dir = /etc/systemd/system + +install-data-hook: $(unit_files) + mkdir -p $(unit_dir) + cp $(unit_file) $(unit_dir) endif dist_doc_DATA = README.md TODO ChangeLog COPYING @@ -24,5 +30,5 @@ knockd_SOURCES = src/knockd.c src/list.c src/list.h src/knock_helper_ipt.sh %.1: %.1.in sed -e "s/#VERSION#/$(VERSION)/" $< > $@ -EXTRA_DIST = doc/knock.1 doc/knock.1.in doc/knockd.1 doc/knockd.1.in knockd.conf +EXTRA_DIST = doc/knock.1 doc/knock.1.in doc/knockd.1 doc/knockd.1.in knockd.conf knockd.service CLEANFILES = $(man_MANS) diff --git a/knockd.service b/knockd.service new file mode 100644 index 0000000..162a8a0 --- /dev/null +++ b/knockd.service @@ -0,0 +1,9 @@ +[Unit] +Description=Port-Knocking Daemon +After=network.target + +[Service] +ExecStart=/usr/bin/knockd + +[Install] +WantedBy=multi-user.target