5.30 hosts support

This commit is contained in:
intika
2019-05-12 01:47:04 +02:00
parent ee8d71fe4c
commit 225ee380ab
7 changed files with 313 additions and 161 deletions

View File

@@ -15,7 +15,7 @@ sysconfdir=$(prefix)/etc
SRCS = $(sort $(wildcard src/*.c))
OBJS = $(SRCS:.c=.o)
LOBJS = src/core.o src/common.o src/libproxybound.o
LOBJS = src/core.o src/common.o src/libproxybound.o src/hostsreader.o src/ip-type.o
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe
LDFLAGS = -shared -fPIC -Wl,--no-as-needed -ldl -lpthread

128
README
View File

@@ -1,128 +0,0 @@
ProxyBound v5.20
================
ProxyBound is a UNIX program, that hooks network-related libc functions
in dynamically linked programs via a preloaded DLL and redirects the
connections through SOCKS4a/5 or HTTP proxies. This is based on
proxychains-ng by rofl0r, proxychains by haad and torsocks by dgoulet
Features:
=========
- Proxify applications (like mainstream proxychains)
- Works with tcp (like mainstream proxychains)
- No leaks over udp/raw/icmp/etc...
- Unsupported protocols are blocked
- Works with chrome/chromium/similar
- Incompatible applications are terminated with a proper message
- Many additional settings over environment variable
- etc.
Used environment variable:
==========================
- PROXYBOUND_CONF_FILE: Path to config file (default ./proxybound.conf then /etc/proxybound.conf)
- PROXYBOUND_QUIET_MODE: Quiet mode (1 or 0, default 0)
- PROXYBOUND_SOCKS5_HOST: Specify unique socks 5 proxy to use (default not used)
- PROXYBOUND_SOCKS5_PORT: Socks 5 port (default not used)
- PROXYBOUND_FORCE_DNS: Force dns resolv requests through (1 or 0, default 1)
- PROXYBOUND_ALLOW_DNS: Allow direct dns, allow udp port 53 and 853 (1 or 0, default 0)
- PROXYBOUND_ALLOW_LEAKS: Allow/Block unproxyfied protocols "UDP/ICMP/RAW", blocked by default (1 or 0, default 0)
- PROXYBOUND_WORKING_INDICATOR: Create '/tmp/proxybound.tmp' when dll is working as intended (1 or 0, default 0)
How it works:
=============
Proxybound hook libc functions like connect(), dynamic loader
facilities are used, namely dl_sym() and LD_PRELOAD thus
dynamically linked programs are required.
Limits :
========
- IPv6 is blocked and is not supported
- Some applications are incompatible (they will be explicitly terminated 2 sec after startup, to avoid leaks)
Install:
========
./configure
make
[optional] sudo make install
if you dont install, you can use proxybound from the build directory
like this: ./proxybound -f src/proxybound.conf telnet google.com 80
Changelog:
==========
Version 5.20:
- add PROXYBOUND_ALLOW_DNS
- update lock feature (send sendto sendmsg)
- add function to terminate when app is not supported
- add PROXYBOUND_WORKING_INDICATOR
- Code cleaning
- Update readme
Version 5.10:
- leak lock feature (send sendto sendmsg)
Version 5.00:
- Initial leak lock feature
- Code cleaning
- Update readme
Version 4.90:
- Import simple SOCKS5 proxy mode from @haad/proxychains
- Code cleaning
- Update readme
Version 4.80:
- Updates with some features from @haad/proxychains
Version 4.70:
- Fix chrome compatibility
Version 4.60:
- Code cleanning & update
Version 4.50:
- Changing the name to ProxyBound
Version 4.40:
- Import security issue fix CVE-2015-3887
- Used v4.3 (4.03) for initial fork
Configuration:
==============
Proxybound config file in following order:
1) File listed in environment variable ${PROXYBOUND_CONF_FILE} or
provided as a -f argument to proxybound script or binary.
2) ./proxybound.conf
3) $(HOME)/.proxybound/proxybound.conf
4) /etc/proxybound.conf
Usage Example:
==============
$ export PROXYBOUND_QUIET_MODE="1"
$ export LD_PRELOAD=/usr/local/lib/libproxybound.so
$ export PROXYBOUND_CONF_FILE=/etc/proxybound.conf
$ telnet targethost.com
In this example it will run telnet through proxy without using proxybound binary
$ proxybound telnet targethost.com
In this example it will run telnet through proxy(or chained proxies) specified by proxybound.conf
$ proxybound -f /etc/proxybound-other.conf targethost2.com
In this example it will use different configuration file then proxybound.conf to connect to targethost2.com host.
$ proxyresolv targethost.com
In this example it will resolve targethost.com through proxy(or chained proxies) specified by proxybound.conf

150
README.md Normal file
View File

@@ -0,0 +1,150 @@
ProxyBound v5.30
================
ProxyBound is a UNIX program, that hooks network-related libc functions in dynamically linked programs via a preloaded DLL and redirects the connections through SOCKS4a/5 or HTTP proxies. This is based on proxychains-ng by rofl0r, proxychains by haad and torsocks by dgoulet
Features:
=========
- Proxify applications (like mainstream proxychains)
- Works with tcp (like mainstream proxychains)
- No leaks over udp/raw/icmp/etc...
- Unsupported protocols are blocked
- Works with chrome/chromium/similar
- Incompatible applications are terminated with a proper message
- Many additional settings over environment variable
- etc.
Used environment variable:
==========================
```
- PROXYBOUND_CONF_FILE: Path to config file (default ./proxybound.conf then /etc/proxybound.conf)
- PROXYBOUND_QUIET_MODE: Quiet mode (1 or 0, default 0)
- PROXYBOUND_SOCKS5_HOST: Specify unique socks 5 proxy to use (default not used)
- PROXYBOUND_SOCKS5_PORT: Socks 5 port (default not used)
- PROXYBOUND_FORCE_DNS: Force dns resolv requests through (1 or 0, default 1)
- PROXYBOUND_ALLOW_DNS: Allow direct dns, allow udp port 53 and 853 (1 or 0, default 0)
- PROXYBOUND_ALLOW_LEAKS: Allow/Block unproxyfied protocols "UDP/ICMP/RAW", blocked by default (1 or 0, default 0)
- PROXYBOUND_WORKING_INDICATOR: Create '/tmp/proxybound.tmp' when dll is working as intended (1 or 0, default 0)
```
How it works:
=============
Proxybound hook libc functions like connect(), dynamic loader facilities are used, namely dl_sym() and LD_PRELOAD thus dynamically linked programs are required.
Limits :
========
- IPv6 is blocked and is not supported
- Some applications are incompatible (they will be explicitly terminated 2 sec after startup, to avoid leaks)
Install:
========
```
./configure
make
[optional] sudo make install
```
if you dont install, you can use proxybound from the build directory like this: `./proxybound -f src/proxybound.conf telnet google.com 80`
Changelog:
==========
**Version 5.30:**
- Code cleaning
- Move readme to md
- Add support for hosts file (upstream import)
**Version 5.20:**
- add PROXYBOUND_ALLOW_DNS
- update lock feature (send sendto sendmsg)
- add function to terminate when app is not supported
- add PROXYBOUND_WORKING_INDICATOR
- Code cleaning
- Update readme
**Version 5.10:**
- leak lock feature (send sendto sendmsg)
**Version 5.00:**
- Initial leak lock feature
- Code cleaning
- Update readme
**Version 4.90:**
- Import simple SOCKS5 proxy mode from @haad/proxychains
- Code cleaning
- Update readme
**Version 4.80:**
- Updates with some features from @haad/proxychains
**Version 4.70:**
- Fix chrome compatibility
**Version 4.60:**
- Code cleanning & update
**Version 4.50:**
- Changing the name to ProxyBound
**Version 4.40:**
- Import security issue fix CVE-2015-3887
- Used v4.3 (4.03) for initial fork
Configuration:
==============
Proxybound config file in following order:
```
1) File listed in environment variable ${PROXYBOUND_CONF_FILE} or
provided as a -f argument to proxybound script or binary.
2) ./proxybound.conf
3) $(HOME)/.proxybound/proxybound.conf
4) /etc/proxybound.conf
```
Usage Example:
==============
In this example it will run telnet through proxy without using proxybound binary
```
$ export PROXYBOUND_QUIET_MODE="1"
$ export LD_PRELOAD=/usr/local/lib/libproxybound.so
$ export PROXYBOUND_CONF_FILE=/etc/proxybound.conf
$ telnet targethost.com
```
In this example it will run telnet through proxy(or chained proxies) specified by proxybound.conf
```
$ proxybound telnet targethost.com
```
In this example it will use different configuration file then proxybound.conf to connect to targethost2.com host.
```
$ proxybound -f /etc/proxybound-other.conf targethost2.com
```
In this example it will resolve targethost.com through proxy(or chained proxies) specified by proxybound.conf
```
$ proxyresolv targethost.com
```

View File

@@ -21,7 +21,6 @@
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/utsname.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -34,22 +33,23 @@
#include <sys/time.h>
#include <stdarg.h>
#include <assert.h>
#include "core.h"
#include "common.h"
#ifdef THREAD_SAFE
#include <pthread.h>
pthread_mutex_t internal_ips_lock;
pthread_mutex_t hostdb_lock;
#endif
#include "core.h"
#include "common.h"
extern int tcp_read_time_out;
extern int tcp_connect_time_out;
extern int proxybound_quiet_mode;
extern unsigned int remote_dns_subnet;
internal_ip_lookup_table internal_ips = { 0, 0, NULL };
extern ip_type hostsreader_get_numeric_ip_for_name(const char* name);
internal_ip_lookup_table internal_ips = { 0, 0, NULL };
uint32_t dalias_hash(char *s0) {
unsigned char *s = (void *) s0;
@@ -254,7 +254,6 @@ static int timed_connect(int sock, const struct sockaddr *addr, socklen_t len) {
return ret;
}
#define INVALID_INDEX 0xFFFFFFFFU
static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, char *user, char *pass) {
char *dns_name = NULL;
@@ -595,7 +594,6 @@ static unsigned int calc_alive(proxy_data * pd, unsigned int proxy_count) {
return alive_count;
}
static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
int retcode = -1;
char *hostname;
@@ -749,8 +747,6 @@ int connect_proxy_chain(int sock, ip_type target_ip,
return -1;
}
static const ip_type local_host = { {127, 0, 0, 1} };
static void gethostbyname_data_setstring(struct gethostbyname_data* data, char* name) {
snprintf(data->addr_name, sizeof(data->addr_name), "%s", name);
data->hostent_space.h_name = data->addr_name;
@@ -763,8 +759,6 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
void *new_mem;
size_t l;
struct hostent *hp;
data->resolved_addr_p[0] = (char *) &data->resolved_addr;
data->resolved_addr_p[1] = NULL;
@@ -781,24 +775,24 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
if(!strcmp(buff, name)) {
data->resolved_addr = inet_addr(buff);
if(data->resolved_addr == (in_addr_t) (-1))
data->resolved_addr = (in_addr_t) (local_host.as_int);
data->resolved_addr = (in_addr_t) (ip_type_localhost.as_int);
goto retname;
}
memset(buff, 0, sizeof(buff));
// this iterates over the "known hosts" db, usually /etc/hosts
MUTEX_LOCK(&hostdb_lock);
while((hp = gethostent()))
if(!strcmp(hp->h_name, name) && hp->h_addrtype == AF_INET && hp->h_length == sizeof(in_addr_t)) {
data->resolved_addr = *((in_addr_t*)(hp->h_addr_list[0]));
MUTEX_UNLOCK(&hostdb_lock);
goto retname;
}
MUTEX_LOCK(&hostdb_lock);
ip_type hdb_res = hostsreader_get_numeric_ip_for_name(name);
//ip_type hdb_res = hdb_get(&hl, (char*) name);
if(hdb_res.as_int != ip_type_invalid.as_int) {
data->resolved_addr = hdb_res.as_int;
MUTEX_UNLOCK(&hostdb_lock);
goto retname;
}
MUTEX_UNLOCK(&hostdb_lock);
hash = dalias_hash((char *) name);
MUTEX_LOCK(&internal_ips_lock);
// see if we already have this dns entry saved.
@@ -811,6 +805,7 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
}
}
}
// grow list if needed.
if(internal_ips.capa < internal_ips.counter + 1) {
PDEBUG("realloc\n");
@@ -819,6 +814,7 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
internal_ips.capa += 16;
internal_ips.list = new_mem;
} else {
// goto ------------
oom:
proxybound_write_log("out of mem\n");
goto err_plus_unlock;
@@ -844,16 +840,16 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
internal_ips.counter += 1;
// goto ------------
have_ip:
MUTEX_UNLOCK(&internal_ips_lock);
// goto ------------
retname:
gethostbyname_data_setstring(data, (char*) name);
gethostbyname_data_setstring(data, (char*) name);
return &data->hostent_space;
// goto ------------
err_plus_unlock:
MUTEX_UNLOCK(&internal_ips_lock);
return NULL;
@@ -899,7 +895,7 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
char buf[1024];
int port;
// printf("proxy_getaddrinfo node %s service %s\n",node,service);
//printf("proxy_getaddrinfo node %s service %s\n",node,service);
space = calloc(1, sizeof(struct addrinfo_data));
if(!space) goto err1;

View File

@@ -20,17 +20,13 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "ip-type.h"
#ifndef __CORE_HEADER
#define __CORE_HEADER
#define BUFF_SIZE 8*1024 // used to read responses from proxies.
#define MAX_LOCALNET 64
typedef union {
unsigned char octet[4];
uint32_t as_int;
} ip_type;
typedef struct {
uint32_t hash;
char* string;

110
src/hostsreader.c Normal file
View File

@@ -0,0 +1,110 @@
/* simple reader for /etc/hosts
it only supports comments, blank lines and lines consisting of an ipv4 hostname pair.
this is required so we can return entries from the host db without messing up the
non-thread-safe state of libc's gethostent(). */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "ip-type.h"
struct hostsreader {
FILE *f;
char* ip, *name;
};
int hostsreader_open(struct hostsreader *ctx) {
if(!(ctx->f = fopen("/etc/hosts", "r"))) return 0;
return 1;
}
void hostsreader_close(struct hostsreader *ctx) {
fclose(ctx->f);
}
static int isnumericipv4(const char* ipstring);
int hostsreader_get(struct hostsreader *ctx, char* buf, size_t bufsize) {
while(1) {
if(!fgets(buf, bufsize, ctx->f)) return 0;
if(*buf == '#') continue;
char *p = buf;
size_t l = bufsize;
ctx->ip = p;
while(*p && !isspace(*p) && l) {
p++;
l--;
}
if(!l || !*p || p == ctx->ip) continue;
*p = 0;
p++;
while(*p && isspace(*p) && l) {
p++;
l--;
}
if(!l || !*p) continue;
ctx->name = p;
while(*p && !isspace(*p) && l) {
p++;
l--;
}
if(!l || !*p) continue;
*p = 0;
if(isnumericipv4(ctx->ip)) return 1;
}
}
char* hostsreader_get_ip_for_name(const char* name, char* buf, size_t bufsize) {
struct hostsreader ctx;
char *res = 0;
if(!hostsreader_open(&ctx)) return 0;
while(hostsreader_get(&ctx, buf, bufsize)) {
if(!strcmp(ctx.name, name)) {
res = ctx.ip;
break;
}
}
hostsreader_close(&ctx);
return res;
}
ip_type hostsreader_get_numeric_ip_for_name(const char* name) {
char *hres;
char buf[320];
if((hres = hostsreader_get_ip_for_name(name, buf, sizeof buf))) {
struct in_addr c;
inet_aton(hres, &c);
ip_type res;
memcpy(res.octet, &c.s_addr, 4);
return res;
} else return ip_type_invalid;
}
/* isnumericipv4() taken from libulz */
static int isnumericipv4(const char* ipstring) {
size_t x = 0, n = 0, d = 0;
int wasdot = 0;
while(1) {
switch(ipstring[x]) {
case 0: goto done;
case '.':
if(!n || wasdot) return 0;
d++;
wasdot = 1;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n++;
wasdot = 0;
break;
default:
return 0;
}
x++;
}
done:
if(d == 3 && n >= 4 && n <= 12) return 1;
return 0;
}

28
src/ip-type.h Normal file
View File

@@ -0,0 +1,28 @@
#include <stdint.h>
typedef union {
unsigned char octet[4];
uint32_t as_int;
} ip_type;
const ip_type ip_type_invalid = { .as_int = -1 };
const ip_type ip_type_localhost = { {127, 0, 0, 1} };
// Definition for ipv6
/*
typedef union {
unsigned char octet[4];
uint32_t as_int;
} ip_type4;
typedef struct {
union {
ip_type4 v4;
unsigned char v6[16];
} addr;
char is_v6;
} ip_type;
const ip_type ip_type_invalid = { .addr.v4.as_int = -1 };
const ip_type ip_type_localhost = { .addr.v4.octet = {127, 0, 0, 1} };
*/