add SOCKS upstream proxy support (socks4/socks5)
original patch submitted in 2006 to debian mailing list: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=392848%29#12 this version was rebased to git and updated by Russ Dill <russ.dill@gmail.com> in 2015 (the original patch used a different config file format). as discussed in #40. commit message by @rofl0r.
This commit is contained in:
parent
116e59e933
commit
8906b0734e
34
src/conf.c
34
src/conf.c
@ -160,6 +160,8 @@ 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_upstream4);
|
||||||
|
static HANDLE_FUNC (handle_upstream5);
|
||||||
static HANDLE_FUNC (handle_upstream_no);
|
static HANDLE_FUNC (handle_upstream_no);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -257,6 +259,14 @@ 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 "(upstream4)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR
|
||||||
|
")?" END, handle_upstream4, NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BEGIN "(upstream5)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR
|
||||||
|
")?" END, handle_upstream5, NULL
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
/* loglevel */
|
/* loglevel */
|
||||||
STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)",
|
STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)",
|
||||||
@ -1066,7 +1076,8 @@ static HANDLE_FUNC (handle_reversepath)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
static HANDLE_FUNC (handle_upstream)
|
static int _handle_upstream(struct config_s* conf, const char* line,
|
||||||
|
regmatch_t match[], proxy_type type)
|
||||||
{
|
{
|
||||||
char *ip;
|
char *ip;
|
||||||
int port;
|
int port;
|
||||||
@ -1080,11 +1091,11 @@ 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 (ip, port, domain, type, &conf->upstream_list);
|
||||||
safefree (domain);
|
safefree (domain);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
upstream_add (ip, port, NULL, &conf->upstream_list);
|
upstream_add (ip, port, NULL, type, &conf->upstream_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
safefree (ip);
|
safefree (ip);
|
||||||
@ -1092,6 +1103,21 @@ static HANDLE_FUNC (handle_upstream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HANDLE_FUNC (handle_upstream)
|
||||||
|
{
|
||||||
|
return _handle_upstream(conf, line, match, HTTP_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HANDLE_FUNC (handle_upstream4)
|
||||||
|
{
|
||||||
|
return _handle_upstream(conf, line, match, SOCKS4_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HANDLE_FUNC (handle_upstream5)
|
||||||
|
{
|
||||||
|
return _handle_upstream(conf, line, match, SOCKS5_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
static HANDLE_FUNC (handle_upstream_no)
|
static HANDLE_FUNC (handle_upstream_no)
|
||||||
{
|
{
|
||||||
char *domain;
|
char *domain;
|
||||||
@ -1100,7 +1126,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, 0, domain, HTTP_TYPE, &conf->upstream_list);
|
||||||
safefree (domain);
|
safefree (domain);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
93
src/reqs.c
93
src/reqs.c
@ -61,9 +61,11 @@
|
|||||||
#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)
|
||||||
|
# define UPSTREAM_IS_HTTP(conn) (conn->upstream_proxy != NULL && conn->upstream_proxy->type == HTTP_TYPE)
|
||||||
#else
|
#else
|
||||||
# define UPSTREAM_CONFIGURED() (0)
|
# define UPSTREAM_CONFIGURED() (0)
|
||||||
# define UPSTREAM_HOST(host) (NULL)
|
# define UPSTREAM_HOST(host) (NULL)
|
||||||
|
# define UPSTREAM_IS_HTTP(up) (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -853,10 +855,10 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
/*
|
/*
|
||||||
* 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
|
||||||
* proxy is in use.)
|
* http proxy is in use.)
|
||||||
*/
|
*/
|
||||||
if (connptr->server_fd == -1 || connptr->show_stats
|
if (connptr->server_fd == -1 || connptr->show_stats
|
||||||
|| (connptr->connect_method && (connptr->upstream_proxy == NULL))) {
|
|| (connptr->connect_method && ! UPSTREAM_IS_HTTP(connptr))) {
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"Not sending client headers to remote machine");
|
"Not sending client headers to remote machine");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1265,6 +1267,88 @@ static void relay_connection (struct conn_s *connptr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
connect_to_upstream_proxy(struct conn_s *connptr, struct request_s *request)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char buff[512]; /* won't use more than 7 + 255 */
|
||||||
|
unsigned short port;
|
||||||
|
struct hostent *host;
|
||||||
|
struct upstream *cur_upstream = connptr->upstream_proxy;
|
||||||
|
|
||||||
|
log_message(LOG_CONN,
|
||||||
|
"Established connection to %s proxy \"%s\" using file descriptor %d.",
|
||||||
|
proxy_type_name(cur_upstream->type), cur_upstream->host, connptr->server_fd);
|
||||||
|
|
||||||
|
if (cur_upstream->type == SOCKS4_TYPE) {
|
||||||
|
|
||||||
|
buff[0] = 4; /* socks version */
|
||||||
|
buff[1] = 1; /* connect command */
|
||||||
|
port = htons(request->port);
|
||||||
|
memcpy(&buff[2], &port, 2); /* dest port */
|
||||||
|
host = gethostbyname(request->host);
|
||||||
|
memcpy(&buff[4], host->h_addr_list[0], 4); /* dest ip */
|
||||||
|
buff[8] = 0; /* user */
|
||||||
|
if (9 != safe_write(connptr->server_fd, buff, 9))
|
||||||
|
return -1;
|
||||||
|
if (8 != safe_read(connptr->server_fd, buff, 8))
|
||||||
|
return -1;
|
||||||
|
if (buff[0]!=0 || buff[1]!=90)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
} else if (cur_upstream->type == SOCKS5_TYPE) {
|
||||||
|
|
||||||
|
/* init */
|
||||||
|
buff[0] = 5; /* socks version */
|
||||||
|
buff[1] = 1; /* number of methods */
|
||||||
|
buff[2] = 0; /* no auth method */
|
||||||
|
if (3 != safe_write(connptr->server_fd, buff, 3))
|
||||||
|
return -1;
|
||||||
|
if (2 != safe_read(connptr->server_fd, buff, 2))
|
||||||
|
return -1;
|
||||||
|
if (buff[0]!=5 || buff[1]!=0)
|
||||||
|
return -1;
|
||||||
|
/* connect */
|
||||||
|
buff[0] = 5; /* socks version */
|
||||||
|
buff[1] = 1; /* connect */
|
||||||
|
buff[2] = 0; /* reserved */
|
||||||
|
buff[3] = 3; /* domainname */
|
||||||
|
len=strlen(request->host);
|
||||||
|
if(len>255)
|
||||||
|
return -1;
|
||||||
|
buff[4] = len; /* length of domainname */
|
||||||
|
memcpy(&buff[5], request->host, len); /* dest ip */
|
||||||
|
port = htons(request->port);
|
||||||
|
memcpy(&buff[5+len], &port, 2); /* dest port */
|
||||||
|
if (7+len != safe_write(connptr->server_fd, buff, 7+len))
|
||||||
|
return -1;
|
||||||
|
if (4 != safe_read(connptr->server_fd, buff, 4))
|
||||||
|
return -1;
|
||||||
|
if (buff[0]!=5 || buff[1]!=0)
|
||||||
|
return -1;
|
||||||
|
switch(buff[3]) {
|
||||||
|
case 1: len=4; break; /* ip v4 */
|
||||||
|
case 4: len=16; break; /* ip v6 */
|
||||||
|
case 3: /* domainname */
|
||||||
|
if (1 != safe_read(connptr->server_fd, buff, 1))
|
||||||
|
return -1;
|
||||||
|
len = buff[0]; /* max = 255 */
|
||||||
|
break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
if (2+len != safe_read(connptr->server_fd, buff, 2+len))
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connptr->connect_method)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return establish_http_connection(connptr, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Establish a connection to the upstream proxy server.
|
* Establish a connection to the upstream proxy server.
|
||||||
*/
|
*/
|
||||||
@ -1308,6 +1392,9 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cur_upstream->type != HTTP_TYPE)
|
||||||
|
return connect_to_upstream_proxy(connptr, request);
|
||||||
|
|
||||||
log_message (LOG_CONN,
|
log_message (LOG_CONN,
|
||||||
"Established connection to upstream proxy \"%s\" "
|
"Established connection to upstream proxy \"%s\" "
|
||||||
"using file descriptor %d.",
|
"using file descriptor %d.",
|
||||||
@ -1527,7 +1614,7 @@ void handle_connection (int fd)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(connptr->connect_method && (connptr->upstream_proxy == NULL))) {
|
if (!connptr->connect_method || UPSTREAM_IS_HTTP(connptr)) {
|
||||||
if (process_server_headers (connptr) < 0) {
|
if (process_server_headers (connptr) < 0) {
|
||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -29,10 +29,22 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
const char *
|
||||||
|
proxy_type_name(proxy_type type)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case HTTP_TYPE: return "http";
|
||||||
|
case SOCKS4_TYPE: return "socks4";
|
||||||
|
case SOCKS5_TYPE: return "socks5";
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 *host, int port, const char *domain,
|
||||||
|
proxy_type type)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
struct upstream *up;
|
struct upstream *up;
|
||||||
@ -44,6 +56,7 @@ static struct upstream *upstream_build (const char *host, int port, const char *
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
up->type = type;
|
||||||
up->host = up->domain = NULL;
|
up->host = up->domain = NULL;
|
||||||
up->ip = up->mask = 0;
|
up->ip = up->mask = 0;
|
||||||
|
|
||||||
@ -57,8 +70,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 %s:%d for [default]",
|
||||||
host, port);
|
proxy_type_name(type), 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,8 +114,8 @@ 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 %s:%d for %s",
|
||||||
host, port, domain);
|
proxy_type_name(type), host, port, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return up;
|
return up;
|
||||||
@ -119,11 +132,11 @@ 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 *host, int port, const char *domain,
|
||||||
struct upstream **upstream_list)
|
proxy_type type, struct upstream **upstream_list)
|
||||||
{
|
{
|
||||||
struct upstream *up;
|
struct upstream *up;
|
||||||
|
|
||||||
up = upstream_build (host, port, domain);
|
up = upstream_build (host, port, domain, type);
|
||||||
if (up == NULL) {
|
if (up == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -202,8 +215,8 @@ struct upstream *upstream_get (char *host, struct upstream *up)
|
|||||||
up = NULL;
|
up = NULL;
|
||||||
|
|
||||||
if (up)
|
if (up)
|
||||||
log_message (LOG_INFO, "Found upstream proxy %s:%d for %s",
|
log_message (LOG_INFO, "Found upstream proxy %s %s:%d for %s",
|
||||||
up->host, up->port, host);
|
proxy_type_name(up->type), up->host, up->port, host);
|
||||||
else
|
else
|
||||||
log_message (LOG_INFO, "No upstream proxy for %s", host);
|
log_message (LOG_INFO, "No upstream proxy for %s", host);
|
||||||
|
|
||||||
|
@ -31,17 +31,20 @@
|
|||||||
* Even if upstream support is not compiled into tinyproxy, this
|
* Even if upstream support is not compiled into tinyproxy, this
|
||||||
* structure still needs to be defined.
|
* structure still needs to be defined.
|
||||||
*/
|
*/
|
||||||
|
typedef enum {HTTP_TYPE, SOCKS4_TYPE, SOCKS5_TYPE} proxy_type;
|
||||||
struct upstream {
|
struct upstream {
|
||||||
struct upstream *next;
|
struct upstream *next;
|
||||||
char *domain; /* optional */
|
char *domain; /* optional */
|
||||||
char *host;
|
char *host;
|
||||||
int port;
|
int port;
|
||||||
in_addr_t ip, mask;
|
in_addr_t ip, mask;
|
||||||
|
proxy_type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
const char *proxy_type_name(proxy_type type);
|
||||||
extern void upstream_add (const char *host, int port, const char *domain,
|
extern void upstream_add (const char *host, int port, const char *domain,
|
||||||
struct upstream **upstream_list);
|
proxy_type type, 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);
|
||||||
#endif /* UPSTREAM_SUPPORT */
|
#endif /* UPSTREAM_SUPPORT */
|
||||||
|
Loading…
Reference in New Issue
Block a user