From 08fb289db582fc455fe8f97769f59d361021138c Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Mon, 6 Jun 2016 07:46:46 -0700 Subject: [PATCH 01/18] first stab at Lua support in sniproxy. Use ./configure CPPFLAGS='-I/usr/include/lua5.1' LIBS='-llua5.1' see sniproxy.lua for example. Note that there is no hostname normalisation, so adding a dot or uppercasing a letter would circumvent this simple example. --- sniproxy.lua | 21 ++++++++++++++++++ src/connection.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++- src/sniproxy.c | 12 +++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 sniproxy.lua diff --git a/sniproxy.lua b/sniproxy.lua new file mode 100644 index 00000000..d4d93f60 --- /dev/null +++ b/sniproxy.lua @@ -0,0 +1,21 @@ +function hex_dump(buf) + for byte=1, #buf, 16 do + local chunk = buf:sub(byte, byte+15) + io.write(string.format('%08X ',byte-1)) + chunk:gsub('.', function (c) io.write(string.format('%02X ',string.byte(c))) end) + io.write(string.rep(' ',3*(16-#chunk))) + io.write("\n") + end +end + +function preconnect(remote, name) + print('->') + hex_dump(remote) + print(name) + if remote == string.char(127,0,0,1) and name == 'rss.7bits.nl' then + print('blocking') + return true + end + print('--') + return false +end diff --git a/src/connection.c b/src/connection.c index 2a93899f..bb816812 100644 --- a/src/connection.c +++ b/src/connection.c @@ -205,6 +205,56 @@ server_socket_open(const struct Connection *con) { con->state == CLIENT_CLOSED; } +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +extern lua_State *lua_state; + +static void apply_lua_policy(struct Connection *con) { + struct sockaddr_storage *saddr = &(con->client.addr); + void *addrptr; + int addrlen; + + if (saddr->ss_family == AF_INET) { + addrlen = 4; + addrptr = &(((struct sockaddr_in *) saddr)->sin_addr); + } else if (saddr->ss_family == AF_INET6) { + addrlen = 16; + addrptr = &(((struct sockaddr_in6 *) saddr)->sin6_addr); + // [[::ffff:192.168.137.1]: + if(memcmp("\0\0\0\0\0\0\0\0\0\0\xff\xff", addrptr, 12) == 0) { + addrptr += 12; + addrlen = 4; + } + } + + fprintf(stderr, "in apply: [%s], addrlen=%d\n", con->hostname, addrlen); + lua_getglobal(lua_state, "preconnect"); + if(!lua_isfunction(lua_state, -1)) { + fprintf(stderr, "no lua function\n"); + lua_pop(lua_state, 1); + return; + } + + lua_pushlstring(lua_state, addrptr, addrlen); + lua_pushlstring(lua_state, con->hostname, con->hostname_len); + // if (strcmp(con->hostname, "rss.7bits.nl") == 0) + // abort_connection(con); + + if(lua_pcall(lua_state, 2, 1, 0)) { + fprintf(stderr, "lua hook error: %s\n", lua_tostring(lua_state, -1)); + lua_pop(lua_state, 1); + return; + } + + int block = lua_toboolean(lua_state, 1); + lua_pop(lua_state, 1); + fprintf(stderr, "block=%d\n", block); + if(block) + abort_connection(con); +} + /* * Main client callback: this is used by both the client and server watchers * @@ -254,8 +304,10 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { /* Handle any state specific logic */ if (is_client && con->state == ACCEPTED) parse_client_request(con); - if (is_client && con->state == PARSED) + if (is_client && con->state == PARSED) { + apply_lua_policy(con); resolve_server_address(con, loop); + } if (is_client && con->state == RESOLVED) initiate_server_connect(con, loop); @@ -370,6 +422,7 @@ parse_client_request(struct Connection *con) { con->hostname = hostname; con->hostname_len = result; + fprintf(stderr, "got hostname [%s] len [%d]\n", hostname, result); con->state = PARSED; } diff --git a/src/sniproxy.c b/src/sniproxy.c index 86d144d4..62fdc8a6 100644 --- a/src/sniproxy.c +++ b/src/sniproxy.c @@ -45,6 +45,9 @@ #include "resolv.h" #include "logger.h" +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" static void usage(); static void daemonize(void); @@ -63,6 +66,7 @@ static struct ev_signal sigusr1_watcher; static struct ev_signal sigint_watcher; static struct ev_signal sigterm_watcher; +lua_State *lua_state; int main(int argc, char **argv) { @@ -118,6 +122,14 @@ main(int argc, char **argv) { init_listeners(&config->listeners, &config->tables, EV_DEFAULT); + lua_state = luaL_newstate(); + luaL_openlibs(lua_state); + + if(luaL_dofile(lua_state, "./sniproxy.lua")) { + fprintf(stderr, "lua dofile error: %s\n", lua_isstring(lua_state, -1) ? lua_tostring(lua_state, -1) : "unknown error"); + return EXIT_FAILURE; + } + /* Drop permissions only when we can */ drop_perms(config->user ? config->user : default_username); From 18973af49335020dea16334fdef9e5750d1cda67 Mon Sep 17 00:00:00 2001 From: Pieter Lexis Date: Fri, 24 Jun 2016 14:29:22 +0200 Subject: [PATCH 02/18] autotools: Implement Lua detection based on PDNS --- configure.ac | 8 ++++++++ m4/pdns_with_lua.m4 | 36 ++++++++++++++++++++++++++++++++++++ m4/pdns_with_luajit.m4 | 22 ++++++++++++++++++++++ src/Makefile.am | 2 +- 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 m4/pdns_with_lua.m4 create mode 100644 m4/pdns_with_luajit.m4 diff --git a/configure.ac b/configure.ac index e2354401..8a518817 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,14 @@ AS_IF([test "x$dns" = "xyes"], ]) ]) +PDNS_WITH_LUAJIT +AS_IF([test "x$with_luajit" = "xno"], [ + PDNS_WITH_LUA +]) +AS_IF([test "x$with_luajit" = "xno" -a "x$with_lua" = "xno"], + [AC_MSG_ERROR([No Lua found]) +]) + AC_ARG_ENABLE([rfc3339-timestamps], [AS_HELP_STRING([--enable-rfc3339-timestamps], [Enable RFC3339 timestamps])], [rfc3339_timestamps=${enableval}], [rfc3339_timestamps=no]) diff --git a/m4/pdns_with_lua.m4 b/m4/pdns_with_lua.m4 new file mode 100644 index 00000000..18bb1b9d --- /dev/null +++ b/m4/pdns_with_lua.m4 @@ -0,0 +1,36 @@ +AC_DEFUN([PDNS_WITH_LUA],[ + AC_MSG_CHECKING([whether we will be linking in Lua]) + AC_ARG_WITH([lua], + [AS_HELP_STRING([--with-lua], [build Lua Bindings @<:@default=auto@:>@])], + [with_lua=$withval], + [with_lua=auto] + ) + AC_MSG_RESULT([$with_lua]) + + AS_IF([test "x$with_lua" != "xno"],[ + AS_IF([test "x$with_lua" = "xyes" -o "x$with_lua" = "xauto"], + [for LUAPC in lua5.3 lua-5.3 lua53 lua5.2 lua-5.2 lua52 lua5.1 lua-5.1 lua51 lua; do + PKG_CHECK_MODULES([LUA], $LUAPC >= 5.1, [ + AC_DEFINE([HAVE_LUA], [1], [Define to 1 if you have lua]) + with_lua=yes + ], [LUAPC=""]) # otherwise pkg_check will fail + if test "x$LUA_LIBS" != "x"; then break; fi + done + ], + [LUAPC="$with_lua" + PKG_CHECK_MODULES([LUA], $LUAPC >= 5.1, [ + AC_DEFINE([HAVE_LUA], [1], [Define to 1 if you have lua]) + with_lua=yes + ]) + ]) + AC_MSG_CHECKING([for chosen LUA]) + AS_IF([test "x$LUAPC" = "x"], [ + AS_IF([test "x$with_lua" = "xyes"], + [AC_MSG_ERROR([cannot find lua])], + [AC_MSG_RESULT([not found])] + )],[ + AC_MSG_RESULT([$LUAPC]) + ]) + ]) + AM_CONDITIONAL([LUA], [test "x$with_lua" = "xyes"]) +]) diff --git a/m4/pdns_with_luajit.m4 b/m4/pdns_with_luajit.m4 new file mode 100644 index 00000000..66394732 --- /dev/null +++ b/m4/pdns_with_luajit.m4 @@ -0,0 +1,22 @@ +AC_DEFUN([PDNS_WITH_LUAJIT],[ + AC_MSG_CHECKING([whether we will be linking in LuaJIT]) + AC_ARG_WITH([luajit], + [AS_HELP_STRING([--with-luajit], [build LuaJIT bindings @<:@default=auto@:>@])], + [with_luajit=$withval], + [with_luajit=no] + ) + AC_MSG_RESULT([$with_luajit]) + + AS_IF([test "x$with_luajit" = "xyes"], [ + LUAJITPC="$with_luajit" + PKG_CHECK_MODULES([LUA], [luajit], + [AC_DEFINE([HAVE_LUA], [1], [Define to 1 if you have LuaJIT])], + [LUAJITPC=""] + ) + AS_IF([test "x$LUAJITPC" = "x"], [ + AC_MSG_ERROR([LuaJIT not found])] + ) + ]) + + AM_CONDITIONAL([LUA], [test "x$with_luajit" = "xyes"]) +]) diff --git a/src/Makefile.am b/src/Makefile.am index ecc1f376..78c0368a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,4 +33,4 @@ sniproxy_SOURCES = sniproxy.c \ tls.c \ tls.h -sniproxy_LDADD = $(LIBEV_LIBS) $(LIBPCRE_LIBS) $(LIBUDNS_LIBS) +sniproxy_LDADD = $(LIBEV_LIBS) $(LIBPCRE_LIBS) $(LIBUDNS_LIBS) $(LUA_LIBS) From 235d37e28fb422eeb9d0d8d88b0ba62d19c9e0ce Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Fri, 23 Sep 2016 16:07:43 +0200 Subject: [PATCH 03/18] make sure lua includes are used --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 78c0368a..353010d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = $(LIBEV_CFLAGS) $(LIBPCRE_CFLAGS) $(LIBUDNS_CFLAGS) +AM_CPPFLAGS = $(LIBEV_CFLAGS) $(LIBPCRE_CFLAGS) $(LIBUDNS_CFLAGS) $(LUA_CFLAGS) sbin_PROGRAMS = sniproxy From 17799754fe3b19893230cbf55171d2d7e741597d Mon Sep 17 00:00:00 2001 From: Pieter Lexis Date: Sat, 8 Oct 2016 13:52:46 +0200 Subject: [PATCH 04/18] Add a luafilename config option --- src/config.c | 22 +++++++++++++++ src/config.h | 1 + src/connection.c | 70 +++++++++++++++++++++++++----------------------- src/sniproxy.c | 18 +++++++------ 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/src/config.c b/src/config.c index fcbee55a..08eb2932 100644 --- a/src/config.c +++ b/src/config.c @@ -39,6 +39,7 @@ struct LoggerBuilder { static int accept_username(struct Config *, char *); static int accept_pidfile(struct Config *, char *); +static int accept_luafilename(struct Config *, char *); static int end_listener_stanza(struct Config *, struct Listener *); static int end_table_stanza(struct Config *, struct Table *); static int end_backend(struct Table *, struct Backend *); @@ -151,6 +152,11 @@ static struct Keyword global_grammar[] = { (int(*)(void *, char *))accept_pidfile, NULL, NULL}, + { "luafilename", + NULL, + (int(*)(void *, char *))accept_luafilename, + NULL, + NULL}, { "resolver", (void *(*)())new_resolver_config, NULL, @@ -198,6 +204,7 @@ init_config(const char *filename, struct ev_loop *loop) { config->filename = NULL; config->user = NULL; config->pidfile = NULL; + config->luafilename = NULL; config->access_log = NULL; config->resolver.nameservers = NULL; config->resolver.search = NULL; @@ -253,6 +260,7 @@ free_config(struct Config *config, struct ev_loop *loop) { free(config->filename); free(config->user); free(config->pidfile); + free(config->luafilename); free_string_vector(config->resolver.nameservers); config->resolver.nameservers = NULL; @@ -302,6 +310,9 @@ print_config(FILE *file, struct Config *config) { if (config->pidfile) fprintf(file, "pidfile %s\n\n", config->pidfile); + if (config->luafilename) + fprintf(file, "luafilename %s\n\n", config->luafilename); + print_resolver_config(file, &config->resolver); SLIST_FOREACH(listener, &config->listeners, entries) { @@ -335,6 +346,17 @@ accept_pidfile(struct Config *config, char *pidfile) { return 1; } +static int +accept_luafilename(struct Config *config, char *luafilename) { + config->luafilename = strdup(luafilename); + if (config->luafilename == NULL) { + err("%s: strdup", __func__); + return -1; + } + + return 1; +} + static int end_listener_stanza(struct Config *config, struct Listener *listener) { if (valid_listener(listener) <= 0) { diff --git a/src/config.h b/src/config.h index 64d19c2d..2473123f 100644 --- a/src/config.h +++ b/src/config.h @@ -34,6 +34,7 @@ struct Config { char *filename; char *user; char *pidfile; + char *luafilename; struct ResolverConfig { char **nameservers; char **search; diff --git a/src/connection.c b/src/connection.c index bb816812..86c86eea 100644 --- a/src/connection.c +++ b/src/connection.c @@ -212,47 +212,49 @@ server_socket_open(const struct Connection *con) { extern lua_State *lua_state; static void apply_lua_policy(struct Connection *con) { - struct sockaddr_storage *saddr = &(con->client.addr); - void *addrptr; - int addrlen; - - if (saddr->ss_family == AF_INET) { - addrlen = 4; - addrptr = &(((struct sockaddr_in *) saddr)->sin_addr); - } else if (saddr->ss_family == AF_INET6) { - addrlen = 16; - addrptr = &(((struct sockaddr_in6 *) saddr)->sin6_addr); - // [[::ffff:192.168.137.1]: - if(memcmp("\0\0\0\0\0\0\0\0\0\0\xff\xff", addrptr, 12) == 0) { - addrptr += 12; + if(lua_state) { + struct sockaddr_storage *saddr = &(con->client.addr); + void *addrptr; + int addrlen; + + if (saddr->ss_family == AF_INET) { addrlen = 4; + addrptr = &(((struct sockaddr_in *) saddr)->sin_addr); + } else if (saddr->ss_family == AF_INET6) { + addrlen = 16; + addrptr = &(((struct sockaddr_in6 *) saddr)->sin6_addr); + // [[::ffff:192.168.137.1]: + if(memcmp("\0\0\0\0\0\0\0\0\0\0\xff\xff", addrptr, 12) == 0) { + addrptr += 12; + addrlen = 4; + } } - } - fprintf(stderr, "in apply: [%s], addrlen=%d\n", con->hostname, addrlen); - lua_getglobal(lua_state, "preconnect"); - if(!lua_isfunction(lua_state, -1)) { - fprintf(stderr, "no lua function\n"); - lua_pop(lua_state, 1); - return; - } + fprintf(stderr, "in apply: [%s], addrlen=%d\n", con->hostname, addrlen); + lua_getglobal(lua_state, "preconnect"); + if(!lua_isfunction(lua_state, -1)) { + fprintf(stderr, "no lua function\n"); + lua_pop(lua_state, 1); + return; + } - lua_pushlstring(lua_state, addrptr, addrlen); - lua_pushlstring(lua_state, con->hostname, con->hostname_len); - // if (strcmp(con->hostname, "rss.7bits.nl") == 0) - // abort_connection(con); + lua_pushlstring(lua_state, addrptr, addrlen); + lua_pushlstring(lua_state, con->hostname, con->hostname_len); + // if (strcmp(con->hostname, "rss.7bits.nl") == 0) + // abort_connection(con); - if(lua_pcall(lua_state, 2, 1, 0)) { - fprintf(stderr, "lua hook error: %s\n", lua_tostring(lua_state, -1)); + if(lua_pcall(lua_state, 2, 1, 0)) { + fprintf(stderr, "lua hook error: %s\n", lua_tostring(lua_state, -1)); + lua_pop(lua_state, 1); + return; + } + + int block = lua_toboolean(lua_state, 1); lua_pop(lua_state, 1); - return; + fprintf(stderr, "block=%d\n", block); + if(block) + abort_connection(con); } - - int block = lua_toboolean(lua_state, 1); - lua_pop(lua_state, 1); - fprintf(stderr, "block=%d\n", block); - if(block) - abort_connection(con); } /* diff --git a/src/sniproxy.c b/src/sniproxy.c index 62fdc8a6..aa7eb78e 100644 --- a/src/sniproxy.c +++ b/src/sniproxy.c @@ -122,17 +122,19 @@ main(int argc, char **argv) { init_listeners(&config->listeners, &config->tables, EV_DEFAULT); - lua_state = luaL_newstate(); - luaL_openlibs(lua_state); - - if(luaL_dofile(lua_state, "./sniproxy.lua")) { - fprintf(stderr, "lua dofile error: %s\n", lua_isstring(lua_state, -1) ? lua_tostring(lua_state, -1) : "unknown error"); - return EXIT_FAILURE; - } - /* Drop permissions only when we can */ drop_perms(config->user ? config->user : default_username); + if(config->luafilename) { + lua_state = luaL_newstate(); + luaL_openlibs(lua_state); + + if(luaL_dofile(lua_state, config->luafilename)) { + fprintf(stderr, "lua dofile error: %s\n", lua_isstring(lua_state, -1) ? lua_tostring(lua_state, -1) : "unknown error"); + return EXIT_FAILURE; + } + } + ev_signal_init(&sighup_watcher, signal_cb, SIGHUP); ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1); ev_signal_init(&sigint_watcher, signal_cb, SIGINT); From 1b51e167c9aa5935f68adf8ae561e35ebd14ea40 Mon Sep 17 00:00:00 2001 From: Pieter Lexis Date: Sat, 8 Oct 2016 17:27:22 +0200 Subject: [PATCH 05/18] Pass address as string to Lua preconnect --- src/connection.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/connection.c b/src/connection.c index 86c86eea..90b2b99b 100644 --- a/src/connection.c +++ b/src/connection.c @@ -214,23 +214,19 @@ extern lua_State *lua_state; static void apply_lua_policy(struct Connection *con) { if(lua_state) { struct sockaddr_storage *saddr = &(con->client.addr); - void *addrptr; - int addrlen; + int addrbegin = 0; + char addr[INET6_ADDRSTRLEN]; if (saddr->ss_family == AF_INET) { - addrlen = 4; - addrptr = &(((struct sockaddr_in *) saddr)->sin_addr); + inet_ntop(saddr->ss_family, &((struct sockaddr_in *) saddr)->sin_addr, addr, INET_ADDRSTRLEN); } else if (saddr->ss_family == AF_INET6) { - addrlen = 16; - addrptr = &(((struct sockaddr_in6 *) saddr)->sin6_addr); - // [[::ffff:192.168.137.1]: - if(memcmp("\0\0\0\0\0\0\0\0\0\0\xff\xff", addrptr, 12) == 0) { - addrptr += 12; - addrlen = 4; - } + char str2[INET6_ADDRSTRLEN]; + inet_ntop(saddr->ss_family, &((struct sockaddr_in6 *) saddr)->sin6_addr, addr, INET6_ADDRSTRLEN); + if(strncmp(addr, "::ffff:", 7) == 0) + addrbegin = 7; } - fprintf(stderr, "in apply: [%s], addrlen=%d\n", con->hostname, addrlen); +// fprintf(stderr, "in apply: [%s], addrlen=%d\n", con->hostname, addrlen); lua_getglobal(lua_state, "preconnect"); if(!lua_isfunction(lua_state, -1)) { fprintf(stderr, "no lua function\n"); @@ -238,7 +234,7 @@ static void apply_lua_policy(struct Connection *con) { return; } - lua_pushlstring(lua_state, addrptr, addrlen); + lua_pushlstring(lua_state, &addr[addrbegin], strlen(addr)); lua_pushlstring(lua_state, con->hostname, con->hostname_len); // if (strcmp(con->hostname, "rss.7bits.nl") == 0) // abort_connection(con); From 052fb80f9d4054a80694ba5d6f033e75553afacc Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Sat, 8 Oct 2016 19:12:35 +0200 Subject: [PATCH 06/18] fix off by 7 --- src/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connection.c b/src/connection.c index 90b2b99b..21270014 100644 --- a/src/connection.c +++ b/src/connection.c @@ -234,7 +234,7 @@ static void apply_lua_policy(struct Connection *con) { return; } - lua_pushlstring(lua_state, &addr[addrbegin], strlen(addr)); + lua_pushlstring(lua_state, &addr[addrbegin], strlen(addr+addrbegin)); lua_pushlstring(lua_state, con->hostname, con->hostname_len); // if (strcmp(con->hostname, "rss.7bits.nl") == 0) // abort_connection(con); From e883bc58feadecdc307d79033ba85563673daef8 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Sat, 8 Oct 2016 19:12:48 +0200 Subject: [PATCH 07/18] adapt lua example to new presentation format --- sniproxy.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sniproxy.lua b/sniproxy.lua index d4d93f60..f012c2c7 100644 --- a/sniproxy.lua +++ b/sniproxy.lua @@ -11,8 +11,9 @@ end function preconnect(remote, name) print('->') hex_dump(remote) + print(remote) print(name) - if remote == string.char(127,0,0,1) and name == 'rss.7bits.nl' then + if remote == '127.0.0.1' and name == 'rss.7bits.nl' then print('blocking') return true end From 67375d4ed74b25daf745a114b88acd52e326d1b2 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Sat, 8 Oct 2016 18:40:27 +0000 Subject: [PATCH 08/18] delimit --- sniproxy.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sniproxy.lua b/sniproxy.lua index f012c2c7..35e8dc15 100644 --- a/sniproxy.lua +++ b/sniproxy.lua @@ -11,8 +11,8 @@ end function preconnect(remote, name) print('->') hex_dump(remote) - print(remote) - print(name) + print("["..remote.."]") + print("["..name.."]") if remote == '127.0.0.1' and name == 'rss.7bits.nl' then print('blocking') return true From 7c662a438f0a65b4ad77258b84f0b49b1db3b130 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Mon, 10 Oct 2016 11:39:48 +0200 Subject: [PATCH 09/18] Don't crash on empty TLS SNI On empty SNI, -2 is stored in the hostname_len field. Since it's an unsigned type (size_t), this leads to an _interesting_ behavior. This was correctly handled in the existing parts of sniproxy, but not in the new Lua code. --- src/connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/connection.c b/src/connection.c index 21270014..02dda9c0 100644 --- a/src/connection.c +++ b/src/connection.c @@ -235,7 +235,7 @@ static void apply_lua_policy(struct Connection *con) { } lua_pushlstring(lua_state, &addr[addrbegin], strlen(addr+addrbegin)); - lua_pushlstring(lua_state, con->hostname, con->hostname_len); + lua_pushlstring(lua_state, con->hostname, con->hostname != NULL ? con->hostname_len : 0); // if (strcmp(con->hostname, "rss.7bits.nl") == 0) // abort_connection(con); @@ -420,7 +420,7 @@ parse_client_request(struct Connection *con) { con->hostname = hostname; con->hostname_len = result; - fprintf(stderr, "got hostname [%s] len [%d]\n", hostname, result); + fprintf(stderr, "got hostname [%s] len [%d]\n", hostname != NULL ? hostname : "(null)", result); con->state = PARSED; } From b875701c42433c3fdb7e3bfd7af66ffdc4868d71 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Mon, 10 Oct 2016 11:34:45 +0200 Subject: [PATCH 10/18] Detect IPv4-mapped and map to IPv4 based on the binary address Otherwise we might get in trouble if some platform / version decide to change the textual representation of IPv4-mapped addresses. --- src/connection.c | 53 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/src/connection.c b/src/connection.c index 02dda9c0..8c7930c4 100644 --- a/src/connection.c +++ b/src/connection.c @@ -24,6 +24,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include +#include #include #include #include @@ -205,6 +206,38 @@ server_socket_open(const struct Connection *con) { con->state == CLIENT_CLOSED; } +static bool is_mapped_ipv4(const struct sockaddr_in6* addr) { + if (addr->sin6_family != AF_INET6) { + return false; + } + + const unsigned char* ptr = (const unsigned char*) &addr->sin6_addr.s6_addr; + for (size_t idx = 0; idx < 10; idx++) { + if (ptr[idx] != 0) { + return false; + } + } + + if (ptr[10] != 0xff) { + return false; + } + + if (ptr[11] != 0xff) { + return false; + } + + return true; +} + +static void map_to_v4(const struct sockaddr_in6* src, struct sockaddr_in* dst) { + const unsigned char* ptr = (const unsigned char*) &src->sin6_addr.s6_addr; + dst->sin_family = AF_INET; + dst->sin_port = src->sin6_port; + + ptr += (sizeof(src->sin6_addr.s6_addr) - sizeof(dst->sin_addr.s_addr)); + memcpy(&dst->sin_addr.s_addr, ptr, sizeof(dst->sin_addr.s_addr)); +} + #include "lua.h" #include "lauxlib.h" #include "lualib.h" @@ -213,20 +246,24 @@ extern lua_State *lua_state; static void apply_lua_policy(struct Connection *con) { if(lua_state) { - struct sockaddr_storage *saddr = &(con->client.addr); - int addrbegin = 0; + const struct sockaddr_storage *saddr = &(con->client.addr); + struct sockaddr_storage unmapped; char addr[INET6_ADDRSTRLEN]; if (saddr->ss_family == AF_INET) { inet_ntop(saddr->ss_family, &((struct sockaddr_in *) saddr)->sin_addr, addr, INET_ADDRSTRLEN); } else if (saddr->ss_family == AF_INET6) { - char str2[INET6_ADDRSTRLEN]; - inet_ntop(saddr->ss_family, &((struct sockaddr_in6 *) saddr)->sin6_addr, addr, INET6_ADDRSTRLEN); - if(strncmp(addr, "::ffff:", 7) == 0) - addrbegin = 7; + if (is_mapped_ipv4((struct sockaddr_in6 *) saddr)) { + map_to_v4((struct sockaddr_in6 *) saddr, (struct sockaddr_in *) &unmapped); + saddr = &unmapped; + inet_ntop(saddr->ss_family, &((struct sockaddr_in *) saddr)->sin_addr, addr, INET_ADDRSTRLEN); + } + else { + inet_ntop(saddr->ss_family, &((struct sockaddr_in6 *) saddr)->sin6_addr, addr, INET6_ADDRSTRLEN); + } } -// fprintf(stderr, "in apply: [%s], addrlen=%d\n", con->hostname, addrlen); +// fprintf(stderr, "in apply: [%s](%zu), addr=%s, addrlen=%zu\n", con->hostname != NULL ? con->hostname : "(null)", con->hostname_len, addr, strlen(addr)); lua_getglobal(lua_state, "preconnect"); if(!lua_isfunction(lua_state, -1)) { fprintf(stderr, "no lua function\n"); @@ -234,7 +271,7 @@ static void apply_lua_policy(struct Connection *con) { return; } - lua_pushlstring(lua_state, &addr[addrbegin], strlen(addr+addrbegin)); + lua_pushlstring(lua_state, addr, strlen(addr)); lua_pushlstring(lua_state, con->hostname, con->hostname != NULL ? con->hostname_len : 0); // if (strcmp(con->hostname, "rss.7bits.nl") == 0) // abort_connection(con); From ed521c546833e875069275d646e9c72b5a3e20f4 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 09:31:01 +0100 Subject: [PATCH 11/18] unbreak make check --- src/connection.c | 2 +- src/sniproxy.c | 2 +- tests/Makefile.am | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/connection.c b/src/connection.c index 8c7930c4..bf3067a3 100644 --- a/src/connection.c +++ b/src/connection.c @@ -242,7 +242,7 @@ static void map_to_v4(const struct sockaddr_in6* src, struct sockaddr_in* dst) { #include "lauxlib.h" #include "lualib.h" -extern lua_State *lua_state; +lua_State *lua_state; static void apply_lua_policy(struct Connection *con) { if(lua_state) { diff --git a/src/sniproxy.c b/src/sniproxy.c index aa7eb78e..aee0e2ed 100644 --- a/src/sniproxy.c +++ b/src/sniproxy.c @@ -66,7 +66,7 @@ static struct ev_signal sigusr1_watcher; static struct ev_signal sigint_watcher; static struct ev_signal sigterm_watcher; -lua_State *lua_state; +extern lua_State *lua_state; int main(int argc, char **argv) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 53849952..ad4bcce9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src -g $(LIBEV_CFLAGS) $(LIBPCRE_CFLAGS) $(LIBUDNS_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/src -g $(LIBEV_CFLAGS) $(LIBPCRE_CFLAGS) $(LIBUDNS_CFLAGS) $(LUA_CFLAGS) TESTS = http_test \ tls_test \ @@ -46,7 +46,7 @@ binder_test_SOURCES = binder_test.c \ buffer_test_SOURCES = buffer_test.c \ ../src/buffer.c -buffer_test_LDADD = $(LIBEV_LIBS) +buffer_test_LDADD = $(LIBEV_LIBS) $(LUA_LIBS) address_test_SOURCES = address_test.c \ ../src/address.c @@ -71,14 +71,14 @@ config_test_SOURCES = config_test.c \ ../src/tls.c \ ../src/http.c -config_test_LDADD = $(LIBEV_LIBS) $(LIBPCRE_LIBS) $(LIBUDNS_LIBS) +config_test_LDADD = $(LIBEV_LIBS) $(LIBPCRE_LIBS) $(LIBUDNS_LIBS) $(LUA_LIBS) resolv_test_SOURCES = resolv_test.c \ ../src/resolv.c \ ../src/address.c \ ../src/logger.c -resolv_test_LDADD = $(LIBEV_LIBS) $(LIBUDNS_LIBS) +resolv_test_LDADD = $(LIBEV_LIBS) $(LIBUDNS_LIBS) $(LUA_LIBS) table_test_SOURCES = table_test.c \ ../src/backend.c \ @@ -86,4 +86,4 @@ table_test_SOURCES = table_test.c \ ../src/address.c \ ../src/logger.c -table_test_LDADD = $(LIBPCRE_LIBS) +table_test_LDADD = $(LIBPCRE_LIBS) $(LUA_LIBS) From 9884477d8cc7c296f03fdd63ca26f677f61ece50 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 10:06:33 +0100 Subject: [PATCH 12/18] lowercase name to prevent uppercase names from going around the block --- sniproxy.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sniproxy.lua b/sniproxy.lua index 35e8dc15..ea121421 100644 --- a/sniproxy.lua +++ b/sniproxy.lua @@ -13,6 +13,8 @@ function preconnect(remote, name) hex_dump(remote) print("["..remote.."]") print("["..name.."]") + name = string.lower(name) + print("["..name.."]") if remote == '127.0.0.1' and name == 'rss.7bits.nl' then print('blocking') return true From 1e4d3f1ded520f79a7b3b89d638be0dd10423312 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 11:01:31 +0100 Subject: [PATCH 13/18] rename PDNS sourced m4s; allow building without Lua --- configure.ac | 7 ++----- m4/{pdns_with_lua.m4 => sniproxy_with_lua.m4} | 2 +- m4/{pdns_with_luajit.m4 => sniproxy_with_luajit.m4} | 2 +- src/connection.c | 4 ++++ src/sniproxy.c | 9 +++++++++ 5 files changed, 17 insertions(+), 7 deletions(-) rename m4/{pdns_with_lua.m4 => sniproxy_with_lua.m4} (97%) rename m4/{pdns_with_luajit.m4 => sniproxy_with_luajit.m4} (94%) diff --git a/configure.ac b/configure.ac index 8a518817..3a64fc83 100644 --- a/configure.ac +++ b/configure.ac @@ -50,12 +50,9 @@ AS_IF([test "x$dns" = "xyes"], ]) ]) -PDNS_WITH_LUAJIT +SNIPROXY_WITH_LUAJIT AS_IF([test "x$with_luajit" = "xno"], [ - PDNS_WITH_LUA -]) -AS_IF([test "x$with_luajit" = "xno" -a "x$with_lua" = "xno"], - [AC_MSG_ERROR([No Lua found]) + SNIPROXY_WITH_LUA ]) AC_ARG_ENABLE([rfc3339-timestamps], diff --git a/m4/pdns_with_lua.m4 b/m4/sniproxy_with_lua.m4 similarity index 97% rename from m4/pdns_with_lua.m4 rename to m4/sniproxy_with_lua.m4 index 18bb1b9d..79bb445b 100644 --- a/m4/pdns_with_lua.m4 +++ b/m4/sniproxy_with_lua.m4 @@ -1,4 +1,4 @@ -AC_DEFUN([PDNS_WITH_LUA],[ +AC_DEFUN([SNIPROXY_WITH_LUA],[ AC_MSG_CHECKING([whether we will be linking in Lua]) AC_ARG_WITH([lua], [AS_HELP_STRING([--with-lua], [build Lua Bindings @<:@default=auto@:>@])], diff --git a/m4/pdns_with_luajit.m4 b/m4/sniproxy_with_luajit.m4 similarity index 94% rename from m4/pdns_with_luajit.m4 rename to m4/sniproxy_with_luajit.m4 index 66394732..a448ddff 100644 --- a/m4/pdns_with_luajit.m4 +++ b/m4/sniproxy_with_luajit.m4 @@ -1,4 +1,4 @@ -AC_DEFUN([PDNS_WITH_LUAJIT],[ +AC_DEFUN([SNIPROXY_WITH_LUAJIT],[ AC_MSG_CHECKING([whether we will be linking in LuaJIT]) AC_ARG_WITH([luajit], [AS_HELP_STRING([--with-luajit], [build LuaJIT bindings @<:@default=auto@:>@])], diff --git a/src/connection.c b/src/connection.c index bf3067a3..aac58101 100644 --- a/src/connection.c +++ b/src/connection.c @@ -238,6 +238,7 @@ static void map_to_v4(const struct sockaddr_in6* src, struct sockaddr_in* dst) { memcpy(&dst->sin_addr.s_addr, ptr, sizeof(dst->sin_addr.s_addr)); } +#ifdef HAVE_LUA #include "lua.h" #include "lauxlib.h" #include "lualib.h" @@ -289,6 +290,7 @@ static void apply_lua_policy(struct Connection *con) { abort_connection(con); } } +#endif /* * Main client callback: this is used by both the client and server watchers @@ -340,7 +342,9 @@ connection_cb(struct ev_loop *loop, struct ev_io *w, int revents) { if (is_client && con->state == ACCEPTED) parse_client_request(con); if (is_client && con->state == PARSED) { +#ifdef HAVE_LUA apply_lua_policy(con); +#endif resolve_server_address(con, loop); } if (is_client && con->state == RESOLVED) diff --git a/src/sniproxy.c b/src/sniproxy.c index aee0e2ed..1270e1db 100644 --- a/src/sniproxy.c +++ b/src/sniproxy.c @@ -45,9 +45,11 @@ #include "resolv.h" #include "logger.h" +#ifdef HAVE_LUA #include "lua.h" #include "lauxlib.h" #include "lualib.h" +#endif static void usage(); static void daemonize(void); @@ -66,7 +68,9 @@ static struct ev_signal sigusr1_watcher; static struct ev_signal sigint_watcher; static struct ev_signal sigterm_watcher; +#ifdef HAVE_LUA extern lua_State *lua_state; +#endif int main(int argc, char **argv) { @@ -126,6 +130,7 @@ main(int argc, char **argv) { drop_perms(config->user ? config->user : default_username); if(config->luafilename) { +#ifdef HAVE_LUA lua_state = luaL_newstate(); luaL_openlibs(lua_state); @@ -133,6 +138,10 @@ main(int argc, char **argv) { fprintf(stderr, "lua dofile error: %s\n", lua_isstring(lua_state, -1) ? lua_tostring(lua_state, -1) : "unknown error"); return EXIT_FAILURE; } +#else + fprintf(stderr, "luafilename specified but Lua support not compiled in\n"); + return EXIT_FAILURE; +#endif } ev_signal_init(&sighup_watcher, signal_cb, SIGHUP); From 1d309c590ccd57a7ce72b2fdad6e4fd3911fd220 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 11:20:17 +0100 Subject: [PATCH 14/18] remove debugging code make sure addr is a valid nul-terminated string avoid useless strlen call --- src/connection.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/connection.c b/src/connection.c index aac58101..77948f90 100644 --- a/src/connection.c +++ b/src/connection.c @@ -251,6 +251,7 @@ static void apply_lua_policy(struct Connection *con) { struct sockaddr_storage unmapped; char addr[INET6_ADDRSTRLEN]; + addr[0]='\0'; if (saddr->ss_family == AF_INET) { inet_ntop(saddr->ss_family, &((struct sockaddr_in *) saddr)->sin_addr, addr, INET_ADDRSTRLEN); } else if (saddr->ss_family == AF_INET6) { @@ -264,7 +265,6 @@ static void apply_lua_policy(struct Connection *con) { } } -// fprintf(stderr, "in apply: [%s](%zu), addr=%s, addrlen=%zu\n", con->hostname != NULL ? con->hostname : "(null)", con->hostname_len, addr, strlen(addr)); lua_getglobal(lua_state, "preconnect"); if(!lua_isfunction(lua_state, -1)) { fprintf(stderr, "no lua function\n"); @@ -272,10 +272,8 @@ static void apply_lua_policy(struct Connection *con) { return; } - lua_pushlstring(lua_state, addr, strlen(addr)); + lua_pushstring(lua_state, addr); lua_pushlstring(lua_state, con->hostname, con->hostname != NULL ? con->hostname_len : 0); - // if (strcmp(con->hostname, "rss.7bits.nl") == 0) - // abort_connection(con); if(lua_pcall(lua_state, 2, 1, 0)) { fprintf(stderr, "lua hook error: %s\n", lua_tostring(lua_state, -1)); From efafec4b08af6604db04fe88a45b8e1024206fd6 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 11:32:23 +0100 Subject: [PATCH 15/18] move includes; change to <> --- src/connection.c | 10 ++++++---- src/sniproxy.c | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/connection.c b/src/connection.c index 77948f90..137e5512 100644 --- a/src/connection.c +++ b/src/connection.c @@ -44,6 +44,12 @@ #include #endif +#ifdef HAVE_LUA +#include +#include +#include +#endif + #include "connection.h" #include "resolv.h" #include "address.h" @@ -239,10 +245,6 @@ static void map_to_v4(const struct sockaddr_in6* src, struct sockaddr_in* dst) { } #ifdef HAVE_LUA -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" - lua_State *lua_state; static void apply_lua_policy(struct Connection *con) { diff --git a/src/sniproxy.c b/src/sniproxy.c index 1270e1db..f0d871bb 100644 --- a/src/sniproxy.c +++ b/src/sniproxy.c @@ -46,9 +46,9 @@ #include "logger.h" #ifdef HAVE_LUA -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" +#include +#include +#include #endif static void usage(); From 6f703991dfa53e2aaee0e63ec902b28ec5a46d09 Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 20:30:01 +0100 Subject: [PATCH 16/18] whitespace nit --- sniproxy.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sniproxy.lua b/sniproxy.lua index ea121421..62e8bdc7 100644 --- a/sniproxy.lua +++ b/sniproxy.lua @@ -4,7 +4,7 @@ function hex_dump(buf) io.write(string.format('%08X ',byte-1)) chunk:gsub('.', function (c) io.write(string.format('%02X ',string.byte(c))) end) io.write(string.rep(' ',3*(16-#chunk))) - io.write("\n") + io.write("\n") end end From ff5b6ce53d9ffe17da79868fb2dc1597118ceacc Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 20:36:00 +0100 Subject: [PATCH 17/18] change example domain --- sniproxy.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sniproxy.lua b/sniproxy.lua index 62e8bdc7..d00632f4 100644 --- a/sniproxy.lua +++ b/sniproxy.lua @@ -15,7 +15,7 @@ function preconnect(remote, name) print("["..name.."]") name = string.lower(name) print("["..name.."]") - if remote == '127.0.0.1' and name == 'rss.7bits.nl' then + if remote == '127.0.0.1' and name == 'www.example.com' then print('blocking') return true end From e1be7f4676aa597b26ca627ad6eabd925ec46d2f Mon Sep 17 00:00:00 2001 From: Peter van Dijk Date: Tue, 7 Feb 2017 20:37:12 +0100 Subject: [PATCH 18/18] stop hexdumping remote now that it's in presentation format --- sniproxy.lua | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/sniproxy.lua b/sniproxy.lua index d00632f4..7d277d22 100644 --- a/sniproxy.lua +++ b/sniproxy.lua @@ -1,16 +1,5 @@ -function hex_dump(buf) - for byte=1, #buf, 16 do - local chunk = buf:sub(byte, byte+15) - io.write(string.format('%08X ',byte-1)) - chunk:gsub('.', function (c) io.write(string.format('%02X ',string.byte(c))) end) - io.write(string.rep(' ',3*(16-#chunk))) - io.write("\n") - end -end - function preconnect(remote, name) print('->') - hex_dump(remote) print("["..remote.."]") print("["..name.."]") name = string.lower(name)