Improved the upstream proxy support by making the upstream proxy
server configurable based on the destination host. [Code written by Peter da Silva]
This commit is contained in:
parent
2e9f27769d
commit
4a377a712d
@ -92,6 +92,32 @@ PidFile "/var/run/tinyproxy.pid"
|
|||||||
#
|
#
|
||||||
# Turns on upstream proxy support.
|
# Turns on upstream proxy support.
|
||||||
#
|
#
|
||||||
|
# The upstream rules allow you to selectively route upstream connections
|
||||||
|
# based on the host/domain of the site being accessed.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
# # connection to test domain goes through testproxy
|
||||||
|
# upstream testproxy:8008 .test.domain.invalid
|
||||||
|
# upstream testproxy:8008 .our_testbed.example.com
|
||||||
|
#
|
||||||
|
# # no upstream proxy for internal websites and unqualified hosts
|
||||||
|
# no upstream .internal.example.com
|
||||||
|
# no upstream www.example.com
|
||||||
|
# no upstream .
|
||||||
|
#
|
||||||
|
# # connection to these boxes go through their DMZ firewalls
|
||||||
|
# upstream cust1_firewall:8008 testbed_for_cust1
|
||||||
|
# upstream cust2_firewall:8008 testbed_for_cust2
|
||||||
|
#
|
||||||
|
# # default upstream is internet firewall
|
||||||
|
# upstream firewall.internal.example.com:80
|
||||||
|
#
|
||||||
|
# The LAST matching rule wins the route decision. As you can see, you
|
||||||
|
# can use a host, or a domain:
|
||||||
|
# name matches host exactly
|
||||||
|
# .name matches any host in domain "name"
|
||||||
|
# . matches any host with no domain (in 'empty' domain)
|
||||||
|
#
|
||||||
#Upstream some.remote.proxy:port
|
#Upstream some.remote.proxy:port
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: grammar.y,v 1.20 2003-03-13 21:42:46 rjkaes Exp $
|
/* $Id: grammar.y,v 1.21 2003-05-29 19:43:58 rjkaes Exp $
|
||||||
*
|
*
|
||||||
* This is the grammar for tinyproxy's configuration file. It needs to be
|
* This is the grammar for tinyproxy's configuration file. It needs to be
|
||||||
* in sync with scanner.l. If you know more about yacc and lex than I do
|
* in sync with scanner.l. If you know more about yacc and lex than I do
|
||||||
@ -171,8 +171,23 @@ statement
|
|||||||
| KW_UPSTREAM unique_address ':' NUMBER
|
| KW_UPSTREAM unique_address ':' NUMBER
|
||||||
{
|
{
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
config.upstream_name = $2;
|
upstream_add($2, $4, NULL);
|
||||||
config.upstream_port = $4;
|
#else
|
||||||
|
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
| KW_UPSTREAM unique_address ':' NUMBER STRING
|
||||||
|
{
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
upstream_add($2, $4, $5);
|
||||||
|
#else
|
||||||
|
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
| KW_NO KW_UPSTREAM STRING
|
||||||
|
{
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
upstream_add(NULL, 0, $3);
|
||||||
#else
|
#else
|
||||||
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
|
log_message(LOG_WARNING, "Upstream proxy support was not compiled in.");
|
||||||
#endif
|
#endif
|
||||||
|
169
src/reqs.c
169
src/reqs.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: reqs.c,v 1.97 2003-05-05 16:46:05 rjkaes Exp $
|
/* $Id: reqs.c,v 1.98 2003-05-29 19:43:57 rjkaes Exp $
|
||||||
*
|
*
|
||||||
* This is where all the work in tinyproxy is actually done. Incoming
|
* This is where all the work in tinyproxy is actually done. Incoming
|
||||||
* connections have a new child created for them. The child then
|
* connections have a new child created for them. The child then
|
||||||
@ -57,9 +57,11 @@
|
|||||||
* enabled.
|
* enabled.
|
||||||
*/
|
*/
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
# define UPSTREAM_CONFIGURED() (config.upstream_name && config.upstream_port != -1)
|
# define UPSTREAM_CONFIGURED() (config.upstream_list != NULL)
|
||||||
|
# define UPSTREAM_HOST(host) upstream_get(host)
|
||||||
#else
|
#else
|
||||||
# define UPSTREAM_CONFIGURED() (0)
|
# define UPSTREAM_CONFIGURED() (0)
|
||||||
|
# define UPSTREAM_HOST(host) (NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -73,6 +75,19 @@
|
|||||||
*/
|
*/
|
||||||
static vector_t ports_allowed_by_connect = NULL;
|
static vector_t ports_allowed_by_connect = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure holds the information pulled from a URL request.
|
||||||
|
*/
|
||||||
|
struct request_s {
|
||||||
|
char *method;
|
||||||
|
char *protocol;
|
||||||
|
|
||||||
|
char *host;
|
||||||
|
uint16_t port;
|
||||||
|
|
||||||
|
char *path;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now, this routine adds a "port" to the list. It also creates the list if
|
* Now, this routine adds a "port" to the list. It also creates the list if
|
||||||
* it hasn't already by done.
|
* it hasn't already by done.
|
||||||
@ -163,18 +178,8 @@ read_request_line(struct conn_s *connptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure holds the information pulled from a URL request.
|
* Free all the memory allocated in a request.
|
||||||
*/
|
*/
|
||||||
struct request_s {
|
|
||||||
char *method;
|
|
||||||
char *protocol;
|
|
||||||
|
|
||||||
char *host;
|
|
||||||
uint16_t port;
|
|
||||||
|
|
||||||
char *path;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_request_struct(struct request_s *request)
|
free_request_struct(struct request_s *request)
|
||||||
{
|
{
|
||||||
@ -304,6 +309,129 @@ build_url(char **url, const char *host, int port, const char *path)
|
|||||||
}
|
}
|
||||||
#endif /* TRANSPARENT_PROXY */
|
#endif /* TRANSPARENT_PROXY */
|
||||||
|
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
/*
|
||||||
|
* Add an entry to the upstream list
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
upstream_add(const char *host, int port, const char *domain)
|
||||||
|
{
|
||||||
|
struct upstream *up = safemalloc(sizeof (struct upstream));
|
||||||
|
|
||||||
|
if (!up) {
|
||||||
|
log_message(LOG_WARNING,
|
||||||
|
"Could not allocate memory for upstream host configuration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domain && domain[0] != '\0')
|
||||||
|
up->domain = safestrdup(domain);
|
||||||
|
else
|
||||||
|
up->domain = NULL;
|
||||||
|
|
||||||
|
if (host && host[0] != '\0' && port > 0)
|
||||||
|
up->host = safestrdup(host);
|
||||||
|
else
|
||||||
|
up->host = NULL;
|
||||||
|
|
||||||
|
if (port > 0)
|
||||||
|
up->port = port;
|
||||||
|
else
|
||||||
|
up->port = 0;
|
||||||
|
|
||||||
|
if (host) {
|
||||||
|
log_message(LOG_INFO, "Adding upstream %s:%d for %s",
|
||||||
|
host, port, domain ? domain : "[default]");
|
||||||
|
} else if (domain) {
|
||||||
|
log_message(LOG_INFO, "Adding no-upstream for %s",
|
||||||
|
domain ? domain : "[default]");
|
||||||
|
} else {
|
||||||
|
log_message(LOG_WARNING,
|
||||||
|
"Nonsense upstream rule: no proxy or domain");
|
||||||
|
|
||||||
|
goto upstream_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!up->domain) {
|
||||||
|
/* always add default to end */
|
||||||
|
struct upstream *tmp = config.upstream_list;
|
||||||
|
|
||||||
|
while (tmp) {
|
||||||
|
if (!tmp->domain) {
|
||||||
|
log_message(LOG_WARNING,
|
||||||
|
"Duplicate default upstream");
|
||||||
|
|
||||||
|
goto upstream_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tmp->next) {
|
||||||
|
up->next = NULL;
|
||||||
|
tmp->next = up;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
up->next = config.upstream_list;
|
||||||
|
config.upstream_list = up;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
upstream_cleanup:
|
||||||
|
safefree(up->host);
|
||||||
|
safefree(up->domain);
|
||||||
|
safefree(up);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a host is in the upstream list
|
||||||
|
*/
|
||||||
|
static struct upstream *
|
||||||
|
upstream_get(char *host)
|
||||||
|
{
|
||||||
|
struct upstream *up = config.upstream_list;
|
||||||
|
|
||||||
|
while (up) {
|
||||||
|
if (!up->domain)
|
||||||
|
break; /* no domain, default, match */
|
||||||
|
|
||||||
|
if (strcasecmp(host, up->domain) == 0)
|
||||||
|
break; /* exact match */
|
||||||
|
|
||||||
|
if (up->domain[0] == '.') { /* domain starts with dot... */
|
||||||
|
char *dot = strchr(host, '.');
|
||||||
|
if (!dot && !up->domain[1])
|
||||||
|
break; /* domain exactly ".", host is local */
|
||||||
|
|
||||||
|
while (dot) {
|
||||||
|
if (strcasecmp(dot, up->domain) == 0)
|
||||||
|
break; /* subdomain match */
|
||||||
|
dot = strchr(dot+1, '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dot)
|
||||||
|
break; /* trailing part of domain matches */
|
||||||
|
}
|
||||||
|
|
||||||
|
up = up->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (up && (!up->host || !up->port))
|
||||||
|
up = NULL;
|
||||||
|
|
||||||
|
if (up)
|
||||||
|
log_message(LOG_INFO, "Found proxy %s:%d for %s",
|
||||||
|
up->host, up->port, host);
|
||||||
|
else
|
||||||
|
log_message(LOG_INFO, "No proxy for %s", host);
|
||||||
|
|
||||||
|
return up;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a connection for HTTP connections.
|
* Create a connection for HTTP connections.
|
||||||
*/
|
*/
|
||||||
@ -1249,8 +1377,17 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
|
|||||||
char *combined_string;
|
char *combined_string;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
struct upstream *cur_upstream = upstream_get(request->host);
|
||||||
|
if(!cur_upstream) {
|
||||||
|
log_message(LOG_WARNING,
|
||||||
|
"No upstream proxy defined for %s.",
|
||||||
|
request->host);
|
||||||
|
indicate_http_error(connptr, 404, "Unable to connect to upstream proxy.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
connptr->server_fd =
|
connptr->server_fd =
|
||||||
opensock(config.upstream_name, config.upstream_port);
|
opensock(cur_upstream->host, cur_upstream->port);
|
||||||
|
|
||||||
if (connptr->server_fd < 0) {
|
if (connptr->server_fd < 0) {
|
||||||
log_message(LOG_WARNING,
|
log_message(LOG_WARNING,
|
||||||
@ -1263,7 +1400,7 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
|
|||||||
|
|
||||||
log_message(LOG_CONN,
|
log_message(LOG_CONN,
|
||||||
"Established connection to upstream proxy \"%s\" using file descriptor %d.",
|
"Established connection to upstream proxy \"%s\" using file descriptor %d.",
|
||||||
config.upstream_name, connptr->server_fd);
|
cur_upstream->host, connptr->server_fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to re-write the "path" part of the request so that we
|
* We need to re-write the "path" part of the request so that we
|
||||||
@ -1383,7 +1520,7 @@ handle_connection(int fd)
|
|||||||
goto send_error;
|
goto send_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UPSTREAM_CONFIGURED()) {
|
if (UPSTREAM_CONFIGURED() && (UPSTREAM_HOST(request->host) != NULL)) {
|
||||||
if (connect_to_upstream(connptr, request) < 0) {
|
if (connect_to_upstream(connptr, request) < 0) {
|
||||||
goto send_error;
|
goto send_error;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: reqs.h,v 1.3 2002-04-12 17:00:42 rjkaes Exp $
|
/* $Id: reqs.h,v 1.4 2003-05-29 19:43:57 rjkaes Exp $
|
||||||
*
|
*
|
||||||
* See 'reqs.c' for a detailed description.
|
* See 'reqs.c' for a detailed description.
|
||||||
*
|
*
|
||||||
@ -21,5 +21,6 @@
|
|||||||
|
|
||||||
extern void handle_connection(int fd);
|
extern void handle_connection(int fd);
|
||||||
extern void add_connect_port_allowed(int port);
|
extern void add_connect_port_allowed(int port);
|
||||||
|
extern void upstream_add(const char *host, int port, const char *domain);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tinyproxy.h,v 1.38 2003-03-13 21:32:33 rjkaes Exp $
|
/* $Id: tinyproxy.h,v 1.39 2003-05-29 19:43:57 rjkaes Exp $
|
||||||
*
|
*
|
||||||
* See 'tinyproxy.c' for a detailed description.
|
* See 'tinyproxy.c' for a detailed description.
|
||||||
*
|
*
|
||||||
@ -25,6 +25,15 @@
|
|||||||
#define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */
|
#define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */
|
||||||
#define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */
|
#define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */
|
||||||
|
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
struct upstream {
|
||||||
|
struct upstream *next;
|
||||||
|
char *domain; /* optional */
|
||||||
|
char *host;
|
||||||
|
int port;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct config_s {
|
struct config_s {
|
||||||
char *logf_name;
|
char *logf_name;
|
||||||
char *config_file;
|
char *config_file;
|
||||||
@ -45,8 +54,7 @@ struct config_s {
|
|||||||
char *my_domain;
|
char *my_domain;
|
||||||
#endif
|
#endif
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
char *upstream_name;
|
struct upstream *upstream_list;
|
||||||
int upstream_port;
|
|
||||||
#endif /* UPSTREAM_SUPPORT */
|
#endif /* UPSTREAM_SUPPORT */
|
||||||
char *pidpath;
|
char *pidpath;
|
||||||
unsigned int idletimeout;
|
unsigned int idletimeout;
|
||||||
|
Loading…
Reference in New Issue
Block a user