Added support for authenticated proxy upstream

This commit is contained in:
goba62000374 2017-06-10 14:47:15 +01:00
parent cb6f868739
commit 902d5e4698
5 changed files with 119 additions and 12 deletions

View File

@ -158,6 +158,9 @@ LogLevel Info
# # default upstream is internet firewall # # default upstream is internet firewall
# upstream firewall.internal.example.com:80 # upstream firewall.internal.example.com:80
# #
# # connection through testproxy with authentication
# upstream user:password@testproxy:8008 ".test.domain.invalid"
#
# The LAST matching rule wins the route decision. As you can see, you # The LAST matching rule wins the route decision. As you can see, you
# can use a host, or a domain: # can use a host, or a domain:
# name matches host exactly # name matches host exactly

View File

@ -47,6 +47,7 @@
* given directive. * given directive.
*/ */
#define WS "[[:space:]]+" #define WS "[[:space:]]+"
#define ANY "(.+)"
#define STR "\"([^\"]+)\"" #define STR "\"([^\"]+)\""
#define BOOL "(yes|on|no|off)" #define BOOL "(yes|on|no|off)"
#define INT "((0x)?[[:digit:]]+)" #define INT "((0x)?[[:digit:]]+)"
@ -160,6 +161,7 @@ static HANDLE_FUNC (handle_xtinyproxy);
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
static HANDLE_FUNC (handle_upstream); static HANDLE_FUNC (handle_upstream);
static HANDLE_FUNC (handle_upstream_auth);
static HANDLE_FUNC (handle_upstream_no); static HANDLE_FUNC (handle_upstream_no);
#endif #endif
@ -257,6 +259,10 @@ struct {
BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR
")?" END, handle_upstream, NULL ")?" END, handle_upstream, NULL
}, },
{
BEGIN "(upstream)" WS ALNUM ":" ANY "@(" IP "|" ALNUM ")" ":" INT "(" WS STR
")?" END, handle_upstream_auth, NULL
},
#endif #endif
/* loglevel */ /* loglevel */
STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)", STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)",
@ -1084,11 +1090,41 @@ static HANDLE_FUNC (handle_upstream)
if (match[10].rm_so != -1) { if (match[10].rm_so != -1) {
domain = get_string_arg (line, &match[10]); domain = get_string_arg (line, &match[10]);
if (domain) { if (domain) {
upstream_add (ip, port, domain, &conf->upstream_list); upstream_add (NULL, NULL, ip, port, domain, &conf->upstream_list);
safefree (domain); safefree (domain);
} }
} else { } else {
upstream_add (ip, port, NULL, &conf->upstream_list); upstream_add (NULL, NULL, ip, port, NULL, &conf->upstream_list);
}
safefree (ip);
return 0;
}
static HANDLE_FUNC (handle_upstream_auth)
{
char *user;
char *pass;
char *ip;
int port;
char *domain;
ip = get_string_arg (line, &match[4]);
if (!ip)
return -1;
user = get_string_arg (line, &match[2]);
pass = get_string_arg (line, &match[3]);
port = (int) get_long_arg (line, &match[9]);
if (match[10].rm_so != -1) {
domain = get_string_arg (line, &match[12]);
if (domain) {
upstream_add (user, pass, ip, port, domain, &conf->upstream_list);
safefree (domain);
}
} else {
upstream_add (user, pass, ip, port, NULL, &conf->upstream_list);
} }
safefree (ip); safefree (ip);
@ -1104,7 +1140,7 @@ static HANDLE_FUNC (handle_upstream_no)
if (!domain) if (!domain)
return -1; return -1;
upstream_add (NULL, 0, domain, &conf->upstream_list); upstream_add (NULL, NULL, NULL, 0, domain, &conf->upstream_list);
safefree (domain); safefree (domain);
return 0; return 0;

View File

