implemented remote proxy dns lookup via use of reserved ip ranges and a lookup table

remote-dns
rofl0r 2011-11-06 14:12:50 +01:00
parent d30b0a8712
commit 5de7fa20c8
3 changed files with 476 additions and 336 deletions

View File

@ -34,37 +34,66 @@
#include <sys/time.h>
#include <stdarg.h>
#include "core.h"
#include "common.h"
extern int tcp_read_time_out;
extern int tcp_connect_time_out;
extern int proxychains_quiet_mode;
internal_ip_lookup_table internal_ips = {0, 0, NULL};
uint32_t dalias_hash(char* s) {
uint_fast32_t h = 0;
while (*s) {
h = 16*h + *s++;
h ^= h>>24 & 0xf0;
}
return h & 0xfffffff;
}
uint32_t index_from_internal_ip(ip_type internalip) {
ip_type tmp = internalip;
uint32_t ret;
ret = tmp.octet[3] + tmp.octet[2] << 8 + tmp.octet[1] << 16;
return ret;
}
in_addr_t make_internal_ip(uint32_t index) {
ip_type ret;
if(index > 0xFFFFFF) return (in_addr_t) -1;
ret.octet[0] = 224;
ret.octet[1] = (index & 0xFF0000) >> 16;
ret.octet[2] = (index & 0xFF00) >> 8;
ret.octet[3] = index & 0xFF;
return (in_addr_t) ret.as_int;
}
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int poll_retry(struct pollfd *fds, nfds_t nfsd, int timeout)
{
int ret;
int time_remain = timeout;
int time_elapsed = 0;
int ret;
int time_remain = timeout;
int time_elapsed = 0;
struct timeval start_time;
struct timeval tv;
struct timeval start_time;
struct timeval tv;
gettimeofday(&start_time, NULL);
gettimeofday(&start_time, NULL);
do
{
//printf("Retry %d\n", time_remain);
ret = poll(fds, nfsd, time_remain);
gettimeofday(&tv, NULL);
time_elapsed = ((tv.tv_sec - start_time.tv_sec) * 1000 + (tv.tv_usec - start_time.tv_usec) / 1000);
//printf("Time elapsed %d\n", time_elapsed);
time_remain = timeout - time_elapsed;
}
while (ret == -1 && errno == EINTR && time_remain > 0);
//if (ret == -1)
//printf("Return %d %d %s\n", ret, errno, strerror(errno));
return ret;
do {
//printf("Retry %d\n", time_remain);
ret = poll(fds, nfsd, time_remain);
gettimeofday(&tv, NULL);
time_elapsed = ((tv.tv_sec - start_time.tv_sec) * 1000 + (tv.tv_usec - start_time.tv_usec) / 1000);
//printf("Time elapsed %d\n", time_elapsed);
time_remain = timeout - time_elapsed;
} while (ret == -1 && errno == EINTR && time_remain > 0);
//if (ret == -1)
//printf("Return %d %d %s\n", ret, errno, strerror(errno));
return ret;
}
@ -108,20 +137,18 @@ static void encode_base_64(char* src,char* dest,int max_len)
int proxychains_write_log(char *str,...)
{
char buff[LOG_BUFF];
va_list arglist;
FILE * log_file;
log_file=stderr;
if (!proxychains_quiet_mode)
{
va_start(arglist,str);
vsprintf(buff,str,arglist);
va_end(arglist);
fprintf(log_file,"%s",buff);
fflush(log_file);
}
return EXIT_SUCCESS;
char buff[LOG_BUFF];
va_list arglist;
FILE * log_file;
log_file=stderr;
if (!proxychains_quiet_mode) {
va_start(arglist,str);
vsprintf(buff,str,arglist);
va_end(arglist);
fprintf(log_file,"%s",buff);
fflush(log_file);
}
return EXIT_SUCCESS;
}
static int write_n_bytes(int fd,char *buff,size_t size)
@ -198,195 +225,239 @@ static int timed_connect(int sock, const struct sockaddr *addr, socklen_t len)
return ret;
}
static int tunnel_to(int sock, unsigned int ip, unsigned short port, proxy_type pt,char *user,char *pass)
#define INVALID_INDEX 0xFFFFFFFFU
static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt,char *user,char *pass)
{
#ifdef DEBUG
PDEBUG("tunnel_to()\n");
#endif
uint32_t index = INVALID_INDEX;
char* dns_name = NULL;
size_t dns_len = 0;
// we use ip addresses with 224.* to lookup their dns name in our table, to allow remote DNS resolution
// the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
// the results returned from gethostbyname et al.)
if(ip.octet[0] == 224) {
index = index_from_internal_ip(ip);
if(index > internal_ips.counter) goto err;
dns_name = internal_ips.list[index]->string;
if(!dns_name) goto err;
dns_len = strlen(dns_name);
if(!dns_len) goto err;
}
size_t ulen = strlen(user);
size_t passlen = strlen(pass);
int len;
char buff[BUFF_SIZE];
memset (buff, 0, sizeof(buff));
switch(pt)
{
case HTTP_TYPE:
{
sprintf(buff,"CONNECT %s:%d HTTP/1.0\r\n",
inet_ntoa( * (struct in_addr *) &ip),
ntohs(port));
if (user[0])
{
char src[256];
char dst[512];
strcpy(src,user);
strcat(src,":");
strcat(src,pass);
encode_base_64(src,dst,512);
strcat(buff,"Proxy-Authorization: Basic ");
strcat(buff,dst);
strcat(buff,"\r\n\r\n");
}
else
strcat(buff,"\r\n");
unsigned char buff[BUFF_SIZE];
//memset (buff, 0, sizeof(buff));
switch(pt) {
case HTTP_TYPE: {
if(!dns_len)
snprintf(buff, sizeof(buff), "CONNECT %s:%d HTTP/1.0\r\n",
inet_ntoa( * (struct in_addr *) &ip.as_int), ntohs(port));
else
snprintf(buff, sizeof(buff), "CONNECT %s:%d HTTP/1.0\r\n", dns_name, ntohs(port));
len=strlen(buff);
if(len!=send(sock,buff,len,0))
return SOCKET_ERROR;
memset(buff, 0, sizeof(buff));
len=0 ;
// read header byte by byte.
while(len<BUFF_SIZE)
{
if(1==read_n_bytes(sock,buff+len,1))
len++;
else
return SOCKET_ERROR;
if ( len > 4 &&
buff[len-1]=='\n' &&
buff[len-2]=='\r' &&
buff[len-3]=='\n' &&
buff[len-4]=='\r' )
break;
}
// if not ok (200) or response greather than BUFF_SIZE return BLOCKED;
if ( (len==BUFF_SIZE) ||
! ( buff[9] =='2' &&
buff[10]=='0' &&
buff[11]=='0' ))
return BLOCKED;
return SUCCESS;
}
break;
case SOCKS4_TYPE:
{
memset(buff,0,sizeof(buff));
buff[0]=4; // socks version
buff[1]=1; // connect command
memcpy(&buff[2],&port,2); // dest port
memcpy(&buff[4],&ip,4); // dest host
len=strlen(user)+1; // username
if(len>1)
strcpy(&buff[8],user);
if((len+8)!=write_n_bytes(sock,buff,(8+len)))
return SOCKET_ERROR;
if(8!=read_n_bytes(sock,buff,8))
return SOCKET_ERROR;
if (buff[0]!=0||buff[1]!=90)
return BLOCKED;
return SUCCESS;
}
break;
case SOCKS5_TYPE:
{
if(user)
{
buff[0]=5; //version
buff[1]=2; //nomber of methods
buff[2]=0; // no auth method
buff[3]=2; /// auth method -> username / password
if(4!=write_n_bytes(sock,buff,4))
return SOCKET_ERROR;
}
else
{
buff[0]=5; //version
buff[1]=1; //nomber of methods
buff[2]=0; // no auth method
if(3!=write_n_bytes(sock,buff,3))
return SOCKET_ERROR;
}
memset(buff,0,sizeof(buff));
if(2!=read_n_bytes(sock,buff,2))
return SOCKET_ERROR;
if (buff[0]!=5||(buff[1]!=0&&buff[1]!=2))
{
if((buff[0]==0x05)&&(buff[1]==(char)0xFF))
return BLOCKED;
else
return SOCKET_ERROR;
}
if (buff[1]==2)
{
// authentication
char in[2];
char out[515]; char* cur=out;
int c;
*cur++=1; // version
c=strlen(user);
*cur++=c;
strncpy(cur,user,c);
cur+=c;
c=strlen(pass);
*cur++=c;
strncpy(cur,pass,c);
cur+=c;
if((cur-out)!=write_n_bytes(sock,out,cur-out))
return SOCKET_ERROR;
if(2!=read_n_bytes(sock,in,2))
return SOCKET_ERROR;
if(in[0]!=1||in[1]!=0)
{
if(in[0]!=1)
return SOCKET_ERROR;
else
return BLOCKED;
}
}
buff[0]=5; // version
buff[1]=1; // connect
buff[2]=0; // reserved
buff[3]=1; // ip v4
memcpy(&buff[4],&ip,4); // dest host
memcpy(&buff[8],&port,2); // dest port
if (user[0])
{
char src[256];
char dst[512];
memcpy(src, user, ulen);
memcpy(src + ulen, ":", 1);
memcpy(src + ulen + 1, pass, passlen);
src[ulen + 1 + passlen] = 0;
if(10!=write_n_bytes(sock,buff,10))
return SOCKET_ERROR;
encode_base_64(src,dst,512);
strcat(buff,"Proxy-Authorization: Basic ");
strcat(buff,dst);
strcat(buff,"\r\n\r\n");
}
else
strcat(buff,"\r\n");
if(4!=read_n_bytes(sock,buff,4))
return SOCKET_ERROR;
len = strlen(buff);
if (buff[0]!=5||buff[1]!=0)
return SOCKET_ERROR;
if(len != send(sock, buff, len, 0))
goto err;
memset(buff, 0, sizeof(buff));
len = 0 ;
// read header byte by byte.
while(len < BUFF_SIZE) {
if(1 == read_n_bytes(sock, buff+len, 1))
len++;
else
goto err;
if (len > 4 &&
buff[len-1]=='\n' &&
buff[len-2]=='\r' &&
buff[len-3]=='\n' &&
buff[len-4]=='\r' )
break;
}
switch (buff[3])
{
case 1: len=4; break;
case 4: len=16; break;
case 3: len=0;
if(1!=read_n_bytes(sock,(char*)&len,1))
return SOCKET_ERROR;
break;
default:
return SOCKET_ERROR;
// if not ok (200) or response greather than BUFF_SIZE return BLOCKED;
if (len == BUFF_SIZE ||
!( buff[9] =='2' &&
buff[10]=='0' &&
buff[11]=='0' ))
return BLOCKED;
return SUCCESS;
}
break;
case SOCKS4_TYPE: {
buff[0] = 4; // socks version
buff[1] = 1; // connect command
memcpy(&buff[2],&port,2); // dest port
if(dns_len) {
ip.octet[0] = 0;
ip.octet[1] = 0;
ip.octet[2] = 0;
ip.octet[3] = 1;
}
memcpy(&buff[4], &ip, 4); // dest host
len = ulen + 1; // username
if(len > 1)
memcpy(&buff[8], user, ulen + 1);
// do socksv4a dns resolution on the server
if(dns_len) {
memcpy(&buff[8 + len], dns_name, dns_len + 1);
len += dns_len + 1;
}
if((len + 8) != write_n_bytes(sock, buff, (8+len)))
goto err;
if((len+2)!=read_n_bytes(sock,buff,(len+2)))
return SOCKET_ERROR;
if(8 != read_n_bytes(sock,buff,8))
goto err;
if (buff[0] != 0 || buff[1] != 90)
return BLOCKED;
return SUCCESS;
}
break;
}
break;
case SOCKS5_TYPE: {
if(user) {
buff[0]=5; //version
buff[1]=2; //nomber of methods
buff[2]=0; // no auth method
buff[3]=2; /// auth method -> username / password
if(4!=write_n_bytes(sock,buff,4))
goto err;
}
else {
buff[0]=5; //version
buff[1]=1; //nomber of methods
buff[2]=0; // no auth method
if(3 != write_n_bytes(sock, buff, 3))
goto err;
}
}
if(2 != read_n_bytes(sock, buff, 2))
goto err;
if (buff[0] != 5 || (buff[1] != 0 && buff[1] != 2)) {
if(buff[0] == 5 && buff[1] ==(char)0xFF)
return BLOCKED;
else
goto err;
}
if (buff[1] == 2) {
// authentication
char in[2];
char out[515]; char* cur=out;
int c;
*cur++=1; // version
c = ulen & 0xFF;
*cur++ = c;
memcpy(cur, user, c);
cur += c;
c = passlen & 0xFF;
*cur++ = c;
memcpy(cur, pass, c);
cur += c;
if((cur-out) != write_n_bytes(sock, out, cur-out))
goto err;
if(2 != read_n_bytes(sock,in,2))
goto err;
if(in[0] != 1 || in[1] != 0) {
if(in[0] != 1)
goto err;
else
return BLOCKED;
}
}
int buff_iter = 0;
buff[buff_iter++] = 5; // version
buff[buff_iter++] = 1; // connect
buff[buff_iter++] = 0; // reserved
if(!dns_len) {
buff[buff_iter++] = 1; // ip v4
memcpy(buff + buff_iter, &ip, 4); // dest host
buff_iter += 4;
} else {
buff[buff_iter++] = 3; //dns
buff[buff_iter++] = dns_len & 0xFF;
memcpy(buff + buff_iter, dns_name, dns_len);
buff_iter += dns_len;
}
memcpy(buff + buff_iter, &port, 2); // dest port
buff_iter += 2;
return SOCKET_ERROR;
if(buff_iter != write_n_bytes(sock, buff, buff_iter))
goto err;
if(4 != read_n_bytes(sock,buff,4))
goto err;
if (buff[0] != 5 || buff[1] != 0)
goto err;
switch (buff[3]) {
case 1: len = 4; break;
case 4: len = 16; break;
case 3: len = 0;
if(1 != read_n_bytes(sock, (char*) &len, 1))
goto err;
break;
default:
goto err;
}
if(len + 2 != read_n_bytes(sock, buff, len+2))
goto err;
return SUCCESS;
}
break;
}
err:
return SOCKET_ERROR;
}
#define TP " ... "
#define DT "Dynamic chain"
#define ST "Strict chain"
#define RT "Random chain"
static int start_chain(int *fd, proxy_data *pd, char* begin_mark)
{
struct sockaddr_in addr;
@ -395,14 +466,14 @@ static int start_chain(int *fd, proxy_data *pd, char* begin_mark)
if(*fd==-1)
goto error;
proxychains_write_log("%s-<>-%s:%d-",
proxychains_write_log(LOG_PREFIX "%s "TP" %s:%d ",
begin_mark,
inet_ntoa(*(struct in_addr*)&pd->ip),
htons(pd->port));
pd->ps=PLAY_STATE;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = pd->ip;
addr.sin_addr.s_addr = (in_addr_t) pd->ip.as_int;
addr.sin_port = pd->port;
if (timed_connect (*fd ,(struct sockaddr*)&addr,sizeof(addr))) {
pd->ps=DOWN_STATE;
@ -411,7 +482,7 @@ static int start_chain(int *fd, proxy_data *pd, char* begin_mark)
pd->ps=BUSY_STATE;
return SUCCESS;
error1:
proxychains_write_log("<--timeout\n");
proxychains_write_log(TP" timeout\n");
error:
if(*fd!=-1)
close(*fd);
@ -481,12 +552,23 @@ static unsigned int calc_alive(proxy_data *pd, unsigned int proxy_count)
static int chain_step(int ns, proxy_data *pfrom, proxy_data *pto)
{
int retcode=-1;
char* hostname;
uint32_t index;
#ifdef DEBUG
PDEBUG("chain_step()\n");
#endif
if(pto->ip.octet[0] == 224) {
index = index_from_internal_ip(pto->ip);
if(index < internal_ips.counter)
hostname = internal_ips.list[index]->string;
else goto usenumericip;
} else {
usenumericip:
hostname = inet_ntoa(*(struct in_addr*)&pto->ip);
}
proxychains_write_log("<>-%s:%d-",
inet_ntoa(*(struct in_addr*)&pto->ip),
proxychains_write_log(TP" %s:%d ",
hostname,
htons(pto->port));
retcode =
tunnel_to(ns, pto->ip, pto->port, pfrom->pt, pfrom->user,
@ -509,7 +591,7 @@ static int chain_step(int ns, proxy_data *pfrom, proxy_data *pto)
return retcode;
}
int connect_proxy_chain( int sock, unsigned int target_ip,
int connect_proxy_chain( int sock, ip_type target_ip,
unsigned short target_port, proxy_data *pd,
unsigned int proxy_count, chain_type ct, unsigned int max_chain )
{
@ -519,11 +601,6 @@ int connect_proxy_chain( int sock, unsigned int target_ip,
unsigned int offset=0;
unsigned int alive_count=0;
unsigned int curr_len=0;
#define TP "<>"
#define DT "|D-chain|"
#define ST "|S-chain|"
#define RT "|R-chain|"
p3=&p4;
#ifdef DEBUG
@ -534,8 +611,8 @@ again:
switch(ct) {
case DYNAMIC_TYPE:
alive_count=calc_alive(pd,proxy_count);
offset=0;
alive_count = calc_alive(pd,proxy_count);
offset = 0;
do {
if(!(p1=select_proxy(FIFOLY,pd,proxy_count,&offset)))
goto error_more;
@ -552,16 +629,16 @@ again:
}
p1=p2;
}
proxychains_write_log(TP);
p3->ip=target_ip;
p3->port=target_port;
if(SUCCESS!=chain_step(ns,p1,p3))
//proxychains_write_log(TP);
p3->ip = target_ip;
p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3))
goto error;
break;
case STRICT_TYPE:
alive_count=calc_alive(pd, proxy_count);
offset=0;
alive_count = calc_alive(pd, proxy_count);
offset = 0;
if(!(p1=select_proxy(FIFOLY, pd, proxy_count, &offset))) {
#ifdef DEBUG
PDEBUG("select_proxy failed\n");
@ -583,12 +660,12 @@ again:
#endif
goto error_strict;
}
p1=p2;
p1 = p2;
}
proxychains_write_log(TP);
p3->ip=target_ip;
p3->port=target_port;
if(SUCCESS!=chain_step(ns,p1,p3))
//proxychains_write_log(TP);
p3->ip = target_ip;
p3->port = target_port;
if(SUCCESS!=chain_step(ns, p1, p3))
goto error;
break;
@ -604,23 +681,23 @@ again:
while(++curr_len<max_chain) {
if(!(p2=select_proxy(RANDOMLY,pd,proxy_count,&offset)))
goto error_more;
if(SUCCESS!=chain_step(ns,p1,p2)) {
if(SUCCESS!=chain_step(ns, p1, p2)) {
#ifdef DEBUG
PDEBUG("GOTO AGAIN 2\n");
#endif
goto again;
}
p1=p2;
p1 = p2;
}
proxychains_write_log(TP);
p3->ip=target_ip;
p3->port=target_port;
//proxychains_write_log(TP);
p3->ip = target_ip;
p3->port = target_port;
if(SUCCESS!=chain_step(ns,p1,p3))
goto error;
}
proxychains_write_log("<><>-OK\n");
proxychains_write_log(TP" OK\n");
dup2(ns,sock);
close(ns);
return 0;
@ -643,72 +720,91 @@ error_strict:
return -1;
}
static struct hostent hostent_space;
static in_addr_t resolved_addr;
static char* resolved_addr_p;
static char* resolved_addr_p[2];
static char addr_name[1024*8];
static const ip_type local_host = {127, 0, 0, 1};
struct hostent* proxy_gethostbyname(const char *name)
{
int pipe_fd[2];
char buff[256];
in_addr_t addr;
pid_t pid;
int status;
uint32_t i, hash;
void* new_mem;
size_t l;
struct hostent* hp;
hostent_space.h_addr_list = &resolved_addr_p;
*hostent_space.h_addr_list = (char*)&resolved_addr;
resolved_addr_p[0] = (char*) &resolved_addr;
resolved_addr_p[1] = NULL;
hostent_space.h_addr_list = resolved_addr_p;
resolved_addr = 0;
gethostname(buff,sizeof(buff));
if(!strcmp(buff,name))
goto got_buff;
if(!strcmp(buff, name)) {
resolved_addr = inet_addr(buff);
if (resolved_addr == (in_addr_t) (-1))
resolved_addr = (in_addr_t) (local_host.as_int);
return &hostent_space;
}
memset(buff, 0, sizeof(buff));
// TODO: this works only once, so cache it ...
// later
while ((hp=gethostent()))
if (!strcmp(hp->h_name,name))
return hp;
if(pipe(pipe_fd))
goto err;
pid = fork();
switch(pid) {
case 0: // child
proxychains_write_log("|DNS-request| %s \n", name);
dup2(pipe_fd[1],1);
//dup2(pipe_fd[1],2);
// putenv("LD_PRELOAD=");
execlp("proxyresolv","proxyresolv",name,NULL);
perror("can't exec proxyresolv");
exit(2);
case -1: //error
close(pipe_fd[0]);
close(pipe_fd[1]);
perror("can't fork");
goto err;
default:
close(pipe_fd[1]);
waitpid(pid, &status, 0);
read(pipe_fd[0],&buff,sizeof(buff));
close(pipe_fd[0]);
got_buff:
addr = inet_addr(buff);
if (addr == (in_addr_t) (-1))
goto err_dns;
memcpy(*(hostent_space.h_addr_list),
&addr ,sizeof(struct in_addr));
hostent_space.h_name = addr_name;
hostent_space.h_length = sizeof (in_addr_t);
hash = dalias_hash((char*) name);
if(internal_ips.counter) {
for( i = 0; i < internal_ips.counter; i++) {
if(internal_ips.list[i]->hash == hash) {
resolved_addr = make_internal_ip(i);
goto have_ip;
}
}
}
proxychains_write_log("|DNS-response| %s is %s\n",
name, inet_ntoa(*(struct in_addr*)&addr));
if(internal_ips.capa < internal_ips.counter + 1) {
new_mem = realloc(internal_ips.list, internal_ips.capa + 16);
if(new_mem) {
internal_ips.capa += 16;
internal_ips.list = new_mem;
} else {
oom:
proxychains_write_log("out of mem\n");
goto err;
}
}
resolved_addr = make_internal_ip(internal_ips.counter);
if(resolved_addr == (in_addr_t) -1) goto err;
l = strlen(name);
new_mem = malloc(sizeof(string_hash_tuple) + l + 1);
if(!new_mem)
goto oom;
internal_ips.list[internal_ips.counter] = new_mem;
internal_ips.list[internal_ips.counter]->hash = hash;
internal_ips.list[internal_ips.counter]->string = (char*) new_mem + sizeof(string_hash_tuple);
memcpy(internal_ips.list[internal_ips.counter]->string, name, l + 1);
internal_ips.counter += 1;
have_ip:
//strncpy(addr_name, name, sizeof(addr_name));
hostent_space.h_name = addr_name;
hostent_space.h_length = sizeof (in_addr_t);
return &hostent_space;
err_dns:
proxychains_write_log("|DNS-response|: %s does not exist\n", name);
perror("err_dns");

View File

@ -5,6 +5,7 @@
copyright : netcreature (C) 2002
email : netcreature@users.sourceforge.net
***************************************************************************/
#include <stdint.h>
/* GPL */
/***************************************************************************
* *
@ -19,31 +20,66 @@
#define BUFF_SIZE 8*1024 // used to read responses from proxies.
#define MAX_LOCALNET 1024
typedef union {
unsigned char octet[4];
uint32_t as_int;
} ip_type;
typedef struct {
uint32_t hash;
char* string;
} string_hash_tuple;
typedef struct {
uint32_t counter;
uint32_t capa;
string_hash_tuple** list;
} internal_ip_lookup_table;
extern internal_ip_lookup_table internal_ips;
/*error codes*/
typedef enum
{
SUCCESS=0,
MEMORY_FAIL, // malloc failed
SOCKET_ERROR, // look errno for more
CHAIN_DOWN, // no proxy in chain responds to tcp
CHAIN_EMPTY, // if proxy_count = 0
BLOCKED // target's port blocked on last proxy in the chain
typedef enum {
SUCCESS=0,
MEMORY_FAIL, // malloc failed
SOCKET_ERROR, // look errno for more
CHAIN_DOWN, // no proxy in chain responds to tcp
CHAIN_EMPTY, // if proxy_count = 0
BLOCKED // target's port blocked on last proxy in the chain
} ERR_CODE;
typedef enum {HTTP_TYPE,SOCKS4_TYPE,SOCKS5_TYPE} proxy_type;
typedef enum {DYNAMIC_TYPE,STRICT_TYPE,RANDOM_TYPE} chain_type;
typedef enum {PLAY_STATE,DOWN_STATE,BLOCKED_STATE,BUSY_STATE} proxy_state;
typedef enum {RANDOMLY,FIFOLY} select_type;
typedef enum {
HTTP_TYPE,
SOCKS4_TYPE,
SOCKS5_TYPE
} proxy_type;
typedef struct
{
typedef enum {
DYNAMIC_TYPE,
STRICT_TYPE,
RANDOM_TYPE}
chain_type;
typedef enum {
PLAY_STATE,
DOWN_STATE,
BLOCKED_STATE,
BUSY_STATE
} proxy_state;
typedef enum {
RANDOMLY,
FIFOLY
} select_type;
typedef struct {
struct in_addr in_addr, netmask;
unsigned short port;
} localaddr_arg;
typedef struct {
unsigned int ip;
ip_type ip;
unsigned short port;
proxy_type pt;
proxy_state ps;
@ -53,21 +89,21 @@ typedef struct {
typedef struct {
proxy_data *pd;
chain_type ct;
unsigned int proxy_count;
int sock;
struct sockaddr addr;
int flags;
chain_type ct;
unsigned int proxy_count;
int sock;
struct sockaddr addr;
int flags;
} thread_arg;
int connect_proxy_chain (
int sock,
unsigned int target_ip,
unsigned short target_port,
proxy_data * pd,
unsigned int proxy_count,
chain_type ct,
unsigned int max_chain );
int sock,
ip_type target_ip,
unsigned short target_port,
proxy_data * pd,
unsigned int proxy_count,
chain_type ct,
unsigned int max_chain );
int proxychains_write_log(char *str,...);
struct hostent* proxy_gethostbyname(const char *name);

View File

@ -62,7 +62,7 @@ static void init_lib(void);
static void init_lib(void)
{
proxychains_write_log("[proxychains v3.2] DLL init\n");
proxychains_write_log(LOG_PREFIX "DLL init\n");
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
true_connect = (connect_t) dlsym(RTLD_NEXT, "connect");
@ -200,21 +200,27 @@ static inline void get_chain_data(
if(buff[0] != '\n' && buff[strspn(buff," ")]!='#') {
if(list) {
memset(&pd[count], 0, sizeof(proxy_data));
pd[count].ps=PLAY_STATE;
port_n=0;
sscanf(buff,"%s %s %d %s %s", type,host,&port_n,
pd[count].user,pd[count].pass);
pd[count].ip=inet_addr(host);
pd[count].port=htons((unsigned short)port_n);
if(!strcmp(type,"http")) {
pd[count].pt=HTTP_TYPE;
}else if(!strcmp(type,"socks4")) {
pd[count].pt=SOCKS4_TYPE;
}else if(!strcmp(type,"socks5")) {
pd[count].pt=SOCKS5_TYPE;
}else continue;
if( pd[count].ip && (int) pd[count].ip != -1 && port_n)
pd[count].ps = PLAY_STATE;
port_n = 0;
sscanf(buff,"%s %s %d %s %s", type, host, &port_n,
pd[count].user, pd[count].pass);
pd[count].ip.as_int = (uint32_t) inet_addr(host);
pd[count].port = htons((unsigned short)port_n);
if(!strcmp(type,"http")) {
pd[count].pt = HTTP_TYPE;
} else if(!strcmp(type,"socks4")) {
pd[count].pt = SOCKS4_TYPE;
} else if(!strcmp(type,"socks5")) {
pd[count].pt = SOCKS5_TYPE;
} else
continue;
if(pd[count].ip.as_int && port_n &&
(int) pd[count].ip.as_int != (uint32_t) -1)
if(++count==MAX_CHAIN)
break;
} else {
@ -226,13 +232,11 @@ static inline void get_chain_data(
*ct=STRICT_TYPE;
} else if(strstr(buff,"dynamic_chain")) {
*ct=DYNAMIC_TYPE;
}else if(strstr(buff,"tcp_read_time_out")){
} else if(strstr(buff,"tcp_read_time_out")){
sscanf(buff,"%s %d",user,&tcp_read_time_out) ;
}else if(strstr(buff,"tcp_connect_time_out")){
} else if(strstr(buff,"tcp_connect_time_out")){
sscanf(buff,"%s %d",user,&tcp_connect_time_out) ;
}
else if(strstr(buff,"localnet"))
{
} else if(strstr(buff,"localnet")) {
if (sscanf(buff,"%s %21[^/]/%15s", user,
local_in_addr_port, local_netmask) < 3) {
fprintf(stderr, "localnet format error");
@ -276,15 +280,14 @@ static inline void get_chain_data(
{
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
}
}
else if(strstr(buff,"chain_len")){
} else if(strstr(buff,"chain_len")){
char *pc;int len;
pc=strchr(buff,'=');
len=atoi(++pc);
proxychains_max_chain=(len?len:1);
}else if(strstr(buff,"quiet_mode")){
} else if(strstr(buff,"quiet_mode")){
proxychains_quiet_mode=1;
}else if(strstr(buff,"proxy_dns")){
} else if(strstr(buff,"proxy_dns")){
proxychains_resolver=1;
}
}
@ -301,6 +304,7 @@ int connect (int sock, const struct sockaddr *addr, unsigned int len)
{
int socktype=0, flags=0, ret=0;
socklen_t optlen = 0;
ip_type dest_ip;
#ifdef DEBUG
char str[256];
#endif
@ -335,20 +339,24 @@ int connect (int sock, const struct sockaddr *addr, unsigned int len)
}
}
flags=fcntl(sock, F_GETFL, 0);
flags = fcntl(sock, F_GETFL, 0);
if(flags & O_NONBLOCK)
fcntl(sock, F_SETFL, !O_NONBLOCK);
ret=connect_proxy_chain(
dest_ip.as_int = SOCKADDR(*addr);
ret = connect_proxy_chain(
sock,
SOCKADDR(*addr),
dest_ip,
SOCKPORT(*addr),
proxychains_pd,
proxychains_proxy_count,
proxychains_ct,
proxychains_max_chain );
fcntl(sock, F_SETFL, flags);
if(ret!=SUCCESS)
errno=ECONNREFUSED;
if(ret != SUCCESS)
errno = ECONNREFUSED;
return ret;
}