From 02d426ef6bc3c8babb4535c9ef758cee8eadce39 Mon Sep 17 00:00:00 2001 From: Ben Sykes Date: Tue, 11 Jul 2017 13:58:42 -0700 Subject: [PATCH] Check for no_proxy environment variable and skip proxy if host is listed This will fix #9989, #11603, #11751. no_proxy is typically comma separated list of hosts and or domains. Matching must be from the end of the uri to accomodate whole domain and subdomain whitelisting. This will work for well-formed no_proxy strings, but may fail if there are additional spaces. --- .../ext/filters/client_channel/http_proxy.c | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/core/ext/filters/client_channel/http_proxy.c b/src/core/ext/filters/client_channel/http_proxy.c index cfb5ec6f00e..aa3f61c9917 100644 --- a/src/core/ext/filters/client_channel/http_proxy.c +++ b/src/core/ext/filters/client_channel/http_proxy.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -30,6 +31,7 @@ #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) { char* uri_str = gpr_getenv("http_proxy"); @@ -80,6 +82,50 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, grpc_uri_destroy(uri); return false; } + char* no_proxy_str = gpr_getenv("no_proxy"); + if (no_proxy_str != NULL) { + static const char* NO_PROXY_SEPARATOR = ","; + bool use_proxy = true; + char* server_host; + char* server_port; + if (!gpr_split_host_port(uri->path[0] == '/' ? uri->path + 1 : uri->path, + &server_host, &server_port)) { + gpr_log(GPR_INFO, + "unable to split host and port, not checking no_proxy list for " + "host '%s'", + server_uri); + } else { + size_t uri_len = strlen(server_host); + char** no_proxy_hosts; + size_t num_no_proxy_hosts; + gpr_string_split(no_proxy_str, NO_PROXY_SEPARATOR, &no_proxy_hosts, + &num_no_proxy_hosts); + for (size_t i = 0; i < num_no_proxy_hosts; i++) { + char* no_proxy_entry = no_proxy_hosts[i]; + size_t no_proxy_len = strlen(no_proxy_entry); + if (no_proxy_len <= uri_len && + gpr_stricmp(no_proxy_entry, &server_host[uri_len - no_proxy_len]) == + 0) { + gpr_log(GPR_INFO, "not using proxy for host in no_proxy list '%s'", + server_uri); + use_proxy = false; + break; + } + } + for (size_t i = 0; i < num_no_proxy_hosts; i++) { + gpr_free(no_proxy_hosts[i]); + } + gpr_free(no_proxy_hosts); + gpr_free(server_host); + gpr_free(server_port); + if (!use_proxy) { + grpc_uri_destroy(uri); + gpr_free(*name_to_resolve); + *name_to_resolve = NULL; + return false; + } + } + } grpc_arg new_arg = grpc_channel_arg_string_create( GRPC_ARG_HTTP_CONNECT_SERVER, uri->path[0] == '/' ? uri->path + 1 : uri->path);