From 27cd819d0679245be97d7164ee4b641f30e502e0 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 7 May 2014 14:33:36 +0800 Subject: [PATCH] refine local proxy for acl support --- libipset/Makefile | 18 ++++++--- libipset/Makefile.am | 2 +- libipset/Makefile.in | 18 ++++++--- src/Makefile.am | 1 + src/Makefile.in | 3 +- src/acl.c | 46 ++++++++++++++++++++-- src/acl.h | 8 ++++ src/local.c | 91 ++++++++++++++++++++++++++------------------ src/local.h | 1 + 9 files changed, 135 insertions(+), 53 deletions(-) create mode 100644 src/acl.h diff --git a/libipset/Makefile b/libipset/Makefile index 982f34a8..105a0802 100644 --- a/libipset/Makefile +++ b/libipset/Makefile @@ -126,8 +126,8 @@ am__objects_3 = set/libipset_la-allocation.lo \ set/libipset_la-inspection.lo set/libipset_la-ipv4_set.lo \ set/libipset_la-ipv6_set.lo set/libipset_la-iterator.lo \ set/libipset_la-storage.lo -am_libipset_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) +am_libipset_la_OBJECTS = libipset_la-general.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) libipset_la_OBJECTS = $(am_libipset_la_OBJECTS) AM_V_lt = $(am__v_lt_$(V)) am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) @@ -326,7 +326,7 @@ map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \ set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \ set/iterator.c set/storage.c -libipset_la_SOURCES = ${bdd_src} ${map_src} ${set_src} +libipset_la_SOURCES = general.c ${bdd_src} ${map_src} ${set_src} libipset_la_CFLAGS = -Iinclude libipset_la_LDFLAGS = -static all: all-am @@ -444,6 +444,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +include ./$(DEPDIR)/libipset_la-general.Plo include bdd/$(DEPDIR)/libipset_la-assignments.Plo include bdd/$(DEPDIR)/libipset_la-basics.Plo include bdd/$(DEPDIR)/libipset_la-bdd-iterator.Plo @@ -487,6 +488,13 @@ include set/$(DEPDIR)/libipset_la-storage.Plo # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ # $(AM_V_CC_no)$(LTCOMPILE) -c -o $@ $< +libipset_la-general.lo: general.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT libipset_la-general.lo -MD -MP -MF $(DEPDIR)/libipset_la-general.Tpo -c -o libipset_la-general.lo `test -f 'general.c' || echo '$(srcdir)/'`general.c + $(AM_V_at)$(am__mv) $(DEPDIR)/libipset_la-general.Tpo $(DEPDIR)/libipset_la-general.Plo +# $(AM_V_CC)source='general.c' object='libipset_la-general.lo' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(AM_V_CC_no)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o libipset_la-general.lo `test -f 'general.c' || echo '$(srcdir)/'`general.c + bdd/libipset_la-assignments.lo: bdd/assignments.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-assignments.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-assignments.Tpo -c -o bdd/libipset_la-assignments.lo `test -f 'bdd/assignments.c' || echo '$(srcdir)/'`bdd/assignments.c $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-assignments.Tpo bdd/$(DEPDIR)/libipset_la-assignments.Plo @@ -750,7 +758,7 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am - -rm -rf bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) + -rm -rf ./$(DEPDIR) bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -796,7 +804,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) + -rm -rf ./$(DEPDIR) bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/libipset/Makefile.am b/libipset/Makefile.am index 9f7325e4..82c52991 100644 --- a/libipset/Makefile.am +++ b/libipset/Makefile.am @@ -25,7 +25,7 @@ map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \ set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \ set/iterator.c set/storage.c -libipset_la_SOURCES = ${bdd_src} ${map_src} ${set_src} +libipset_la_SOURCES = general.c ${bdd_src} ${map_src} ${set_src} libipset_la_CFLAGS = -Iinclude libipset_la_LDFLAGS = -static diff --git a/libipset/Makefile.in b/libipset/Makefile.in index ba1fa744..cfe14a88 100644 --- a/libipset/Makefile.in +++ b/libipset/Makefile.in @@ -126,8 +126,8 @@ am__objects_3 = set/libipset_la-allocation.lo \ set/libipset_la-inspection.lo set/libipset_la-ipv4_set.lo \ set/libipset_la-ipv6_set.lo set/libipset_la-iterator.lo \ set/libipset_la-storage.lo -am_libipset_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) +am_libipset_la_OBJECTS = libipset_la-general.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) libipset_la_OBJECTS = $(am_libipset_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -326,7 +326,7 @@ map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \ set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \ set/iterator.c set/storage.c -libipset_la_SOURCES = ${bdd_src} ${map_src} ${set_src} +libipset_la_SOURCES = general.c ${bdd_src} ${map_src} ${set_src} libipset_la_CFLAGS = -Iinclude libipset_la_LDFLAGS = -static all: all-am @@ -444,6 +444,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libipset_la-general.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-assignments.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-basics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bdd/$(DEPDIR)/libipset_la-bdd-iterator.Plo@am__quote@ @@ -487,6 +488,13 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +libipset_la-general.lo: general.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT libipset_la-general.lo -MD -MP -MF $(DEPDIR)/libipset_la-general.Tpo -c -o libipset_la-general.lo `test -f 'general.c' || echo '$(srcdir)/'`general.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libipset_la-general.Tpo $(DEPDIR)/libipset_la-general.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='general.c' object='libipset_la-general.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -c -o libipset_la-general.lo `test -f 'general.c' || echo '$(srcdir)/'`general.c + bdd/libipset_la-assignments.lo: bdd/assignments.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libipset_la_CFLAGS) $(CFLAGS) -MT bdd/libipset_la-assignments.lo -MD -MP -MF bdd/$(DEPDIR)/libipset_la-assignments.Tpo -c -o bdd/libipset_la-assignments.lo `test -f 'bdd/assignments.c' || echo '$(srcdir)/'`bdd/assignments.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) bdd/$(DEPDIR)/libipset_la-assignments.Tpo bdd/$(DEPDIR)/libipset_la-assignments.Plo @@ -750,7 +758,7 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am - -rm -rf bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) + -rm -rf ./$(DEPDIR) bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -796,7 +804,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) + -rm -rf ./$(DEPDIR) bdd/$(DEPDIR) map/$(DEPDIR) set/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/Makefile.am b/src/Makefile.am index f919c2df..dad43b41 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,7 @@ AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasi AM_CFLAGS += -I$(top_builddir)/libev AM_CFLAGS += -I$(top_builddir)/libasyncns AM_CFLAGS += -I$(top_builddir)/libipset/include +AM_CFLAGS += -I$(top_builddir)/libcork/include AM_LDFLAGS = -static diff --git a/src/Makefile.in b/src/Makefile.in index 0517b207..4972bb22 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -340,7 +340,8 @@ top_srcdir = @top_srcdir@ AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations \ -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE \ -I$(top_builddir)/libev -I$(top_builddir)/libasyncns \ - -I$(top_builddir)/libipset/include + -I$(top_builddir)/libipset/include \ + -I$(top_builddir)/libcork/include AM_LDFLAGS = -static SS_COMMON_LIBS = $(top_builddir)/libev/libev.la \ $(top_builddir)/libcork/libcork.la \ diff --git a/src/acl.c b/src/acl.c index c6912f73..bfaec27b 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1,7 +1,47 @@ #include +#include -struct ip_set *init_acl(void) +static struct ip_set set; + +int init_acl(const char *path) +{ + ipset_init_library(); + ipset_init(&set); + + FILE *f = fopen(path, "r"); + if (f == NULL) FATAL("Invalid acl path."); + + char line[256]; + while(!feof(f)) + { + if (fgets(line, 256, f)) + { + char host[256]; + int cidr; + sscanf(line, "%s/%d", host, &cidr); + struct cork_ipv4 addr; + int err = cork_ipv4_init(&addr, host); + if (err) continue; + ipset_ipv4_add_network(&set, &addr, cidr); + } + } + + fclose(f); + + return 0; +} + +void free_acl(void) +{ + ipset_done(&set); +} + +int is_bypass(const char* host) { - struct ip_set *ipset = ipset_new(); - return ipset; + struct cork_ipv4 addr; + int err = cork_ipv4_init(&addr, host); + if (err) return 0; + struct cork_ip ip; + cork_ip_from_ipv4(&ip, &addr); + return ipset_contains_ip(&set, &ip); } diff --git a/src/acl.h b/src/acl.h new file mode 100644 index 00000000..d8edf50c --- /dev/null +++ b/src/acl.h @@ -0,0 +1,8 @@ +#ifndef _ACL_H +#define _ACL_H + +int init_acl(const char *path); +void free_acl(void); +int is_addr_bypass(const char* host); + +#endif // _ACL_H diff --git a/src/local.c b/src/local.c index 76411b47..a7d2aa85 100644 --- a/src/local.c +++ b/src/local.c @@ -50,7 +50,6 @@ int verbose = 0; int udprelay = 0; static int fast_open = 0; -static struct addrinfo *remote_res = NULL; #ifndef __MINGW32__ static int setnonblocking(int fd) @@ -196,7 +195,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { #ifdef TCP_FASTOPEN s = sendto(remote->fd, remote->buf, r, MSG_FASTOPEN, - remote_res->ai_addr, remote_res->ai_addrlen); + remote->addr_info->ai_addr, remote->addr_info->ai_addrlen); if (s == -1) { if (errno == EINPROGRESS) @@ -717,6 +716,7 @@ struct remote* new_remote(int fd, int timeout) remote->send_ctx->connected = 0; remote->buf_len = 0; remote->buf_idx = 0; + remote->addr_info = NULL; return remote; } @@ -732,6 +732,10 @@ static void free_remote(struct remote *remote) { free(remote->buf); } + if (remote->addr_info) + { + freeaddrinfo(remote->addr_info); + } free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -823,44 +827,29 @@ static void close_and_free_server(EV_P_ struct server *server) } } -static void accept_cb (EV_P_ ev_io *w, int revents) +static struct remote* connect_to_remote(struct listen_ctx *listener) { - struct listen_ctx *listener = (struct listen_ctx *)w; - int serverfd = accept(listener->fd, NULL, NULL); - if (serverfd == -1) - { - ERROR("accept"); - return; - } - setnonblocking(serverfd); int opt = 1; - setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); -#ifdef SO_NOSIGPIPE - setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); -#endif - int sockfd; + struct addrinfo *remote_res; - if (remote_res == NULL) + struct addrinfo hints; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + int index = rand() % listener->remote_num; + if (verbose) { - struct addrinfo hints; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - int index = rand() % listener->remote_num; - if (verbose) - { - LOGD("connect to %s:%s", listener->remote_addr[index].host, - listener->remote_addr[index].port); - } - int err = getaddrinfo(listener->remote_addr[index].host, - listener->remote_addr[index].port, - &hints, &remote_res); - if (err) - { - ERROR("getaddrinfo"); - return; - } + LOGD("connect to %s:%s", listener->remote_addr[index].host, + listener->remote_addr[index].port); + } + int err = getaddrinfo(listener->remote_addr[index].host, + listener->remote_addr[index].port, + &hints, &remote_res); + if (err) + { + ERROR("getaddrinfo"); + return NULL; } sockfd = socket(remote_res->ai_family, remote_res->ai_socktype, @@ -868,7 +857,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) if (sockfd < 0) { ERROR("socket"); - return; + return NULL; } setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); @@ -882,13 +871,39 @@ static void accept_cb (EV_P_ ev_io *w, int revents) if (listener->iface) setinterface(sockfd, listener->iface); #endif - struct server *server = new_server(serverfd, listener->method); struct remote *remote = new_remote(sockfd, listener->timeout); + remote->addr_info = remote_res; + + return remote; +} + + +static void accept_cb (EV_P_ ev_io *w, int revents) +{ + struct listen_ctx *listener = (struct listen_ctx *)w; + int serverfd = accept(listener->fd, NULL, NULL); + if (serverfd == -1) + { + ERROR("accept"); + return; + } + setnonblocking(serverfd); + int opt = 1; + setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif + + struct remote *remote = connect_to_remote(listener); + + if (remote == NULL) return; + + struct server *server = new_server(serverfd, listener->method); server->remote = remote; remote->server = server; if (!fast_open) { - connect(sockfd, remote_res->ai_addr, remote_res->ai_addrlen); + connect(remote->fd, remote->addr_info->ai_addr, remote->addr_info->ai_addrlen); // listen to remote connected event ev_io_start(EV_A_ &remote->send_ctx->io); ev_timer_start(EV_A_ &remote->send_ctx->watcher); diff --git a/src/local.h b/src/local.h index e71eff11..40afe604 100644 --- a/src/local.h +++ b/src/local.h @@ -59,6 +59,7 @@ struct remote struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; struct server *server; + struct addrinfo *addr_info; };