A bunch of changes from Petr Lampa that add transparent proxy support to tinyproxy. The additional code is in process_request(), but Petr also had to change around some of the other functions (like process_client_headers and handle_connection.) Note: Right now this code has not been tested, but it is believed to work. To enable run ./configure --enable-transparent-proxy
This commit is contained in:
parent
0242d89877
commit
f47685c861
125
src/reqs.c
125
src/reqs.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: reqs.c,v 1.81 2002-05-31 18:09:09 rjkaes Exp $
|
/* $Id: reqs.c,v 1.82 2002-06-06 20:32:30 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
|
||||||
@ -11,6 +11,7 @@
|
|||||||
* Copyright (C) 1998 Steven Young
|
* Copyright (C) 1998 Steven Young
|
||||||
* Copyright (C) 1999-2002 Robert James Kaes (rjkaes@flarenet.com)
|
* Copyright (C) 1999-2002 Robert James Kaes (rjkaes@flarenet.com)
|
||||||
* Copyright (C) 2000 Chris Lightfoot (chris@ex-parrot.com)
|
* Copyright (C) 2000 Chris Lightfoot (chris@ex-parrot.com)
|
||||||
|
* Copyright (C) 2002 Petr Lampa (lampa@fit.vutbr.cz)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@ -300,7 +301,7 @@ send_ssl_response(struct conn_s *connptr)
|
|||||||
* build a new request line. Finally connect to the remote server.
|
* build a new request line. Finally connect to the remote server.
|
||||||
*/
|
*/
|
||||||
static struct request_s *
|
static struct request_s *
|
||||||
process_request(struct conn_s *connptr)
|
process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
||||||
{
|
{
|
||||||
char *url;
|
char *url;
|
||||||
struct request_s *request;
|
struct request_s *request;
|
||||||
@ -397,6 +398,61 @@ process_request(struct conn_s *connptr)
|
|||||||
|
|
||||||
connptr->connect_method = TRUE;
|
connptr->connect_method = TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef TRANSPARENT_PROXY
|
||||||
|
/*
|
||||||
|
* This section of code is used for the transparent proxy
|
||||||
|
* option. You will need to configure your firewall to
|
||||||
|
* redirect all connections for HTTP traffic to tinyproxy
|
||||||
|
* for this to work properly.
|
||||||
|
*
|
||||||
|
* This code was written by Petr Lampa <lampa@fit.vutbr.cz>
|
||||||
|
*/
|
||||||
|
int length;
|
||||||
|
char *data;
|
||||||
|
length = hashmap_entry_by_key(hashofheaders, "host", (void **)&data);
|
||||||
|
if (length <= 0) {
|
||||||
|
struct sockaddr_in dest_addr;
|
||||||
|
|
||||||
|
if (getsockname(connptr->client_fd, (struct sockaddr *)&dest_addr, &length) < 0) {
|
||||||
|
log_message(LOG_ERR,
|
||||||
|
"process_request: cannot get destination IP for %d",
|
||||||
|
connptr->client_fd);
|
||||||
|
indicate_http_error(connptr, 400, "Bad Request. Unknown destination.");
|
||||||
|
safefree(url);
|
||||||
|
free_request_struct(request);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
request->host = safemalloc(17);
|
||||||
|
strcpy(request->host, inet_ntoa(dest_addr.sin_addr));
|
||||||
|
request->port = ntohs(dest_addr.sin_port);
|
||||||
|
request->path = safemalloc(strlen(url) + 1);
|
||||||
|
strcpy(request->path, url);
|
||||||
|
log_message(LOG_INFO,
|
||||||
|
"process_request: trans IP %s http://%s:%d%s for %d",
|
||||||
|
request->method, request->host, request->port, request->path, connptr->client_fd);
|
||||||
|
} else {
|
||||||
|
request->host = safemalloc(length+1);
|
||||||
|
if (sscanf(data, "%[^:]:%hu", request->host, &request->port) != 2) {
|
||||||
|
strcpy(request->host, data);
|
||||||
|
request->port = 80;
|
||||||
|
}
|
||||||
|
request->path = safemalloc(strlen(url) + 1);
|
||||||
|
strcpy(request->path, url);
|
||||||
|
log_message(LOG_INFO,
|
||||||
|
"process_request: trans Host %s http://%s:%d%s for %d",
|
||||||
|
request->method, request->host, request->port, request->path, connptr->client_fd);
|
||||||
|
}
|
||||||
|
if (config.ipAddr &&
|
||||||
|
strcmp(request->host, config.ipAddr) == 0) {
|
||||||
|
log_message(LOG_ERR,
|
||||||
|
"process_request: destination IP is localhost %d",
|
||||||
|
connptr->client_fd);
|
||||||
|
indicate_http_error(connptr, 400, "Bad Request. Bad destination.");
|
||||||
|
safefree(url);
|
||||||
|
free_request_struct(request);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
log_message(LOG_ERR,
|
log_message(LOG_ERR,
|
||||||
"process_request: Unknown URL type on file descriptor %d",
|
"process_request: Unknown URL type on file descriptor %d",
|
||||||
connptr->client_fd);
|
connptr->client_fd);
|
||||||
@ -406,6 +462,7 @@ process_request(struct conn_s *connptr)
|
|||||||
free_request_struct(request);
|
free_request_struct(request);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
@ -730,38 +787,26 @@ write_via_header(int fd, hashmap_t hashofheaders,
|
|||||||
* - rjkaes
|
* - rjkaes
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
process_client_headers(struct conn_s *connptr)
|
process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
|
||||||
{
|
{
|
||||||
static char *skipheaders[] = {
|
static char *skipheaders[] = {
|
||||||
"host",
|
"host",
|
||||||
"keep-alive",
|
"keep-alive",
|
||||||
"proxy-authenticate",
|
"proxy-authenticate",
|
||||||
"proxy-authorization",
|
"proxy-authorization",
|
||||||
|
"proxy-connection",
|
||||||
"te",
|
"te",
|
||||||
"trailers",
|
"trailers",
|
||||||
"transfer-encoding",
|
"transfer-encoding",
|
||||||
"upgrade"
|
"upgrade"
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
hashmap_t hashofheaders;
|
|
||||||
hashmap_iter iter;
|
hashmap_iter iter;
|
||||||
long content_length = -1;
|
long content_length = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
char *data, *header;
|
char *data, *header;
|
||||||
|
|
||||||
hashofheaders = hashmap_create(HEADER_BUCKETS);
|
|
||||||
if (!hashofheaders)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get all the headers from the client in a big hash.
|
|
||||||
*/
|
|
||||||
if (get_all_headers(connptr->client_fd, hashofheaders) < 0) {
|
|
||||||
log_message(LOG_WARNING, "Could not retrieve all the headers from the client");
|
|
||||||
goto ERROR_EXIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't send headers if there's already an error, if the request was
|
* Don't send headers if there's already an error, if the request was
|
||||||
* a stats request, or if this was a CONNECT method (unless upstream
|
* a stats request, or if this was a CONNECT method (unless upstream
|
||||||
@ -770,7 +815,6 @@ process_client_headers(struct conn_s *connptr)
|
|||||||
if (connptr->server_fd == -1 || connptr->show_stats
|
if (connptr->server_fd == -1 || connptr->show_stats
|
||||||
|| (connptr->connect_method && !UPSTREAM_CONFIGURED())) {
|
|| (connptr->connect_method && !UPSTREAM_CONFIGURED())) {
|
||||||
log_message(LOG_INFO, "Not sending client headers to remote machine");
|
log_message(LOG_INFO, "Not sending client headers to remote machine");
|
||||||
hashmap_delete(hashofheaders);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,17 +885,11 @@ process_client_headers(struct conn_s *connptr)
|
|||||||
* Spin here pulling the data from the client.
|
* Spin here pulling the data from the client.
|
||||||
*/
|
*/
|
||||||
PULL_CLIENT_DATA:
|
PULL_CLIENT_DATA:
|
||||||
hashmap_delete(hashofheaders);
|
|
||||||
|
|
||||||
if (content_length > 0)
|
if (content_length > 0)
|
||||||
return pull_client_data(connptr,
|
return pull_client_data(connptr,
|
||||||
(unsigned long int) content_length);
|
(unsigned long int) content_length);
|
||||||
else
|
else
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ERROR_EXIT:
|
|
||||||
hashmap_delete(hashofheaders);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -865,6 +903,7 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
"keep-alive",
|
"keep-alive",
|
||||||
"proxy-authenticate",
|
"proxy-authenticate",
|
||||||
"proxy-authorization",
|
"proxy-authorization",
|
||||||
|
"proxy-connection",
|
||||||
"transfer-encoding",
|
"transfer-encoding",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1219,6 +1258,7 @@ handle_connection(int fd)
|
|||||||
{
|
{
|
||||||
struct conn_s *connptr;
|
struct conn_s *connptr;
|
||||||
struct request_s *request = NULL;
|
struct request_s *request = NULL;
|
||||||
|
hashmap_t hashofheaders = NULL;
|
||||||
|
|
||||||
char peer_ipaddr[PEER_IP_LENGTH];
|
char peer_ipaddr[PEER_IP_LENGTH];
|
||||||
char peer_string[PEER_STRING_LENGTH];
|
char peer_string[PEER_STRING_LENGTH];
|
||||||
@ -1238,7 +1278,9 @@ handle_connection(int fd)
|
|||||||
update_stats(STAT_DENIED);
|
update_stats(STAT_DENIED);
|
||||||
indicate_http_error(connptr, 403,
|
indicate_http_error(connptr, 403,
|
||||||
"You do not have authorization for using this service.");
|
"You do not have authorization for using this service.");
|
||||||
goto send_error;
|
send_http_error_message(connptr);
|
||||||
|
destroy_conn(connptr);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TUNNEL_CONFIGURED()) {
|
if (TUNNEL_CONFIGURED()) {
|
||||||
@ -1251,23 +1293,50 @@ handle_connection(int fd)
|
|||||||
internal_proxy:
|
internal_proxy:
|
||||||
if (read_request_line(connptr) < 0) {
|
if (read_request_line(connptr) < 0) {
|
||||||
update_stats(STAT_BADCONN);
|
update_stats(STAT_BADCONN);
|
||||||
|
indicate_http_error(connptr, 408,
|
||||||
|
"Server timeout waiting for the HTTP request from the client.");
|
||||||
|
send_http_error_message(connptr);
|
||||||
destroy_conn(connptr);
|
destroy_conn(connptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
request = process_request(connptr);
|
/*
|
||||||
|
* The "hashofheaders" store the client's headers.
|
||||||
|
*/
|
||||||
|
if (!(hashofheaders = hashmap_create(HEADER_BUCKETS))) {
|
||||||
|
update_stats(STAT_BADCONN);
|
||||||
|
indicate_http_error(connptr, 503, HTTP503ERROR);
|
||||||
|
send_http_error_message(connptr);
|
||||||
|
destroy_conn(connptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get all the headers from the client in a big hash.
|
||||||
|
*/
|
||||||
|
if (get_all_headers(connptr->client_fd, hashofheaders) < 0) {
|
||||||
|
log_message(LOG_WARNING, "Could not retrieve all the headers from the client");
|
||||||
|
hashmap_delete(hashofheaders);
|
||||||
|
update_stats(STAT_BADCONN);
|
||||||
|
destroy_conn(connptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request = process_request(connptr, hashofheaders);
|
||||||
if (!request) {
|
if (!request) {
|
||||||
if (!connptr->error_string && !connptr->show_stats) {
|
if (!connptr->error_string && !connptr->show_stats) {
|
||||||
update_stats(STAT_BADCONN);
|
update_stats(STAT_BADCONN);
|
||||||
destroy_conn(connptr);
|
destroy_conn(connptr);
|
||||||
|
hashmap_delete(hashofheaders);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
goto send_error;
|
goto send_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UPSTREAM_CONFIGURED()) {
|
if (UPSTREAM_CONFIGURED()) {
|
||||||
if (connect_to_upstream(connptr, request) < 0)
|
if (connect_to_upstream(connptr, request) < 0) {
|
||||||
goto send_error;
|
goto send_error;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
connptr->server_fd = opensock(request->host, request->port);
|
connptr->server_fd = opensock(request->host, request->port);
|
||||||
if (connptr->server_fd < 0) {
|
if (connptr->server_fd < 0) {
|
||||||
@ -1286,13 +1355,15 @@ handle_connection(int fd)
|
|||||||
send_error:
|
send_error:
|
||||||
free_request_struct(request);
|
free_request_struct(request);
|
||||||
|
|
||||||
if (process_client_headers(connptr) < 0) {
|
if (process_client_headers(connptr, hashofheaders) < 0) {
|
||||||
update_stats(STAT_BADCONN);
|
update_stats(STAT_BADCONN);
|
||||||
if (!connptr->error_string) {
|
if (!connptr->error_string) {
|
||||||
|
hashmap_delete(hashofheaders);
|
||||||
destroy_conn(connptr);
|
destroy_conn(connptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hashmap_delete(hashofheaders);
|
||||||
|
|
||||||
if (connptr->error_string) {
|
if (connptr->error_string) {
|
||||||
send_http_error_message(connptr);
|
send_http_error_message(connptr);
|
||||||
|
Loading…
Reference in New Issue
Block a user