diff --git a/net/redsocks/Makefile b/net/redsocks/Makefile index caf541e1ba..4f5f563cae 100644 --- a/net/redsocks/Makefile +++ b/net/redsocks/Makefile @@ -8,14 +8,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=redsocks -PKG_VERSION:=0.4 +PKG_VERSION:=0.4-20150907 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_PROTO:=git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_URL:=https://github.com/darkk/redsocks.git -PKG_SOURCE_VERSION:=release-0.4 +PKG_SOURCE_VERSION:=2118c616b4970a0436eceaa57a6e3451ec98ad2b PKG_MAINTAINER:=Johannes Morgenroth PKG_LICENSE:=Apache-2.0 diff --git a/net/redsocks/patches/0001-Fix-bug-in-DNS-resolution-results-were-ignored-since.patch b/net/redsocks/patches/0001-Fix-bug-in-DNS-resolution-results-were-ignored-since.patch deleted file mode 100644 index 595be191d4..0000000000 --- a/net/redsocks/patches/0001-Fix-bug-in-DNS-resolution-results-were-ignored-since.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 290f19972e9f7b74f818ae211cb535e32f1f314f Mon Sep 17 00:00:00 2001 -From: Leonid Evdokimov -Date: Tue, 10 Apr 2012 00:57:26 +0400 -Subject: [PATCH 01/12] Fix bug in DNS resolution - results were ignored (since - 8179a1ff). - ---- - parser.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/parser.c b/parser.c -index 85d3533..6198828 100644 ---- a/parser.c -+++ b/parser.c -@@ -295,22 +295,22 @@ static int vp_in_addr(parser_context *context, void *addr, const char *token) - memcpy(addr, &ia, sizeof(ia)); - } - else { -- struct addrinfo *addr, hints; -+ struct addrinfo *ainfo, hints; - int err; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; /* IPv4-only */ - hints.ai_socktype = SOCK_STREAM; /* I want to have one address once and ONLY once, that's why I specify socktype and protocol */ - hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_ADDRCONFIG; /* I don't need IPv4 addrs without IPv4 connectivity */ -- err = getaddrinfo(token, NULL, &hints, &addr); -+ err = getaddrinfo(token, NULL, &hints, &ainfo); - if (err == 0) { - int count, taken; - struct addrinfo *iter; - struct sockaddr_in *resolved_addr; -- for (iter = addr, count = 0; iter; iter = iter->ai_next, ++count) -+ for (iter = ainfo, count = 0; iter; iter = iter->ai_next, ++count) - ; - taken = rand() % count; -- for (iter = addr; taken > 0; iter = iter->ai_next, --taken) -+ for (iter = ainfo; taken > 0; iter = iter->ai_next, --taken) - ; - resolved_addr = (struct sockaddr_in*)iter->ai_addr; - assert(resolved_addr->sin_family == iter->ai_family && iter->ai_family == AF_INET); -@@ -318,7 +318,7 @@ static int vp_in_addr(parser_context *context, void *addr, const char *token) - log_error(LOG_WARNING, "%s resolves to %d addresses, using %s", - token, count, inet_ntoa(resolved_addr->sin_addr)); - memcpy(addr, &resolved_addr->sin_addr, sizeof(ia)); -- freeaddrinfo(addr); -+ freeaddrinfo(ainfo); - } - else { - if (err == EAI_SYSTEM) --- -1.9.1 - diff --git a/net/redsocks/patches/0002-inet_ntop-red_inet_ntop.patch b/net/redsocks/patches/0002-inet_ntop-red_inet_ntop.patch deleted file mode 100644 index 058556e795..0000000000 --- a/net/redsocks/patches/0002-inet_ntop-red_inet_ntop.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 6015b3a6f26e04dd5d78cd6c1320886fc9035612 Mon Sep 17 00:00:00 2001 -From: Leonid Evdokimov -Date: Tue, 10 Apr 2012 01:37:34 +0400 -Subject: [PATCH 02/12] inet_ntop -> red_inet_ntop - ---- - redsocks.c | 13 ++++--------- - redudp.c | 19 +++++++++++-------- - utils.c | 37 +++++++++++++++++++++++++++++++++---- - utils.h | 7 +++++++ - 4 files changed, 55 insertions(+), 21 deletions(-) - -diff --git a/redsocks.c b/redsocks.c -index d085e10..ba5eab2 100644 ---- a/redsocks.c -+++ b/redsocks.c -@@ -207,22 +207,17 @@ void redsocks_log_write_plain( - int saved_errno = errno; - struct evbuffer *fmt = evbuffer_new(); - va_list ap; -- char clientaddr_str[INET6_ADDRSTRLEN], destaddr_str[INET6_ADDRSTRLEN]; -+ char clientaddr_str[RED_INET_ADDRSTRLEN], destaddr_str[RED_INET_ADDRSTRLEN]; - - if (!fmt) { - log_errno(LOG_ERR, "evbuffer_new()"); - // no return, as I have to call va_start/va_end - } - -- if (!inet_ntop(clientaddr->sin_family, &clientaddr->sin_addr, clientaddr_str, sizeof(clientaddr_str))) -- strncpy(clientaddr_str, "???", sizeof(clientaddr_str)); -- if (!inet_ntop(destaddr->sin_family, &destaddr->sin_addr, destaddr_str, sizeof(destaddr_str))) -- strncpy(destaddr_str, "???", sizeof(destaddr_str)); -- - if (fmt) { -- evbuffer_add_printf(fmt, "[%s:%i->%s:%i]: %s", -- clientaddr_str, ntohs(clientaddr->sin_port), -- destaddr_str, ntohs(destaddr->sin_port), -+ evbuffer_add_printf(fmt, "[%s->%s]: %s", -+ red_inet_ntop(clientaddr, clientaddr_str, sizeof(clientaddr_str)), -+ red_inet_ntop(destaddr, destaddr_str, sizeof(destaddr_str)), - orig_fmt); - } - -diff --git a/redudp.c b/redudp.c -index 0a97852..9516a50 100644 ---- a/redudp.c -+++ b/redudp.c -@@ -436,10 +436,9 @@ static void redudp_pkt_from_socks(int fd, short what, void *_arg) - return; - - if (memcmp(&udprelayaddr, &client->udprelayaddr, sizeof(udprelayaddr)) != 0) { -- char buf[INET6_ADDRSTRLEN]; -- const char *addr = inet_ntop(udprelayaddr.sin_family, &udprelayaddr.sin_addr, buf, sizeof(buf)); -- redudp_log_error(client, LOG_NOTICE, "Got packet from unexpected address %s:%u.", -- addr ? addr : "?", ntohs(udprelayaddr.sin_port)); -+ char buf[RED_INET_ADDRSTRLEN]; -+ redudp_log_error(client, LOG_NOTICE, "Got packet from unexpected address %s.", -+ red_inet_ntop(&udprelayaddr, buf, sizeof(buf))); - return; - } - -@@ -459,10 +458,14 @@ static void redudp_pkt_from_socks(int fd, short what, void *_arg) - if (pkt.header.ip.port != client->instance->config.destaddr.sin_port || - pkt.header.ip.addr != client->instance->config.destaddr.sin_addr.s_addr) - { -- char buf[INET6_ADDRSTRLEN]; -- const char *addr = inet_ntop(AF_INET, &pkt.header.ip.addr, buf, sizeof(buf)); -- redudp_log_error(client, LOG_NOTICE, "Socks5 server relayed packet from unexpected address %s:%u.", -- addr ? addr : "?", ntohs(pkt.header.ip.port)); -+ char buf[RED_INET_ADDRSTRLEN]; -+ struct sockaddr_in pktaddr = { -+ .sin_family = AF_INET, -+ .sin_addr = { pkt.header.ip.addr }, -+ .sin_port = pkt.header.ip.port, -+ }; -+ redudp_log_error(client, LOG_NOTICE, "Socks5 server relayed packet from unexpected address %s.", -+ red_inet_ntop(&pktaddr, buf, sizeof(buf))); - return; - } - -diff --git a/utils.c b/utils.c -index c6ced51..6e1f3af 100644 ---- a/utils.c -+++ b/utils.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -42,10 +43,9 @@ int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inadd - } - - if (pktlen >= buflen) { -- char buf[INET6_ADDRSTRLEN]; -- const char *addr = inet_ntop(inaddr->sin_family, &inaddr->sin_addr, buf, sizeof(buf)); -- log_error(LOG_WARNING, "wow! Truncated udp packet of size %zd from %s:%u! impossible! dropping it...", -- pktlen, addr ? addr : "?", ntohs(inaddr->sin_port)); -+ char buf[RED_INET_ADDRSTRLEN]; -+ log_error(LOG_WARNING, "wow! Truncated udp packet of size %zd from %s! impossible! dropping it...", -+ pktlen, red_inet_ntop(inaddr, buf, sizeof(buf))); - return -1; - } - -@@ -176,4 +176,33 @@ int red_is_socket_connected_ok(struct bufferevent *buffev) - } - } - -+char *red_inet_ntop(const struct sockaddr_in* sa, char* buffer, size_t buffer_size) -+{ -+ const char *retval = 0; -+ size_t len = 0; -+ uint16_t port; -+ const char placeholder[] = "???:???"; -+ -+ assert(buffer_size >= sizeof(placeholder)); -+ -+ memset(buffer, buffer_size, 0); -+ if (sa->sin_family == AF_INET) { -+ retval = inet_ntop(AF_INET, &sa->sin_addr, buffer, buffer_size); -+ port = ((struct sockaddr_in*)sa)->sin_port; -+ } -+ else if (sa->sin_family == AF_INET6) { -+ retval = inet_ntop(AF_INET6, &((const struct sockaddr_in6*)sa)->sin6_addr, buffer, buffer_size); -+ port = ((struct sockaddr_in6*)sa)->sin6_port; -+ } -+ if (retval) { -+ assert(retval == buffer); -+ len = strlen(retval); -+ snprintf(buffer + len, buffer_size - len, ":%d", ntohs(port)); -+ } -+ else { -+ strcpy(buffer, placeholder); -+ } -+ return buffer; -+} -+ - /* vim:set tabstop=4 softtabstop=4 shiftwidth=4: */ -diff --git a/utils.h b/utils.h -index f691b77..d3af00f 100644 ---- a/utils.h -+++ b/utils.h -@@ -57,6 +57,13 @@ int fcntl_nonblock(int fd); - (what) & EVBUFFER_TIMEOUT ? "EVBUFFER_TIMEOUT" : "0", \ - (what) & ~(EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF|EVBUFFER_ERROR|EVBUFFER_TIMEOUT) - -+#if INET6_ADDRSTRLEN < INET_ADDRSTRLEN -+# error Impossible happens: INET6_ADDRSTRLEN < INET_ADDRSTRLEN -+#else -+# define RED_INET_ADDRSTRLEN (INET6_ADDRSTRLEN + 1 + 5 + 1) // addr + : + port + \0 -+#endif -+char *red_inet_ntop(const struct sockaddr_in* sa, char* buffer, size_t buffer_size); -+ - /* vim:set tabstop=4 softtabstop=4 shiftwidth=4: */ - /* vim:set foldmethod=marker foldlevel=32 foldmarker={,}: */ - #endif /* UTILS_H_SAT_FEB__2_02_24_05_2008 */ --- -1.9.1 - diff --git a/net/redsocks/patches/0003-Initial-support-for-UDP-TPROXY-redirection.-No-more-.patch b/net/redsocks/patches/0003-Initial-support-for-UDP-TPROXY-redirection.-No-more-.patch deleted file mode 100644 index b89f4be902..0000000000 --- a/net/redsocks/patches/0003-Initial-support-for-UDP-TPROXY-redirection.-No-more-.patch +++ /dev/null @@ -1,449 +0,0 @@ -From 709646d59d96cb73a7e70347f37de9823e4e5f14 Mon Sep 17 00:00:00 2001 -From: Leonid Evdokimov -Date: Fri, 13 Apr 2012 01:57:23 +0400 -Subject: [PATCH 03/12] Initial support for UDP + TPROXY redirection. No more - dest_ip in redudp. - - * TPROXY requires Linux 2.6.29+ (see man 7 ip[1]). - * all redsocks code is running as root to bind to arbitrary port. - * Non-Linux and old-Linux builds are broken at the moment. - -[1] http://www.kernel.org/doc/man-pages/online/pages/man7/ip.7.html ---- - dnstc.c | 2 +- - redudp.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- - redudp.h | 2 + - utils.c | 43 +++++++++++++- - utils.h | 2 +- - 5 files changed, 227 insertions(+), 19 deletions(-) - -diff --git a/dnstc.c b/dnstc.c -index 43881d8..5f9fedd 100644 ---- a/dnstc.c -+++ b/dnstc.c -@@ -68,7 +68,7 @@ static void dnstc_pkt_from_client(int fd, short what, void *_arg) - ssize_t pktlen, outgoing; - - assert(fd == EVENT_FD(&self->listener)); -- pktlen = red_recv_udp_pkt(fd, buf.raw, sizeof(buf), &clientaddr); -+ pktlen = red_recv_udp_pkt(fd, buf.raw, sizeof(buf), &clientaddr, NULL); - if (pktlen == -1) - return; - -diff --git a/redudp.c b/redudp.c -index 9516a50..262af3e 100644 ---- a/redudp.c -+++ b/redudp.c -@@ -15,6 +15,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -33,30 +34,157 @@ - #include "redudp.h" - - #define redudp_log_error(client, prio, msg...) \ -- redsocks_log_write_plain(__FILE__, __LINE__, __func__, 0, &(client)->clientaddr, &(client)->instance->config.destaddr, prio, ## msg) -+ redsocks_log_write_plain(__FILE__, __LINE__, __func__, 0, &(client)->clientaddr, get_destaddr(client), prio, ## msg) - #define redudp_log_errno(client, prio, msg...) \ -- redsocks_log_write_plain(__FILE__, __LINE__, __func__, 1, &(client)->clientaddr, &(client)->instance->config.destaddr, prio, ## msg) -+ redsocks_log_write_plain(__FILE__, __LINE__, __func__, 1, &(client)->clientaddr, get_destaddr(client), prio, ## msg) - - static void redudp_pkt_from_socks(int fd, short what, void *_arg); - static void redudp_drop_client(redudp_client *client); - static void redudp_fini_instance(redudp_instance *instance); - static int redudp_fini(); -+static int redudp_transparent(int fd); - - typedef struct redudp_expected_assoc_reply_t { - socks5_reply h; - socks5_addr_ipv4 ip; - } PACKED redudp_expected_assoc_reply; - -+struct bound_udp4_key { -+ struct in_addr sin_addr; -+ uint16_t sin_port; -+}; -+ -+struct bound_udp4 { -+ struct bound_udp4_key key; -+ int ref; -+ int fd; -+}; -+ - /*********************************************************************** - * Helpers - */ -+// TODO: separate binding to privileged process (this operation requires uid-0) -+static void* root_bound_udp4 = NULL; // to avoid two binds to same IP:port -+ -+static int bound_udp4_cmp(const void *a, const void *b) -+{ -+ return memcmp(a, b, sizeof(struct bound_udp4_key)); -+} -+ -+static void bound_udp4_mkkey(struct bound_udp4_key *key, const struct sockaddr_in *addr) -+{ -+ memset(key, 0, sizeof(*key)); -+ key->sin_addr = addr->sin_addr; -+ key->sin_port = addr->sin_port; -+} -+ -+static int bound_udp4_get(const struct sockaddr_in *addr) -+{ -+ struct bound_udp4_key key; -+ struct bound_udp4 *node, **pnode; -+ -+ bound_udp4_mkkey(&key, addr); -+ // I assume, that memory allocation for lookup is awful, so I use -+ // tfind/tsearch pair instead of tsearch/check-result. -+ pnode = tfind(&key, &root_bound_udp4, bound_udp4_cmp); -+ if (pnode) { -+ assert((*pnode)->ref > 0); -+ (*pnode)->ref++; -+ return (*pnode)->fd; -+ } -+ -+ node = calloc(1, sizeof(*node)); -+ if (!node) { -+ log_errno(LOG_ERR, "calloc"); -+ goto fail; -+ } -+ -+ node->key = key; -+ node->ref = 1; -+ node->fd = socket(AF_INET, SOCK_DGRAM, 0); -+ if (node->fd == -1) { -+ log_errno(LOG_ERR, "socket"); -+ goto fail; -+ } -+ -+ if (0 != redudp_transparent(node->fd)) -+ goto fail; -+ -+ if (0 != bind(node->fd, (struct sockaddr*)addr, sizeof(*addr))) { -+ log_errno(LOG_ERR, "bind"); -+ goto fail; -+ } -+ -+ pnode = tsearch(node, &root_bound_udp4, bound_udp4_cmp); -+ if (!pnode) { -+ log_errno(LOG_ERR, "tsearch(%p) == %p", node, pnode); -+ goto fail; -+ } -+ assert(node == *pnode); -+ -+ return node->fd; -+ -+fail: -+ if (node) { -+ if (node->fd != -1) -+ redsocks_close(node->fd); -+ free(node); -+ } -+ return -1; -+} -+ -+static void bound_udp4_put(const struct sockaddr_in *addr) -+{ -+ struct bound_udp4_key key; -+ struct bound_udp4 **pnode, *node; -+ void *parent; -+ -+ bound_udp4_mkkey(&key, addr); -+ pnode = tfind(&key, &root_bound_udp4, bound_udp4_cmp); -+ assert(pnode && (*pnode)->ref > 0); -+ -+ node = *pnode; -+ -+ node->ref--; -+ if (node->ref) -+ return; -+ -+ parent = tdelete(node, &root_bound_udp4, bound_udp4_cmp); -+ assert(parent); -+ -+ redsocks_close(node->fd); // expanding `pnode` to avoid use after free -+ free(node); -+} -+ -+static int redudp_transparent(int fd) -+{ -+ int on = 1; -+ int error = setsockopt(fd, SOL_IP, IP_TRANSPARENT, &on, sizeof(on)); -+ if (error) -+ log_errno(LOG_ERR, "setsockopt(..., SOL_IP, IP_TRANSPARENT)"); -+ return error; -+} -+ -+static int do_tproxy(redudp_instance* instance) -+{ -+ return instance->config.destaddr.sin_addr.s_addr == 0; -+} -+ -+static struct sockaddr_in* get_destaddr(redudp_client *client) -+{ -+ if (do_tproxy(client->instance)) -+ return &client->destaddr; -+ else -+ return &client->instance->config.destaddr; -+} -+ - static void redudp_fill_preamble(socks5_udp_preabmle *preamble, redudp_client *client) - { - preamble->reserved = 0; - preamble->frag_no = 0; /* fragmentation is not supported */ - preamble->addrtype = socks5_addrtype_ipv4; -- preamble->ip.addr = client->instance->config.destaddr.sin_addr.s_addr; -- preamble->ip.port = client->instance->config.destaddr.sin_port; -+ preamble->ip.addr = get_destaddr(client)->sin_addr.s_addr; -+ preamble->ip.port = get_destaddr(client)->sin_port; - } - - static struct evbuffer* socks5_mkmethods_plain_wrapper(void *p) -@@ -104,6 +232,8 @@ static void redudp_drop_client(redudp_client *client) - redudp_log_errno(client, LOG_ERR, "event_del"); - redsocks_close(fd); - } -+ if (client->sender_fd != -1) -+ bound_udp4_put(&client->destaddr); - list_for_each_entry_safe(q, tmp, &client->queue, list) { - list_del(&q->list); - free(q); -@@ -344,7 +474,8 @@ static void redudp_relay_connected(struct bufferevent *buffev, void *_arg) - redudp_client *client = _arg; - int do_password = socks5_is_valid_cred(client->instance->config.login, client->instance->config.password); - int error; -- redudp_log_error(client, LOG_DEBUG, ""); -+ char relayaddr_str[RED_INET_ADDRSTRLEN]; -+ redudp_log_error(client, LOG_DEBUG, "via %s", red_inet_ntop(&client->instance->config.relayaddr, relayaddr_str, sizeof(relayaddr_str))); - - if (!red_is_socket_connected_ok(buffev)) { - redudp_log_errno(client, LOG_NOTICE, "red_is_socket_connected_ok"); -@@ -382,7 +513,7 @@ static void redudp_timeout(int fd, short what, void *_arg) - redudp_drop_client(client); - } - --static void redudp_first_pkt_from_client(redudp_instance *self, struct sockaddr_in *clientaddr, char *buf, size_t pktlen) -+static void redudp_first_pkt_from_client(redudp_instance *self, struct sockaddr_in *clientaddr, struct sockaddr_in *destaddr, char *buf, size_t pktlen) - { - redudp_client *client = calloc(1, sizeof(*client)); - -@@ -395,9 +526,13 @@ static void redudp_first_pkt_from_client(redudp_instance *self, struct sockaddr_ - INIT_LIST_HEAD(&client->queue); - client->instance = self; - memcpy(&client->clientaddr, clientaddr, sizeof(*clientaddr)); -+ if (destaddr) -+ memcpy(&client->destaddr, destaddr, sizeof(client->destaddr)); - evtimer_set(&client->timeout, redudp_timeout, client); - // XXX: self->relay_ss->init(client); - -+ client->sender_fd = -1; // it's postponed until socks-server replies to avoid trivial DoS -+ - client->relay = red_connect_relay(&client->instance->config.relayaddr, - redudp_relay_connected, redudp_relay_error, client); - if (!client->relay) -@@ -431,7 +566,7 @@ static void redudp_pkt_from_socks(int fd, short what, void *_arg) - - assert(fd == EVENT_FD(&client->udprelay)); - -- pktlen = red_recv_udp_pkt(fd, pkt.buf, sizeof(pkt.buf), &udprelayaddr); -+ pktlen = red_recv_udp_pkt(fd, pkt.buf, sizeof(pkt.buf), &udprelayaddr, NULL); - if (pktlen == -1) - return; - -@@ -455,8 +590,8 @@ static void redudp_pkt_from_socks(int fd, short what, void *_arg) - return; - } - -- if (pkt.header.ip.port != client->instance->config.destaddr.sin_port || -- pkt.header.ip.addr != client->instance->config.destaddr.sin_addr.s_addr) -+ if (pkt.header.ip.port != get_destaddr(client)->sin_port || -+ pkt.header.ip.addr != get_destaddr(client)->sin_addr.s_addr) - { - char buf[RED_INET_ADDRSTRLEN]; - struct sockaddr_in pktaddr = { -@@ -472,8 +607,18 @@ static void redudp_pkt_from_socks(int fd, short what, void *_arg) - redsocks_time(&client->last_relay_event); - redudp_bump_timeout(client); - -+ if (do_tproxy(client->instance) && client->sender_fd == -1) { -+ client->sender_fd = bound_udp4_get(&client->destaddr); -+ if (client->sender_fd == -1) { -+ redudp_log_error(client, LOG_WARNING, "bound_udp4_get failure"); -+ return; -+ } -+ } -+ - fwdlen = pktlen - sizeof(pkt.header); -- outgoing = sendto(EVENT_FD(&client->instance->listener), -+ outgoing = sendto(do_tproxy(client->instance) -+ ? client->sender_fd -+ : EVENT_FD(&client->instance->listener), - pkt.buf + sizeof(pkt.header), fwdlen, 0, - (struct sockaddr*)&client->clientaddr, sizeof(client->clientaddr)); - if (outgoing != fwdlen) { -@@ -486,18 +631,21 @@ static void redudp_pkt_from_socks(int fd, short what, void *_arg) - static void redudp_pkt_from_client(int fd, short what, void *_arg) - { - redudp_instance *self = _arg; -- struct sockaddr_in clientaddr; -+ struct sockaddr_in clientaddr, destaddr, *pdestaddr; - char buf[0xFFFF]; // UDP packet can't be larger then that - ssize_t pktlen; - redudp_client *tmp, *client = NULL; - -+ pdestaddr = do_tproxy(self) ? &destaddr : NULL; -+ - assert(fd == EVENT_FD(&self->listener)); -- pktlen = red_recv_udp_pkt(fd, buf, sizeof(buf), &clientaddr); -+ pktlen = red_recv_udp_pkt(fd, buf, sizeof(buf), &clientaddr, pdestaddr); - if (pktlen == -1) - return; - - // TODO: this lookup may be SLOOOOOW. - list_for_each_entry(tmp, &self->clients, list) { -+ // TODO: check destaddr - if (0 == memcmp(&clientaddr, &tmp->clientaddr, sizeof(clientaddr))) { - client = tmp; - break; -@@ -515,7 +663,7 @@ static void redudp_pkt_from_client(int fd, short what, void *_arg) - } - } - else { -- redudp_first_pkt_from_client(self, &clientaddr, buf, pktlen); -+ redudp_first_pkt_from_client(self, &clientaddr, pdestaddr, buf, pktlen); - } - } - -@@ -554,7 +702,6 @@ static int redudp_onenter(parser_section *section) - instance->config.relayaddr.sin_family = AF_INET; - instance->config.relayaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - instance->config.destaddr.sin_family = AF_INET; -- instance->config.destaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - instance->config.max_pktqueue = 5; - instance->config.udp_timeout = 30; - instance->config.udp_timeout_stream = 180; -@@ -614,6 +761,28 @@ static int redudp_init_instance(redudp_instance *instance) - goto fail; - } - -+ if (do_tproxy(instance)) { -+ int on = 1; -+ char buf[RED_INET_ADDRSTRLEN]; -+ // iptables TPROXY target does not send packets to non-transparent sockets -+ if (0 != redudp_transparent(fd)) -+ goto fail; -+ -+ error = setsockopt(fd, SOL_IP, IP_RECVORIGDSTADDR, &on, sizeof(on)); -+ if (error) { -+ log_errno(LOG_ERR, "setsockopt(listener, SOL_IP, IP_RECVORIGDSTADDR)"); -+ goto fail; -+ } -+ -+ log_error(LOG_DEBUG, "redudp @ %s: TPROXY", red_inet_ntop(&instance->config.bindaddr, buf, sizeof(buf))); -+ } -+ else { -+ char buf1[RED_INET_ADDRSTRLEN], buf2[RED_INET_ADDRSTRLEN]; -+ log_error(LOG_DEBUG, "redudp @ %s: destaddr=%s", -+ red_inet_ntop(&instance->config.bindaddr, buf1, sizeof(buf1)), -+ red_inet_ntop(&instance->config.destaddr, buf2, sizeof(buf2))); -+ } -+ - error = bind(fd, (struct sockaddr*)&instance->config.bindaddr, sizeof(instance->config.bindaddr)); - if (error) { - log_errno(LOG_ERR, "bind"); -diff --git a/redudp.h b/redudp.h -index 308bd33..3f1d9d1 100644 ---- a/redudp.h -+++ b/redudp.h -@@ -24,6 +24,8 @@ typedef struct redudp_client_t { - list_head list; - redudp_instance *instance; - struct sockaddr_in clientaddr; -+ struct sockaddr_in destaddr; -+ int sender_fd; // shared between several clients socket (bound to `destaddr`) - struct event timeout; - struct bufferevent *relay; - struct event udprelay; -diff --git a/utils.c b/utils.c -index 6e1f3af..afdeea8 100644 ---- a/utils.c -+++ b/utils.c -@@ -26,17 +26,54 @@ - #include "utils.h" - #include "redsocks.h" // for redsocks_close - --int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inaddr) -+int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inaddr, struct sockaddr_in *toaddr) - { - socklen_t addrlen = sizeof(*inaddr); - ssize_t pktlen; -- -- pktlen = recvfrom(fd, buf, buflen, 0, (struct sockaddr*)inaddr, &addrlen); -+ struct msghdr msg; -+ struct iovec io; -+ char control[1024]; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.msg_name = inaddr; -+ msg.msg_namelen = sizeof(*inaddr); -+ msg.msg_iov = &io; -+ msg.msg_iovlen = 1; -+ msg.msg_control = control; -+ msg.msg_controllen = sizeof(control); -+ io.iov_base = buf; -+ io.iov_len = buflen; -+ -+ pktlen = recvmsg(fd, &msg, 0); - if (pktlen == -1) { - log_errno(LOG_WARNING, "recvfrom"); - return -1; - } - -+ if (toaddr) { -+ memset(toaddr, 0, sizeof(*toaddr)); -+ for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { -+ if ( -+ cmsg->cmsg_level == SOL_IP && -+ cmsg->cmsg_type == IP_ORIGDSTADDR && -+ cmsg->cmsg_len >= CMSG_LEN(sizeof(*toaddr)) -+ ) { -+ struct sockaddr_in* cmsgaddr = (struct sockaddr_in*)CMSG_DATA(cmsg); -+ char buf[RED_INET_ADDRSTRLEN]; -+ log_error(LOG_DEBUG, "IP_ORIGDSTADDR: %s", red_inet_ntop(cmsgaddr, buf, sizeof(buf))); -+ memcpy(toaddr, cmsgaddr, sizeof(*toaddr)); -+ } -+ else { -+ log_error(LOG_WARNING, "unexepcted cmsg (level,type) = (%d,%d)", -+ cmsg->cmsg_level, cmsg->cmsg_type); -+ } -+ } -+ if (toaddr->sin_family != AF_INET) { -+ log_error(LOG_WARNING, "(SOL_IP, IP_ORIGDSTADDR) not found"); -+ return -1; -+ } -+ } -+ - if (addrlen != sizeof(*inaddr)) { - log_error(LOG_WARNING, "unexpected address length %u instead of %zu", addrlen, sizeof(*inaddr)); - return -1; -diff --git a/utils.h b/utils.h -index d3af00f..c2277e9 100644 ---- a/utils.h -+++ b/utils.h -@@ -44,7 +44,7 @@ char *redsocks_evbuffer_readline(struct evbuffer *buf); - struct bufferevent* red_connect_relay(struct sockaddr_in *addr, evbuffercb writecb, everrorcb errorcb, void *cbarg); - int red_socket_geterrno(struct bufferevent *buffev); - int red_is_socket_connected_ok(struct bufferevent *buffev); --int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inaddr); -+int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *fromaddr, struct sockaddr_in *toaddr); - - int fcntl_nonblock(int fd); - --- -1.9.1 - diff --git a/net/redsocks/patches/0004-Fix-transposition-of-memset-parameters.patch b/net/redsocks/patches/0004-Fix-transposition-of-memset-parameters.patch deleted file mode 100644 index cb6fa1e4c1..0000000000 --- a/net/redsocks/patches/0004-Fix-transposition-of-memset-parameters.patch +++ /dev/null @@ -1,25 +0,0 @@ -From b60b492602448b59aea194afd4991910d3613e5c Mon Sep 17 00:00:00 2001 -From: Cody Schafer -Date: Tue, 24 Apr 2012 04:33:13 -0500 -Subject: [PATCH 04/12] Fix transposition of memset parameters. - ---- - utils.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/utils.c b/utils.c -index afdeea8..31c6894 100644 ---- a/utils.c -+++ b/utils.c -@@ -222,7 +222,7 @@ char *red_inet_ntop(const struct sockaddr_in* sa, char* buffer, size_t buffer_si - - assert(buffer_size >= sizeof(placeholder)); - -- memset(buffer, buffer_size, 0); -+ memset(buffer, 0, buffer_size); - if (sa->sin_family == AF_INET) { - retval = inet_ntop(AF_INET, &sa->sin_addr, buffer, buffer_size); - port = ((struct sockaddr_in*)sa)->sin_port; --- -1.9.1 - diff --git a/net/redsocks/patches/0005-Fix-compilation-on-Ubuntu-10.04-LTS-and-hopefully-De.patch b/net/redsocks/patches/0005-Fix-compilation-on-Ubuntu-10.04-LTS-and-hopefully-De.patch deleted file mode 100644 index f0f09aa543..0000000000 --- a/net/redsocks/patches/0005-Fix-compilation-on-Ubuntu-10.04-LTS-and-hopefully-De.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 18e2b5ed1ffb3e7c5dfec8ff41b3027163f680ed Mon Sep 17 00:00:00 2001 -From: Leonid Evdokimov -Date: Wed, 12 Sep 2012 02:05:39 +0400 -Subject: [PATCH 09/12] Fix compilation on Ubuntu 10.04 LTS and (hopefully) - Debian squeeze[1] - -fixes #28, fixes #22, fixes #24 -[1] current "stable" release ---- - libc-compat.h | 25 +++++++++++++++++++++++++ - libevent-compat.h | 11 +++++++++++ - redsocks.c | 1 + - redudp.c | 1 + - utils.c | 1 + - 5 files changed, 39 insertions(+) - create mode 100644 libc-compat.h - create mode 100644 libevent-compat.h - -diff --git a/libc-compat.h b/libc-compat.h -new file mode 100644 -index 0000000..adcf63b ---- /dev/null -+++ b/libc-compat.h -@@ -0,0 +1,25 @@ -+#ifndef UUID_67C91670_FCCB_4855_BDF7_609F1EECB8B4 -+#define UUID_67C91670_FCCB_4855_BDF7_609F1EECB8B4 -+ -+/* all these definitions, are included into bits/in.h from libc6-dev 2.15-0ubuntu10 -+ * from Ubuntu 12.04 and is not included into libc6-dev 2.11.1-0ubuntu7.10 from -+ * Ubuntu 10.04. -+ * linux/in.h is not included directly because of lots of redefinitions, -+ * extracting single value from linux/in.h is not done because it looks like -+ * autotools reinvention */ -+#ifndef IP_ORIGDSTADDR -+# warning Using hardcoded value for IP_ORIGDSTADDR as libc headers do not define it. -+# define IP_ORIGDSTADDR 20 -+#endif -+ -+#ifndef IP_RECVORIGDSTADDR -+# warning Using hardcoded value for IP_RECVORIGDSTADDR as libc headers do not define it. -+# define IP_RECVORIGDSTADDR IP_ORIGDSTADDR -+#endif -+ -+#ifndef IP_TRANSPARENT -+# warning Using hardcoded value for IP_TRANSPARENT as libc headers do not define it. -+# define IP_TRANSPARENT 19 -+#endif -+ -+#endif // 67C91670_FCCB_4855_BDF7_609F1EECB8B4 -diff --git a/libevent-compat.h b/libevent-compat.h -new file mode 100644 -index 0000000..a7f1ca1 ---- /dev/null -+++ b/libevent-compat.h -@@ -0,0 +1,11 @@ -+#ifndef UUID_FC148CFA_5ECC_488E_8A62_CD39406C9F1E -+#define UUID_FC148CFA_5ECC_488E_8A62_CD39406C9F1E -+ -+/* evutil_socket_t is macros in libevent-2.0, not typedef, libevent-1.4 is -+ * still supported because of Ubuntu 10.04 LTS */ -+#ifndef evutil_socket_t -+# warning Using hardcoded value for evutil_socket_t as libevent headers do not define it. -+# define evutil_socket_t int -+#endif -+ -+#endif // FC148CFA_5ECC_488E_8A62_CD39406C9F1E -diff --git a/redsocks.c b/redsocks.c -index ba5eab2..878576f 100644 ---- a/redsocks.c -+++ b/redsocks.c -@@ -33,6 +33,7 @@ - #include "base.h" - #include "redsocks.h" - #include "utils.h" -+#include "libevent-compat.h" - - - #define REDSOCKS_RELAY_HALFBUFF 4096 -diff --git a/redudp.c b/redudp.c -index 262af3e..05460dc 100644 ---- a/redudp.c -+++ b/redudp.c -@@ -32,6 +32,7 @@ - #include "main.h" - #include "redsocks.h" - #include "redudp.h" -+#include "libc-compat.h" - - #define redudp_log_error(client, prio, msg...) \ - redsocks_log_write_plain(__FILE__, __LINE__, __func__, 0, &(client)->clientaddr, get_destaddr(client), prio, ## msg) -diff --git a/utils.c b/utils.c -index 31c6894..7de3969 100644 ---- a/utils.c -+++ b/utils.c -@@ -25,6 +25,7 @@ - #include "log.h" - #include "utils.h" - #include "redsocks.h" // for redsocks_close -+#include "libc-compat.h" - - int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inaddr, struct sockaddr_in *toaddr) - { --- -1.9.1 - diff --git a/net/redsocks/patches/0006-fix_default_config_location.patch b/net/redsocks/patches/0006-fix_default_config_location.patch index 1994befa6c..987085f0dd 100644 --- a/net/redsocks/patches/0006-fix_default_config_location.patch +++ b/net/redsocks/patches/0006-fix_default_config_location.patch @@ -6,7 +6,7 @@ Forwared: no Last-Update: 2013-04-23 --- a/main.c +++ b/main.c -@@ -39,7 +39,7 @@ +@@ -39,7 +39,7 @@ app_subsys *subsystems[] = { &dnstc_subsys, };