@ -61,6 +61,41 @@
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
# define UPSTREAM_CONFIGURED() (config.upstream_list != NULL) # define UPSTREAM_CONFIGURED() (config.upstream_list != NULL)
# define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list) # define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list)
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void encode_base_64(char* src, char* dest, int max_len) {
int n, l, i;
l = strlen(src);
max_len = (max_len - 1) / 4;
for (i = 0; i < max_len; i++, src += 3, l -= 3) {
switch (l) {
case 0:
break;
case 1:
n = src[0] << 16;
*dest++ = base64[(n >> 18) & 077];
*dest++ = base64[(n >> 12) & 077];
*dest++ = '=';
*dest++ = '=';
break;
case 2:
n = src[0] << 16 | src[1] << 8;
*dest++ = base64[(n >> 18) & 077];
*dest++ = base64[(n >> 12) & 077];
*dest++ = base64[(n >> 6) & 077];
*dest++ = '=';
break;
default:
n = src[0] << 16 | src[1] << 8 | src[2];
*dest++ = base64[(n >> 18) & 077];
*dest++ = base64[(n >> 12) & 077];
*dest++ = base64[(n >> 6) & 077];
*dest++ = base64[n & 077];
}
if (l < 3) break;
}
*dest++ = 0;
}
#else #else
# define UPSTREAM_CONFIGURED() (0) # define UPSTREAM_CONFIGURED() (0)
# define UPSTREAM_HOST(host) (NULL) # define UPSTREAM_HOST(host) (NULL)
@ -1498,6 +1533,22 @@ void handle_connection (int fd)
connptr->upstream_proxy = UPSTREAM_HOST (request->host); connptr->upstream_proxy = UPSTREAM_HOST (request->host);
if (connptr->upstream_proxy != NULL) { if (connptr->upstream_proxy != NULL) {
if (connptr->upstream_proxy->user)
{
char proxy_auth[200] = "";
char src[256];
char dst2[512];
strcpy(src, connptr->upstream_proxy->user);
strcat(src, ":");
strcat(src, connptr->upstream_proxy->pass);
encode_base_64(src, dst2, 512);
strcat(proxy_auth, "Basic ");
strcat(proxy_auth, dst2);
hashmap_insert (hashofheaders,
"Proxy-Authorization",
proxy_auth, strlen (proxy_auth) + 1);
}
if (connect_to_upstream (connptr, request) < 0) { if (connect_to_upstream (connptr, request) < 0) {
goto fail; goto fail;
} }

View File

@ -32,7 +32,7 @@
/** /**
* Construct an upstream struct from input data. * Construct an upstream struct from input data.
*/ */
static struct upstream *upstream_build (const char *host, int port, const char *domain) static struct upstream *upstream_build (const char *user, const char *pass, const char *host, int port, const char *domain)
{ {
char *ptr; char *ptr;
struct upstream *up; struct upstream *up;
@ -44,9 +44,18 @@ static struct upstream *upstream_build (const char *host, int port, const char *
return NULL; return NULL;
} }
up->host = up->domain = NULL; up->user = up->pass = up->host = up->domain = NULL;
up->ip = up->mask = 0; up->ip = up->mask = 0;
if (user != NULL) {
up->user = safestrdup(user);
}
if (pass != NULL) {
up->pass = safestrdup(pass);
}
if (domain == NULL) { if (domain == NULL) {
if (!host || host[0] == '\0' || port < 1) { if (!host || host[0] == '\0' || port < 1) {
log_message (LOG_WARNING, log_message (LOG_WARNING,
@ -57,8 +66,8 @@ static struct upstream *upstream_build (const char *host, int port, const char *
up->host = safestrdup (host); up->host = safestrdup (host);
up->port = port; up->port = port;
log_message (LOG_INFO, "Added upstream %s:%d for [default]", log_message (LOG_INFO, "Added upstream %s:<hidden>@%s:%d for [default]",
host, port); user, host, port);
} else if (host == NULL) { } else if (host == NULL) {
if (!domain || domain[0] == '\0') { if (!domain || domain[0] == '\0') {
log_message (LOG_WARNING, log_message (LOG_WARNING,
@ -101,13 +110,15 @@ static struct upstream *upstream_build (const char *host, int port, const char *
up->port = port; up->port = port;
up->domain = safestrdup (domain); up->domain = safestrdup (domain);
log_message (LOG_INFO, "Added upstream %s:%d for %s", log_message (LOG_INFO, "Added upstream %s:<hidden>@%s:%d for %s",
host, port, domain); user, host, port, domain);
} }
return up; return up;
fail: fail:
safefree (up->user);
safefree (up->pass);
safefree (up->host); safefree (up->host);
safefree (up->domain); safefree (up->domain);
safefree (up); safefree (up);
@ -118,12 +129,12 @@ fail:
/* /*
* Add an entry to the upstream list * Add an entry to the upstream list
*/ */
void upstream_add (const char *host, int port, const char *domain, void upstream_add (const char *user, const char *pass, const char *host, int port, const char *domain,
struct upstream **upstream_list) struct upstream **upstream_list)
{ {
struct upstream *up; struct upstream *up;
up = upstream_build (host, port, domain); up = upstream_build (user, pass, host, port, domain);
if (up == NULL) { if (up == NULL) {
return; return;
} }
@ -154,6 +165,8 @@ void upstream_add (const char *host, int port, const char *domain,
return; return;
upstream_cleanup: upstream_cleanup:
safefree (up->user);
safefree (up->pass);
safefree (up->host); safefree (up->host);
safefree (up->domain); safefree (up->domain);
safefree (up); safefree (up);
@ -215,6 +228,8 @@ void free_upstream_list (struct upstream *up)
while (up) { while (up) {
struct upstream *tmp = up; struct upstream *tmp = up;
up = up->next; up = up->next;
safefree (tmp->user);
safefree (tmp->pass);
safefree (tmp->domain); safefree (tmp->domain);
safefree (tmp->host); safefree (tmp->host);
safefree (tmp); safefree (tmp);

View File

@ -35,12 +35,14 @@ struct upstream {
struct upstream *next; struct upstream *next;
char *domain; /* optional */ char *domain; /* optional */
char *host; char *host;
char *user;
char *pass;
int port; int port;
in_addr_t ip, mask; in_addr_t ip, mask;
}; };
#ifdef UPSTREAM_SUPPORT #ifdef UPSTREAM_SUPPORT
extern void upstream_add (const char *host, int port, const char *domain, extern void upstream_add (const char *user, const char *pass, const char *host, int port, const char *domain,
struct upstream **upstream_list); struct upstream **upstream_list);
extern struct upstream *upstream_get (char *host, struct upstream *up); extern struct upstream *upstream_get (char *host, struct upstream *up);
extern void free_upstream_list (struct upstream *up); extern void free_upstream_list (struct upstream *up);