From 2abda4c7643797bf148fb267da8cbe4032d9b659 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Fri, 6 Nov 2020 23:25:56 +0100 Subject: WIP: BindIPv4Mapped --- etc/tinyproxy.conf.in | 7 +++++++ src/conf-tokens.c | 3 ++- src/conf-tokens.h | 1 + src/conf.c | 8 ++++++++ src/conf.h | 1 + src/conns.c | 5 ++++- src/conns.h | 8 +++++++- src/reqs.c | 12 +++++++++--- src/sock.c | 15 +++++++++++++-- src/sock.h | 3 ++- 10 files changed, 54 insertions(+), 9 deletions(-) diff --git a/etc/tinyproxy.conf.in b/etc/tinyproxy.conf.in index 06f5480..5a170c2 100644 --- a/etc/tinyproxy.conf.in +++ b/etc/tinyproxy.conf.in @@ -42,6 +42,13 @@ Port 8888 # #BindSame yes +# +# BindIPv4Mapped: If enabled, tinyproxy will bind the outgoing IPv6 +# connection to the IPv4 address of the incoming connection using +# the mapping. +# +#BindIPv4Mapped 2001:0db8::ffff:0:0 + # # Timeout: The maximum number of seconds of inactivity a connection is # allowed to have before it is closed by tinyproxy. diff --git a/src/conf-tokens.c b/src/conf-tokens.c index bad7013..4ca38e3 100644 --- a/src/conf-tokens.c +++ b/src/conf-tokens.c @@ -57,7 +57,8 @@ config_directive_find (register const char *str, register size_t len) {"logfile", CD_logfile}, {"basicauth", CD_basicauth}, {"addheader", CD_addheader}, - {"maxrequestsperchild", CD_maxrequestsperchild} + {"maxrequestsperchild", CD_maxrequestsperchild}, + {"bindipv4mapped", CD_bindipv4mapped}, }; for(i=0;istathost); safefree (conf->user); safefree (conf->group); + safefree (conf->bind_ipv4mapped); stringlist_free(conf->basicauth_list); stringlist_free(conf->listen_addrs); stringlist_free(conf->bind_addrs); @@ -845,6 +848,11 @@ static HANDLE_FUNC (handle_listen) return 0; } +static HANDLE_FUNC (handle_bindipv4mapped) +{ + return set_string_arg(&conf->bind_ipv4mapped, line, &match[2]); +} + static HANDLE_FUNC (handle_errorfile) { /* diff --git a/src/conf.h b/src/conf.h index 9914049..a7c5a0c 100644 --- a/src/conf.h +++ b/src/conf.h @@ -70,6 +70,7 @@ struct config_s { unsigned int idletimeout; sblist *bind_addrs; unsigned int bindsame; + char *bind_ipv4mapped; /* * The configured name to use in the HTTP "Via" header field. diff --git a/src/conns.c b/src/conns.c index 19aaa49..921cdf6 100644 --- a/src/conns.c +++ b/src/conns.c @@ -39,7 +39,8 @@ void conn_struct_init(struct conn_s *connptr) { } int conn_init_contents (struct conn_s *connptr, const char *ipaddr, - const char *sock_ipaddr) + const char *sock_ipaddr, + const char *sock_ipaddr_mapped) { struct buffer_s *cbuffer, *sbuffer; @@ -59,6 +60,8 @@ int conn_init_contents (struct conn_s *connptr, const char *ipaddr, connptr->server_ip_addr = (sock_ipaddr ? safestrdup (sock_ipaddr) : NULL); + connptr->server_ip_addr_mapped = (sock_ipaddr_mapped ? + safestrdup (sock_ipaddr_mapped) : NULL); connptr->client_ip_addr = safestrdup (ipaddr); update_stats (STAT_OPEN); diff --git a/src/conns.h b/src/conns.h index 9618efb..c702fed 100644 --- a/src/conns.h +++ b/src/conns.h @@ -61,6 +61,11 @@ struct conn_s { */ char *server_ip_addr; + /* + * Store the server's mapped IP (for BindSame) + */ + char *server_ip_addr_mapped; + /* * Store the client's IP information */ @@ -93,7 +98,8 @@ extern void conn_struct_init(struct conn_s *connptr); /* second stage initializiation, sets up buffers and connection details */ extern int conn_init_contents (struct conn_s *connptr, const char *ipaddr, - const char *sock_ipaddr); + const char *sock_ipaddr, + const char *sock_ipaddr_mapped); extern void conn_destroy_contents (struct conn_s *connptr); #endif diff --git a/src/reqs.c b/src/reqs.c index 977af6b..f5c804a 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1381,7 +1381,7 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request) connptr->server_fd = opensock (cur_upstream->host, cur_upstream->port, - connptr->server_ip_addr); + connptr->server_ip_addr, NULL); if (connptr->server_fd < 0) { log_message (LOG_WARNING, @@ -1530,6 +1530,7 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) orderedmap hashofheaders = NULL; char sock_ipaddr[IP_LENGTH]; + char sock_ipaddr_mapped[IP_LENGTH]; char peer_ipaddr[IP_LENGTH]; getpeer_information (addr, peer_ipaddr, sizeof(peer_ipaddr)); @@ -1537,13 +1538,17 @@ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) if (config->bindsame) getsock_ip (fd, sock_ipaddr); + if (config->bind_ipv4mapped) + getmapped_ip (config->bind_ipv4mapped, sock_ipaddr, sock_ipaddr_mapped); + log_message (LOG_CONN, config->bindsame ? "Connect (file descriptor %d): %s at [%s]" : "Connect (file descriptor %d): %s", fd, peer_ipaddr, sock_ipaddr); if(!conn_init_contents (connptr, peer_ipaddr, - config->bindsame ? sock_ipaddr : NULL)) { + config->bindsame ? sock_ipaddr : NULL, + config->bind_ipv4mapped ? sock_ipaddr_mapped : NULL)) { close (fd); return; } @@ -1683,7 +1688,8 @@ e401: } } else { connptr->server_fd = opensock (request->host, request->port, - connptr->server_ip_addr); + connptr->server_ip_addr, + connptr->server_ip_addr_mapped); if (connptr->server_fd < 0) { indicate_http_error (connptr, 500, "Unable to connect", "detail", diff --git a/src/sock.c b/src/sock.c index 70169a6..f9d6a89 100644 --- a/src/sock.c +++ b/src/sock.c @@ -113,7 +113,7 @@ bind_socket_list (int sockfd, sblist *addresses, int family) * the getaddrinfo() library function, which allows for a protocol * independent implementation (mostly for IPv4 and IPv6 addresses.) */ -int opensock (const char *host, int port, const char *bind_to) +int opensock (const char *host, int port, const char *bind_to, const char *bind_to_alt) { int sockfd, n; struct addrinfo hints, *res, *ressave; @@ -151,7 +151,10 @@ int opensock (const char *host, int port, const char *bind_to) /* Bind to the specified address */ if (bind_to) { if (bind_socket (sockfd, bind_to, - res->ai_family) < 0) { + res->ai_family) < 0 && + (!bind_to_alt || + bind_socket (sockfd, bind_to_alt, + res->ai_family) < 0)) { close (sockfd); continue; /* can't bind, so try again */ } @@ -382,6 +385,14 @@ int getsock_ip (int fd, char *ipaddr) return 0; } +int getmapped_ip (const char *ipv4mapped_conf, const char *ipaddr, char *ipaddr_mapped) +{ + memset(ipaddr_mapped, 0, IP_LENGTH); + strncpy(ipaddr_mapped, ipv4mapped_conf, IP_LENGTH-1); + strncat(ipaddr_mapped, ipaddr, IP_LENGTH-1-strlen(ipaddr_mapped)); +} + + /* * Return the peer's socket information. */ diff --git a/src/sock.h b/src/sock.h index aee5bf5..15ab4df 100644 --- a/src/sock.h +++ b/src/sock.h @@ -50,13 +50,14 @@ union sockaddr_union { struct sockaddr_in6 v6; }; -extern int opensock (const char *host, int port, const char *bind_to); +extern int opensock (const char *host, int port, const char *bind_to, const char *bind_to_alt); extern int listen_sock (const char *addr, uint16_t port, sblist* listen_fds); extern int socket_nonblocking (int sock); extern int socket_blocking (int sock); extern int getsock_ip (int fd, char *ipaddr); +extern int getmapped_ip (const char *ipv4mapped_conf, const char *ipaddr, char *ipaddr_mapped); extern void getpeer_information (union sockaddr_union *addr, char *ipaddr, size_t ipaddr_len); #endif -- cgit v1.2.3