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
 | 
			
		||||
 * connections have a new child created for them. The child then
 | 
			
		||||
@ -11,6 +11,7 @@
 | 
			
		||||
 * Copyright (C) 1998	    Steven Young
 | 
			
		||||
 * Copyright (C) 1999-2002  Robert James Kaes (rjkaes@flarenet.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
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
static struct request_s *
 | 
			
		||||
process_request(struct conn_s *connptr)
 | 
			
		||||
process_request(struct conn_s *connptr, hashmap_t hashofheaders)
 | 
			
		||||
{
 | 
			
		||||
	char *url;
 | 
			
		||||
	struct request_s *request;
 | 
			
		||||
@ -397,6 +398,61 @@ process_request(struct conn_s *connptr)
 | 
			
		||||
		
 | 
			
		||||
		connptr->connect_method = TRUE;
 | 
			
		||||
	} 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,
 | 
			
		||||
			    "process_request: Unknown URL type on file descriptor %d",
 | 
			
		||||
			    connptr->client_fd);
 | 
			
		||||
@ -406,6 +462,7 @@ process_request(struct conn_s *connptr)
 | 
			
		||||
		free_request_struct(request);
 | 
			
		||||
 | 
			
		||||
		return NULL;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef FILTER_ENABLE
 | 
			
		||||
@ -730,38 +787,26 @@ write_via_header(int fd, hashmap_t hashofheaders,
 | 
			
		||||
 *	- rjkaes
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
process_client_headers(struct conn_s *connptr)
 | 
			
		||||
process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
 | 
			
		||||
{
 | 
			
		||||
	static char *skipheaders[] = {
 | 
			
		||||
		"host",
 | 
			
		||||
		"keep-alive",
 | 
			
		||||
		"proxy-authenticate",
 | 
			
		||||
		"proxy-authorization",
 | 
			
		||||
		"proxy-connection",
 | 
			
		||||
		"te",
 | 
			
		||||
		"trailers",
 | 
			
		||||
		"transfer-encoding",
 | 
			
		||||
		"upgrade"
 | 
			
		||||
	};
 | 
			
		||||
	int i;
 | 
			
		||||
	hashmap_t hashofheaders;
 | 
			
		||||
	hashmap_iter iter;
 | 
			
		||||
	long content_length = -1;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
	 * 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
 | 
			
		||||
	    || (connptr->connect_method && !UPSTREAM_CONFIGURED())) {
 | 
			
		||||
		log_message(LOG_INFO, "Not sending client headers to remote machine");
 | 
			
		||||
		hashmap_delete(hashofheaders);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -841,17 +885,11 @@ process_client_headers(struct conn_s *connptr)
 | 
			
		||||
	 * Spin here pulling the data from the client.
 | 
			
		||||
	 */
 | 
			
		||||
  PULL_CLIENT_DATA:
 | 
			
		||||
	hashmap_delete(hashofheaders);
 | 
			
		||||
 | 
			
		||||
	if (content_length > 0)
 | 
			
		||||
		return pull_client_data(connptr,
 | 
			
		||||
					(unsigned long int) content_length);
 | 
			
		||||
	else
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
  ERROR_EXIT:
 | 
			
		||||
	hashmap_delete(hashofheaders);
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -865,6 +903,7 @@ process_server_headers(struct conn_s *connptr)
 | 
			
		||||
		"keep-alive",
 | 
			
		||||
		"proxy-authenticate",
 | 
			
		||||
		"proxy-authorization",
 | 
			
		||||
		"proxy-connection",
 | 
			
		||||
		"transfer-encoding",
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
@ -1219,6 +1258,7 @@ handle_connection(int fd)
 | 
			
		||||
{
 | 
			
		||||
	struct conn_s *connptr;
 | 
			
		||||
	struct request_s *request = NULL;
 | 
			
		||||
	hashmap_t hashofheaders = NULL;
 | 
			
		||||
 | 
			
		||||
	char peer_ipaddr[PEER_IP_LENGTH];
 | 
			
		||||
	char peer_string[PEER_STRING_LENGTH];
 | 
			
		||||
@ -1238,7 +1278,9 @@ handle_connection(int fd)
 | 
			
		||||
		update_stats(STAT_DENIED);
 | 
			
		||||
		indicate_http_error(connptr, 403,
 | 
			
		||||
			"You do not have authorization for using this service.");
 | 
			
		||||
		goto send_error;
 | 
			
		||||
		send_http_error_message(connptr);
 | 
			
		||||
		destroy_conn(connptr);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (TUNNEL_CONFIGURED()) {
 | 
			
		||||
@ -1251,23 +1293,50 @@ handle_connection(int fd)
 | 
			
		||||
      internal_proxy:
 | 
			
		||||
	if (read_request_line(connptr) < 0) {
 | 
			
		||||
		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);
 | 
			
		||||
		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 (!connptr->error_string && !connptr->show_stats) {
 | 
			
		||||
			update_stats(STAT_BADCONN);
 | 
			
		||||
			destroy_conn(connptr);
 | 
			
		||||
			hashmap_delete(hashofheaders);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		goto send_error;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (UPSTREAM_CONFIGURED()) {
 | 
			
		||||
		if (connect_to_upstream(connptr, request) < 0)
 | 
			
		||||
		if (connect_to_upstream(connptr, request) < 0) {
 | 
			
		||||
			goto send_error;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		connptr->server_fd = opensock(request->host, request->port);
 | 
			
		||||
		if (connptr->server_fd < 0) {
 | 
			
		||||
@ -1286,13 +1355,15 @@ handle_connection(int fd)
 | 
			
		||||
      send_error:
 | 
			
		||||
	free_request_struct(request);
 | 
			
		||||
 | 
			
		||||
	if (process_client_headers(connptr) < 0) {
 | 
			
		||||
	if (process_client_headers(connptr, hashofheaders) < 0) {
 | 
			
		||||
		update_stats(STAT_BADCONN);
 | 
			
		||||
		if (!connptr->error_string) {
 | 
			
		||||
			hashmap_delete(hashofheaders);
 | 
			
		||||
			destroy_conn(connptr);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hashmap_delete(hashofheaders);
 | 
			
		||||
 | 
			
		||||
	if (connptr->error_string) {
 | 
			
		||||
		send_http_error_message(connptr);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user