Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

block requests from a Lua script #224

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ AS_IF([test "x$dns" = "xyes"],
])
])

SNIPROXY_WITH_LUAJIT
AS_IF([test "x$with_luajit" = "xno"], [
SNIPROXY_WITH_LUA
])

AC_ARG_ENABLE([rfc3339-timestamps],
[AS_HELP_STRING([--enable-rfc3339-timestamps], [Enable RFC3339 timestamps])],
[rfc3339_timestamps=${enableval}], [rfc3339_timestamps=no])
Expand Down
36 changes: 36 additions & 0 deletions m4/sniproxy_with_lua.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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@:>@])],
[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"])
])
22 changes: 22 additions & 0 deletions m4/sniproxy_with_luajit.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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@:>@])],
[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"])
])
13 changes: 13 additions & 0 deletions sniproxy.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function preconnect(remote, name)
print('->')
print("["..remote.."]")
print("["..name.."]")
name = string.lower(name)
print("["..name.."]")
if remote == '127.0.0.1' and name == 'www.example.com' then
print('blocking')
return true
end
print('--')
return false
end
4 changes: 2 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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)
22 changes: 22 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct Config {
char *filename;
char *user;
char *pidfile;
char *luafilename;
struct ResolverConfig {
char **nameservers;
char **search;
Expand Down
94 changes: 93 additions & 1 deletion src/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
Expand All @@ -43,6 +44,12 @@
#include <alloca.h>
#endif

#ifdef HAVE_LUA
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#endif

#include "connection.h"
#include "resolv.h"
#include "address.h"
Expand Down Expand Up @@ -205,6 +212,86 @@ 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));
}

#ifdef HAVE_LUA
lua_State *lua_state;

static void apply_lua_policy(struct Connection *con) {
if(lua_state) {
const struct sockaddr_storage *saddr = &(con->client.addr);
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) {
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);
}
}

lua_getglobal(lua_state, "preconnect");
if(!lua_isfunction(lua_state, -1)) {
fprintf(stderr, "no lua function\n");
lua_pop(lua_state, 1);
return;
}

lua_pushstring(lua_state, addr);
lua_pushlstring(lua_state, con->hostname, con->hostname != NULL ? con->hostname_len : 0);

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);
}
}
#endif

/*
* Main client callback: this is used by both the client and server watchers
*
Expand Down Expand Up @@ -254,8 +341,12 @@ 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) {
#ifdef HAVE_LUA
apply_lua_policy(con);
#endif
resolve_server_address(con, loop);
}
if (is_client && con->state == RESOLVED)
initiate_server_connect(con, loop);

Expand Down Expand Up @@ -370,6 +461,7 @@ parse_client_request(struct Connection *con) {

con->hostname = hostname;
con->hostname_len = result;
fprintf(stderr, "got hostname [%s] len [%d]\n", hostname != NULL ? hostname : "(null)", result);
con->state = PARSED;
}

Expand Down
23 changes: 23 additions & 0 deletions src/sniproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +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);
Expand All @@ -63,6 +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) {
Expand Down Expand Up @@ -121,6 +129,21 @@ main(int argc, char **argv) {
/* Drop permissions only when we can */
drop_perms(config->user ? config->user : default_username);

if(config->luafilename) {
#ifdef HAVE_LUA
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;
}
#else
fprintf(stderr, "luafilename specified but Lua support not compiled in\n");
return EXIT_FAILURE;
#endif
}

ev_signal_init(&sighup_watcher, signal_cb, SIGHUP);
ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1);
ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
Expand Down
10 changes: 5 additions & 5 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
@@ -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 \
Expand Down Expand Up @@ -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
Expand All @@ -71,19 +71,19 @@ 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 \
../src/table.c \
../src/address.c \
../src/logger.c

table_test_LDADD = $(LIBPCRE_LIBS)
table_test_LDADD = $(LIBPCRE_LIBS) $(LUA_LIBS)