41 Commits

Author SHA1 Message Date
intika
aabf9dfeb5 v5.60 rewrite core functions (check change log) 2019-05-31 19:42:05 +02:00
intika
d0b562c9b7 code cleaning 2019-05-29 21:03:16 +02:00
intika
76510d068e fix dns/skype proxy 2019-05-29 04:09:22 +02:00
intika
166121a6f9 update debug output 2019-05-29 04:00:21 +02:00
intika
ae650ef746 v5.50 initial bind support 2019-05-20 12:57:46 +02:00
intika
a7b0ed9ae5 initial bind support final 2019-05-20 07:06:21 +02:00
intika
49eee52bf3 initial bind support fix 2019-05-20 06:39:56 +02:00
intika
e9e1b71f71 initial bind support 2019-05-20 06:27:01 +02:00
intika
02e49d8987 v5.5 Block non tcp packet on send() and Prevent bypass noleak 2019-05-20 05:59:41 +02:00
intika
c44925214b update documentation 2019-05-12 02:58:16 +02:00
intika
29709c329d clean 2019-05-12 02:56:20 +02:00
intika
79b5e5d037 update readme 2019-05-12 02:55:22 +02:00
intika
d22c8b701d 5.40 adding help and documentation 2019-05-12 02:53:56 +02:00
intika
5e7371ea5b 5.20 fix release 2019-05-12 02:00:10 +02:00
intika
225ee380ab 5.30 hosts support 2019-05-12 01:47:04 +02:00
intika
ee8d71fe4c Update README 2019-05-07 01:01:40 +02:00
intika
926f88a37f Update README 2019-05-06 23:42:45 +02:00
intika
db55059f7a update readme 2019-03-04 04:56:55 +01:00
intika
72e6a79ec8 update readme 2019-03-04 04:49:50 +01:00
intika
2afabd099e Release v5.2 2019-03-04 04:35:17 +01:00
intika
7b96064b85 fix PROXYBOUND_ALLOW_DNS 2019-03-04 01:24:40 +01:00
intika
2acf3f984f Clean bins 2019-03-04 01:13:56 +01:00
intika
9f3547873c PROXYBOUND_ALLOW_DNS 2019-03-04 01:13:29 +01:00
intika
0546f807ee set proxify dns by default 2019-03-04 00:32:00 +01:00
intika
adf83f7b98 block udp sendmsg sendto 2019-03-04 00:27:04 +01:00
intika
c38bd90863 block udp sendto 2019-03-03 20:13:11 +01:00
intika
d0f3a6e7c5 PROXYBOUND_ALLOW_LEAKS in connect() 2019-03-03 19:39:46 +01:00
intika
d669d49e9b Debug version 2019-03-03 06:05:31 +01:00
intika
6057e27cf9 Reject UDP requests to non-local addresses on connect() 2019-03-03 03:10:30 +01:00
intika
96d51f2ff6 Initial block udp feature 2019-03-03 02:22:57 +01:00
intika
1d26392034 Initial block udp feature 2019-03-03 02:22:40 +01:00
intika
c3fd2daf07 update readme 2019-03-02 22:27:50 +01:00
intika
ae19b49bee Revert readme changes 2019-03-02 22:21:08 +01:00
intika
4eb5b8aa6f Add socks 5 env & other settings 2019-03-02 22:18:55 +01:00
intika
6e16c21922 Fix compilation error in get_config_path() 2019-03-02 20:49:53 +01:00
intika
1b60c84e15 better random proxy selection 2019-03-02 20:46:28 +01:00
intika
c97f93a24a Fix wrong glibc prototype 2019-03-02 20:26:47 +01:00
intika
2232f02558 Revert to 4-Nov to fix chrome compatibility 2019-03-02 20:10:02 +01:00
intika
0a56d70577 update 2019-03-01 21:15:10 +01:00
intika
55fbd34bb8 Initial release 2019-03-01 21:07:56 +01:00
intika
ee1a9da2a3 Fix security issue CVE-2015-3887 2019-01-22 14:09:29 +01:00
40 changed files with 1735 additions and 1538 deletions

2
.gitignore vendored
View File

@@ -9,7 +9,7 @@
*~
*.patch
# Autoconf stuff
# Autoconf files
libtool
config.*
stamp-h

24
AUTHORS
View File

@@ -1,23 +1,11 @@
original code up to version 3.1
N3E7CR34TUR3.
http://proxychains.sourceforge.net
netcreature@users.sourceforge.net
Proxybound v4.x: intika https://github.com/Intika-Linux-Proxy/Proxybound
main.c, remote-dns, thread safety, bugfixes, build system,
cleanups, mac support
rofl0r.
https://github.com/rofl0r/proxychains
Proxychains-ng v4.x: rofl0r https://github.com/rofl0r/proxychains
localnet, bugfixes
jianing yang.
https://github.com/jianingy/proxychains
https://sourceforge.net/projects/proxychains/forums/forum/644747/topic/3498696
Proxychains v4.x: jianingy https://github.com/jianingy/proxychains
poll_retry (fixes for signal handling)
colin cross.
https://sourceforge.net/projects/proxychains/forums/forum/644747/topic/2367923
Proxychains v4.x: colin-cross https://sourceforge.net/projects/proxychains/forums/forum/644747/topic/2367923
collecting patches from px forum and putting it into a repo
adam hamsik.
https://github.com/haad/proxychains
Proxychains v4.x: haad https://github.com/haad/proxychains
Proxychains v3.1: N3E7CR34TUR3 http://proxychains.sourceforge.net

View File

@@ -1,65 +0,0 @@
ProxyChains version history (public releases)
====================
ver 3.1
changed:
* dns resolver script fix
* prototypes in core.h
-------------------------------------------------------------------------
ver 3.0
added:
* new feature - DNS from behind proxy
* proxyresolv - stand alone command
* proxychains.conf - new option to enable/disable DNS support
changed:
* bugfixes in core lib
* fixed strict chain
* fixed random chain
* output text
* autotools fix
-------------------------------------------------------------------------
ver 2.1
* bugfuxes
-------------------------------------------------------------------------
ver 2.0
* major core rewrite
* new config options
-------------------------------------------------------------------------
ver 1.8.2
* minor bugfixes
* improved compilation on FreeBSD & OpenBSD sysems.
* improved compilation on Sun Solaris systems .
* cross platform (UNIX) issues
-------------------------------------------------------------------------
ver 1.8.0
added:
* Socks5 protocol
* Socks4 protocol
* HTTP proxy auth basic
* Socks4 user auth
* Socks5 user/pass auth
* more chain options (random, strict, dynamic )
* configurable timeout for TCP connect.
* configurable timeout for TCP read.
* INSTALL file (explains how to install properly)
changed:
* configuration file entries (proxychains.conf)
* configuration file lookup
-------------------------------------------------------------------------
ver 0.0.1
* TCP calls interception
* HTTP CONNECT proxy protocol.

View File

View File

@@ -1,5 +1,5 @@
#
# Makefile for proxychains (requires GNU make), stolen from musl
# Makefile for proxybound
#
# Use config.mak to override any of the following variables.
# Do not make changes here.
@@ -15,9 +15,7 @@ sysconfdir=$(prefix)/etc
SRCS = $(sort $(wildcard src/*.c))
OBJS = $(SRCS:.c=.o)
LOBJS = src/core.o src/common.o src/libproxychains.o src/shm.o \
src/allocator_thread.o src/ip_type.o src/stringdump.o \
src/hostentdb.o src/hash.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
@@ -32,11 +30,11 @@ INSTALL_FLAGS = -D -m
-include config.mak
LDSO_PATHNAME = libproxychains4.$(LDSO_SUFFIX)
LDSO_PATHNAME = libproxybound.$(LDSO_SUFFIX)
SHARED_LIBS = $(LDSO_PATHNAME)
ALL_LIBS = $(SHARED_LIBS)
PXCHAINS = proxychains4
PXCHAINS = proxybound
ALL_TOOLS = $(PXCHAINS)
@@ -46,9 +44,12 @@ CFLAGS_MAIN=-DLIB_DIR=\"$(libdir)\" -DSYSCONFDIR=\"$(sysconfdir)\" -DDLL_NAME=\"
all: $(ALL_LIBS) $(ALL_TOOLS)
debug: CFLAGS += -D DEBUG
debug: $(ALL_LIBS) $(ALL_TOOLS)
install-config:
install -d $(DESTDIR)/$(sysconfdir)
install $(INSTALL_FLAGS) 644 src/proxychains.conf $(DESTDIR)/$(sysconfdir)/
install $(INSTALL_FLAGS) 644 src/proxybound.conf $(DESTDIR)/$(sysconfdir)/
install:
install -d $(DESTDIR)/$(bindir)/ $(DESTDIR)/$(libdir)/

121
README
View File

@@ -1,121 +0,0 @@
ProxyChains ver 4.3 README
==========================
ProxyChains 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.
*********** ATTENTION ***********
this program works only on dynamically linked programs.
also both proxychains and the program to call must use
the same dynamic linker (i.e. same libc).
why ? because in order to hook to libc functions like
connect(), dynamic loader facilities are used, namely
dl_sym() and LD_PRELOAD.
*********************************
*** Installation ***
# needs a working C compiler, preferably gcc
./configure
make
[optional] sudo make install
if you dont install, you can use proxychains from the build directory
like this: ./proxychains4 -f src/proxychains.conf telnet google.com 80
Changelog:
----------
Version 4.3:
- fixes programs that do dns-lookups in child processes (fork()ed),
like irssi. to achieve this, support for compilation without pthreads
was sacrified.
- fixes thread safety for gethostent() calls.
- improved DNS handling speed, since hostent db is cached.
Version 4.2:
- fixes compilation issues with ubuntu 12.04 toolchain
- fixes segfault in rare codepath
Version 4.1
- support for mac os x (all archs)
- all internal functions are threadsafe when compiled with -DTHREAD_SAFE
(default).
Version 4.0
- replaced dnsresolver script (which required a dynamically linked "dig"
binary to be present) with remote DNS lookup.
this speeds up any operation involving DNS, as the old script had to use TCP.
additionally it allows to use .onion urls when used with TOR.
- removed broken autoconf build system with a simple Makefile.
there's a ./configure script though for convenience.
it also adds support for a config file passed via command line switches/
environment variables.
Version 3.0
- support for DNS resolving through proxy
supports SOCKS4, SOCKS5 and HTTP CONNECT proxy servers.
Auth-types: socks - "user/pass" , http - "basic".
When to use it ?
1) When the only way to get "outside" from your LAN is through proxy server.
2) To get out from behind restrictive firewall which filters outgoing ports.
3) To use two (or more) proxies in chain:
like: your_host <--> proxy1 <--> proxy2 <--> target_host
4) To "proxify" some program with no proxy support built-in (like telnet)
5) Access intranet from outside via proxy.
6) To use DNS behind proxy.
7) To access hidden tor onion services.
Some cool features:
* This program can mix different proxy types in the same chain
like: your_host <-->socks5 <--> http <--> socks4 <--> target_host
* Different chaining options supported
random order from the list ( user defined length of chain ).
exact order (as they appear in the list )
dynamic order (smart exclude dead proxies from chain)
* You can use it with any TCP client application, even network scanners
yes, yes - you can make portscan via proxy (or chained proxies)
for example with Nmap scanner by fyodor (www.insecire.org/nmap).
proxychains nmap -sT -PO -p 80 -iR (find some webservers through proxy)
* You can use it with servers, like squid, sendmail, or whatever.
* DNS resolving through proxy.
Configuration:
--------------
proxychains looks for config file in following order:
1) file listed in environment variable ${PROXYCHAINS_CONF_FILE} or
provided as a -f argument to proxychains script or binary.
2) ./proxychains.conf
3) $(HOME)/.proxychains/proxychains.conf
4) /etc/proxychains.conf **
**see more in /etc/proxychains.conf
Usage Example:
$ proxychains telnet targethost.com
in this example it will run telnet through proxy(or chained proxies)
specified by proxychains.conf
Usage Example:
$ proxychains -f /etc/proxychains-other.conf targethost2.com
in this example it will use different configuration file then proxychains.conf
to connect to targethost2.com host.
Usage Example:
$ proxyresolv targethost.com
in this example it will resolve targethost.com through proxy(or chained proxies)
specified by proxychains.conf

184
README.md Normal file
View File

@@ -0,0 +1,184 @@
ProxyBound v5.60
================
ProxyBound force any unix application to use a specific proxy and prevent it from leaking the original ip; Technically, 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 project is based on proxychain by [netcreature](https://sourceforge.net/u/netcreature/profile/), 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/icmp/etc... (INET & INET6)
- Unsupported protocols are blocked
- Support chrome/chromium/skype/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/ETC", 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.
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`
Install debug version :
=======================
```
./configure
make debug
[optional] sudo make install
```
Changelog:
==========
**Version 5.60:**
- Fix skype compatibility
- Improve no leak feature
- Improve debug version
- Improve output/log messages
- Rewrite main hooked functions connect
- Rewrite main hooked functions bind
- Rewrite main hooked functions sendmsg
- Rewrite main hooked functions sendto
- Rewrite main hooked functions send
**Version 5.50:**
- Block non tcp packet on send()
- Prevent bypass noleak
- Add support for bind() to block listen on unsupported protocol
- Add skype support
**Version 5.40:**
- Add "--help" and "-h" parameter
- Add "--version" and "-v" parameter
- Update help page
**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
Limits :
========
- IPv6 is blocked and not supported (currently partially supported)
- Some applications are incompatible (they will be explicitly terminated 2 sec after startup, to avoid leaks)
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
```

7
TODO
View File

@@ -1,7 +0,0 @@
ProxyChains ver 4.0 TODO
===================
hooks for reentrant dns functions, i.e. gethostbyaddr_r

6
dist/config.mak vendored
View File

@@ -1,7 +1,7 @@
### config.mak template for proxychains
#######################################
### config.mak template for proxybound
######################################
# just copy into proxychains root dir and adapt to your needs.
# just copy into proxybound root dir and adapt to your needs.
prefix = /usr/local/
libdir = $(prefix)/lib

View File

@@ -1,289 +0,0 @@
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/select.h>
#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include "allocator_thread.h"
#include "shm.h"
#include "debug.h"
#include "ip_type.h"
#include "mutex.h"
#include "hash.h"
#include "stringdump.h"
/* stuff for our internal translation table */
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;
pthread_mutex_t internal_ips_lock;
internal_ip_lookup_table *internal_ips = NULL;
internal_ip_lookup_table internal_ips_buf;
uint32_t index_from_internal_ip(ip_type internalip) {
PFUNC();
ip_type tmp = internalip;
uint32_t ret;
ret = tmp.octet[3] + (tmp.octet[2] << 8) + (tmp.octet[1] << 16);
ret -= 1;
return ret;
}
char *string_from_internal_ip(ip_type internalip) {
PFUNC();
char *res = NULL;
uint32_t index = index_from_internal_ip(internalip);
if(index < internal_ips->counter)
res = internal_ips->list[index]->string;
return res;
}
extern unsigned int remote_dns_subnet;
ip_type make_internal_ip(uint32_t index) {
ip_type ret;
index++; // so we can start at .0.0.1
if(index > 0xFFFFFF)
return ip_type_invalid;
ret.octet[0] = remote_dns_subnet & 0xFF;
ret.octet[1] = (index & 0xFF0000) >> 16;
ret.octet[2] = (index & 0xFF00) >> 8;
ret.octet[3] = index & 0xFF;
return ret;
}
static ip_type ip_from_internal_list(char* name, size_t len) {
uint32_t hash = dalias_hash((char *) name);
size_t i;
ip_type res;
void* new_mem;
// see if we already have this dns entry saved.
if(internal_ips->counter) {
for(i = 0; i < internal_ips->counter; i++) {
if(internal_ips->list[i]->hash == hash && !strcmp(name, internal_ips->list[i]->string)) {
res = make_internal_ip(i);
PDEBUG("got cached ip for %s\n", name);
goto have_ip;
}
}
}
// grow list if needed.
if(internal_ips->capa < internal_ips->counter + 1) {
PDEBUG("realloc\n");
new_mem = realloc(internal_ips->list, (internal_ips->capa + 16) * sizeof(void *));
if(new_mem) {
internal_ips->capa += 16;
internal_ips->list = new_mem;
} else {
oom:
PDEBUG("out of mem\n");
goto err_plus_unlock;
}
}
res = make_internal_ip(internal_ips->counter);
if(res.as_int == ip_type_invalid.as_int)
goto err_plus_unlock;
string_hash_tuple tmp = { 0 };
new_mem = dumpstring((char*) &tmp, sizeof(string_hash_tuple));
if(!new_mem)
goto oom;
PDEBUG("creating new entry %d for ip of %s\n", (int) internal_ips->counter, name);
internal_ips->list[internal_ips->counter] = new_mem;
internal_ips->list[internal_ips->counter]->hash = hash;
new_mem = dumpstring((char*) name, len + 1);
if(!new_mem) {
internal_ips->list[internal_ips->counter] = 0;
goto oom;
}
internal_ips->list[internal_ips->counter]->string = new_mem;
internal_ips->counter += 1;
have_ip:
return res;
err_plus_unlock:
PDEBUG("return err\n");
return ip_type_invalid;
}
/* stuff for communication with the allocator thread */
enum at_msgtype {
ATM_GETIP,
ATM_GETNAME,
ATM_EXIT,
};
enum at_direction {
ATD_SERVER = 0,
ATD_CLIENT,
ATD_MAX,
};
struct at_msghdr {
enum at_msgtype msgtype;
size_t datalen;
};
static pthread_t allocator_thread;
static pthread_attr_t allocator_thread_attr;
static int req_pipefd[2];
static int resp_pipefd[2];
static int wait_data(int readfd) {
PFUNC();
fd_set fds;
FD_ZERO(&fds);
FD_SET(readfd, &fds);
int ret;
while((ret = select(readfd+1, &fds, NULL, NULL, NULL)) <= 0) {
if(ret < 0) {
perror("select2");
return 0;
}
}
return 1;
}
static int sendmessage(enum at_direction dir, struct at_msghdr *hdr, void* data) {
static int* destfd[ATD_MAX] = { [ATD_SERVER] = &req_pipefd[1], [ATD_CLIENT] = &resp_pipefd[1] };
int ret = write(*destfd[dir], hdr, sizeof *hdr) == sizeof *hdr;
if(ret && hdr->datalen) {
assert(hdr->datalen <= MSG_LEN_MAX);
ret = write(*destfd[dir], data, hdr->datalen) == hdr->datalen;
}
return ret;
}
static int getmessage(enum at_direction dir, struct at_msghdr *hdr, void* data) {
static int* readfd[ATD_MAX] = { [ATD_SERVER] = &req_pipefd[0], [ATD_CLIENT] = &resp_pipefd[0] };
int ret;
if((ret = wait_data(*readfd[dir]))) {
ret = read(*readfd[dir], hdr, sizeof *hdr) == sizeof(*hdr);
assert(hdr->datalen <= MSG_LEN_MAX);
if(ret && hdr->datalen) {
ret = read(*readfd[dir], data, hdr->datalen) == hdr->datalen;
}
}
return ret;
}
static void* threadfunc(void* x) {
(void) x;
int ret;
struct at_msghdr msg;
union {
char host[MSG_LEN_MAX];
ip_type ip;
} readbuf;
while((ret = getmessage(ATD_SERVER, &msg, &readbuf))) {
switch(msg.msgtype) {
case ATM_GETIP:
/* client wants an ip for a DNS name. iterate our list and check if we have an existing entry.
* if not, create a new one. */
readbuf.ip = ip_from_internal_list(readbuf.host, msg.datalen - 1);
msg.datalen = sizeof(ip_type);
break;
case ATM_GETNAME: {
char *host = string_from_internal_ip(readbuf.ip);
if(host) {
size_t l = strlen(host);
assert(l < MSG_LEN_MAX);
memcpy(readbuf.host, host, l + 1);
msg.datalen = l + 1;
}
break;
}
case ATM_EXIT:
return 0;
default:
abort();
}
ret = sendmessage(ATD_CLIENT, &msg, &readbuf);
}
return 0;
}
/* API to access the internal ip mapping */
ip_type at_get_ip_for_host(char* host, size_t len) {
ip_type readbuf;
MUTEX_LOCK(&internal_ips_lock);
if(len > MSG_LEN_MAX) goto inv;
struct at_msghdr msg = {.msgtype = ATM_GETIP, .datalen = len + 1 };
if(sendmessage(ATD_SERVER, &msg, host) &&
getmessage(ATD_CLIENT, &msg, &readbuf));
else {
inv:
readbuf = ip_type_invalid;
}
MUTEX_UNLOCK(&internal_ips_lock);
return readbuf;
}
size_t at_get_host_for_ip(ip_type ip, char* readbuf) {
struct at_msghdr msg = {.msgtype = ATM_GETNAME, .datalen = sizeof(ip_type) };
size_t res = 0;
MUTEX_LOCK(&internal_ips_lock);
if(sendmessage(ATD_SERVER, &msg, &ip) && getmessage(ATD_CLIENT, &msg, readbuf)) {
if((ptrdiff_t) msg.datalen <= 0) res = 0;
else res = msg.datalen - 1;
}
MUTEX_UNLOCK(&internal_ips_lock);
return res;
}
static void initpipe(int* fds) {
if(pipe(fds) == -1) {
perror("pipe");
exit(1);
}
}
/* initialize with pointers to shared memory. these will
* be used to place responses and arguments */
void at_init(void) {
PFUNC();
MUTEX_INIT(&internal_ips_lock);
internal_ips = &internal_ips_buf;
memset(internal_ips, 0, sizeof *internal_ips);
initpipe(req_pipefd);
initpipe(resp_pipefd);
pthread_attr_init(&allocator_thread_attr);
pthread_attr_setstacksize(&allocator_thread_attr, 16 * 1024);
pthread_create(&allocator_thread, &allocator_thread_attr, threadfunc, 0);
}
void at_close(void) {
PFUNC();
const int msg = ATM_EXIT;
write(req_pipefd[1], &msg, sizeof(int));
pthread_join(allocator_thread, NULL);
close(req_pipefd[0]);
close(req_pipefd[1]);
close(resp_pipefd[0]);
close(resp_pipefd[1]);
pthread_attr_destroy(&allocator_thread_attr);
MUTEX_DESTROY(&internal_ips_lock);
}

View File

@@ -1,15 +0,0 @@
#ifndef ALLOCATOR_THREAD_H
#define ALLOCATOR_THREAD_H
#include <unistd.h>
#include "ip_type.h"
#define MSG_LEN_MAX 256
void at_init(void);
void at_close(void);
size_t at_get_host_for_ip(ip_type ip, char* readbuf);
ip_type at_get_ip_for_host(char* host, size_t len);
//RcB: DEP "allocator_thread.c"
#endif

View File

@@ -3,30 +3,6 @@
#include <unistd.h>
#include <stdio.h>
// stolen from libulz (C) rofl0r
void pc_stringfromipv4(unsigned char *ip_buf_4_bytes, char *outbuf_16_bytes) {
unsigned char *p;
char *o = outbuf_16_bytes;
unsigned char n;
for(p = ip_buf_4_bytes; p < ip_buf_4_bytes + 4; p++) {
n = *p;
if(*p >= 100) {
if(*p >= 200)
*(o++) = '2';
else
*(o++) = '1';
n %= 100;
}
if(*p >= 10) {
*(o++) = (n / 10) + '0';
n %= 10;
}
*(o++) = n + '0';
*(o++) = '.';
}
o[-1] = 0;
}
static int check_path(char *path) {
if(!path)
return 0;
@@ -39,33 +15,38 @@ char *get_config_path(char* default_path, char* pbuf, size_t bufsize) {
char *path = default_path;
if(check_path(path))
goto have;
if (!pbuf) {
perror("couldnt find configuration file");
exit(1);
}
// priority 1: env var PROXYCHAINS_CONF_FILE
path = getenv(PROXYCHAINS_CONF_FILE_ENV_VAR);
// priority 1: env var PROXYBOUND_CONF_FILE
path = getenv(PROXYBOUND_CONF_FILE_ENV_VAR);
if(check_path(path))
goto have;
// priority 2; proxychains conf in actual dir
// priority 2; proxybound conf in actual dir
path = getcwd(buf, sizeof(buf));
snprintf(pbuf, bufsize, "%s/%s", path, PROXYCHAINS_CONF_FILE);
snprintf(pbuf, bufsize, "%s/%s", path, PROXYBOUND_CONF_FILE);
path = pbuf;
if(check_path(path))
goto have;
// priority 3; $HOME/.proxychains/proxychains.conf
// priority 3; $HOME/.proxybound/proxybound.conf
path = getenv("HOME");
snprintf(pbuf, bufsize, "%s/.proxychains/%s", path, PROXYCHAINS_CONF_FILE);
snprintf(pbuf, bufsize, "%s/.proxybound/%s", path, PROXYBOUND_CONF_FILE);
path = pbuf;
if(check_path(path))
goto have;
// priority 4: $SYSCONFDIR/proxychains.conf
path = SYSCONFDIR "/" PROXYCHAINS_CONF_FILE;
// priority 4: $SYSCONFDIR/proxybound.conf
path = SYSCONFDIR "/" PROXYBOUND_CONF_FILE;
if(check_path(path))
goto have;
// priority 5: /etc/proxychains.conf
path = "/etc/" PROXYCHAINS_CONF_FILE;
// priority 5: /etc/proxybound.conf
path = "/etc/" PROXYBOUND_CONF_FILE;
if(check_path(path))
goto have;

View File

@@ -1,10 +1,13 @@
#ifndef COMMON_H
#define COMMON_H
#define PROXYCHAINS_CONF_FILE_ENV_VAR "PROXYCHAINS_CONF_FILE"
#define PROXYCHAINS_QUIET_MODE_ENV_VAR "PROXYCHAINS_QUIET_MODE"
#define PROXYCHAINS_CONF_FILE "proxychains.conf"
#define LOG_PREFIX "[proxychains] "
#define PROXYBOUND_CONF_FILE_ENV_VAR "PROXYBOUND_CONF_FILE"
#define PROXYBOUND_QUIET_MODE_ENV_VAR "PROXYBOUND_QUIET_MODE"
#define PROXYBOUND_SOCKS5_HOST_ENV_VAR "PROXYBOUND_SOCKS5_HOST"
#define PROXYBOUND_SOCKS5_PORT_ENV_VAR "PROXYBOUND_SOCKS5_PORT"
#define PROXYBOUND_FORCE_DNS_ENV_VAR "PROXYBOUND_FORCE_DNS"
#define PROXYBOUND_ALLOW_LEAKS_ENV_VAR "PROXYBOUND_ALLOW_LEAKS"
#define PROXYBOUND_ALLOW_DNS_ENV_VAR "PROXYBOUND_ALLOW_DNS"
#define PROXYBOUND_WORKING_INDICATOR_ENV_VAR "PROXYBOUND_WORKING_INDICATOR"
#define PROXYBOUND_CONF_FILE "proxybound.conf"
#define LOG_PREFIX "[Proxybound] "
#ifndef SYSCONFDIR
#define SYSCONFDIR "/etc"
#endif
@@ -12,7 +15,5 @@
#include <stddef.h>
char *get_config_path(char* default_path, char* pbuf, size_t bufsize);
void pc_stringfromipv4(unsigned char *ip_buf_4_bytes, char *outbuf_16_bytes);
//RcB: DEP "common.c"
#endif
//RcB: DEP "common.c"

View File

@@ -1,8 +1,8 @@
/***************************************************************************
core.c - description
-------------------
core.c
------
begin : Tue May 14 2002
copyright : netcreature (C) 2002
copyright : netcreature (C) 2002
email : netcreature@users.sourceforge.net
***************************************************************************
* GPL *
@@ -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,17 +33,88 @@
#include <sys/time.h>
#include <stdarg.h>
#include <assert.h>
#include "core.h"
#include "common.h"
#include "shm.h"
#include "allocator_thread.h"
#ifdef THREAD_SAFE
#include <pthread.h>
pthread_mutex_t internal_ips_lock;
pthread_mutex_t hostdb_lock;
#endif
extern int tcp_read_time_out;
extern int tcp_connect_time_out;
extern int proxychains_quiet_mode;
extern int proxybound_quiet_mode;
extern unsigned int remote_dns_subnet;
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;
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);
ret -= 1;
return ret;
}
char *string_from_internal_ip(ip_type internalip) {
char *res = NULL;
uint32_t index = index_from_internal_ip(internalip);
MUTEX_LOCK(&internal_ips_lock);
if(index < internal_ips.counter)
res = internal_ips.list[index]->string;
MUTEX_UNLOCK(&internal_ips_lock);
return res;
}
in_addr_t make_internal_ip(uint32_t index) {
ip_type ret;
index++; // so we can start at .0.0.1
if(index > 0xFFFFFF)
return (in_addr_t) - 1;
ret.octet[0] = remote_dns_subnet & 0xFF;
ret.octet[1] = (index & 0xFF0000) >> 16;
ret.octet[2] = (index & 0xFF00) >> 8;
ret.octet[3] = index & 0xFF;
return (in_addr_t) ret.as_int;
}
// stolen from libulz (C) rofl0r
void pc_stringfromipv4(unsigned char *ip_buf_4_bytes, char *outbuf_16_bytes) {
unsigned char *p;
char *o = outbuf_16_bytes;
unsigned char n;
for(p = ip_buf_4_bytes; p < ip_buf_4_bytes + 4; p++) {
n = *p;
if(*p >= 100) {
if(*p >= 200)
*(o++) = '2';
else
*(o++) = '1';
n %= 100;
}
if(*p >= 10) {
*(o++) = (n / 10) + '0';
n %= 10;
}
*(o++) = n + '0';
*(o++) = '.';
}
o[-1] = 0;
}
static int poll_retry(struct pollfd *fds, nfds_t nfsd, int timeout) {
int ret;
int time_remain = timeout;
@@ -105,10 +175,10 @@ static void encode_base_64(char *src, char *dest, int max_len) {
*dest++ = 0;
}
void proxychains_write_log(char *str, ...) {
void proxybound_write_log(char *str, ...) {
char buff[1024*20];
va_list arglist;
if(!proxychains_quiet_mode) {
if(!proxybound_quiet_mode) {
va_start(arglist, str);
vsnprintf(buff, sizeof(buff), str, arglist);
va_end(arglist);
@@ -150,21 +220,20 @@ static int timed_connect(int sock, const struct sockaddr *addr, socklen_t len) {
int ret, value;
socklen_t value_len;
struct pollfd pfd[1];
PFUNC();
pfd[0].fd = sock;
pfd[0].events = POLLOUT;
fcntl(sock, F_SETFL, O_NONBLOCK);
ret = true_connect(sock, addr, len);
PDEBUG("\nconnect ret=%d\n", ret);
PDEBUG("timed_connect: core.c: ret=%d\n", ret);
if(ret == -1 && errno == EINPROGRESS) {
ret = poll_retry(pfd, 1, tcp_connect_time_out);
PDEBUG("\npoll ret=%d\n", ret);
PDEBUG("timed_connect: core.c: poll ret=%d\n", ret);
if(ret == 1) {
value_len = sizeof(socklen_t);
getsockopt(sock, SOL_SOCKET, SO_ERROR, &value, &value_len);
PDEBUG("\nvalue=%d\n", value);
PDEBUG("timed_connect: core.c: value=%d\n", value);
if(!value)
ret = 0;
else
@@ -185,32 +254,33 @@ 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;
char hostnamebuf[MSG_LEN_MAX];
size_t dns_len = 0;
PFUNC();
PDEBUG("tunnel_to: core.c: init tunnel_to()\n");
// 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.)
// the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
if(ip.octet[0] == remote_dns_subnet) {
dns_len = at_get_host_for_ip(ip, hostnamebuf);
if(!dns_len) goto err;
else dns_name = hostnamebuf;
dns_name = string_from_internal_ip(ip);
if(!dns_name)
goto err;
dns_len = strlen(dns_name);
if(!dns_len)
goto err;
}
PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>");
PDEBUG("tunnel_to: core.c: host dns %s\n", dns_name ? dns_name : "<NULL>");
size_t ulen = strlen(user);
size_t passlen = strlen(pass);
if(ulen > 0xFF || passlen > 0xFF || dns_len > 0xFF) {
proxychains_write_log(LOG_PREFIX "error: maximum size of 255 for user/pass or domain name!\n");
proxybound_write_log(LOG_PREFIX "ERROR: USER+PASS/DOMAIN SIZE EXCEEDS MAX VALUE OF 255!\n\n\n");
goto err;
}
@@ -423,7 +493,7 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
return SOCKET_ERROR;
}
#define TP " ... "
#define TP "... "
#define DT "Dynamic chain"
#define ST "Strict chain"
#define RT "Random chain"
@@ -437,8 +507,7 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
goto error;
pc_stringfromipv4(&pd->ip.octet[0], ip_buf);
proxychains_write_log(LOG_PREFIX "%s " TP " %s:%d ",
begin_mark, ip_buf, htons(pd->port));
proxybound_write_log(LOG_PREFIX "%s " TP "%s:%d\n", begin_mark, ip_buf, htons(pd->port));
pd->ps = PLAY_STATE;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
@@ -451,13 +520,27 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
pd->ps = BUSY_STATE;
return SUCCESS;
error1:
proxychains_write_log(TP " timeout\n");
proxybound_write_log(LOG_PREFIX TP "timeout\n");
error:
if(*fd != -1)
close(*fd);
return SOCKET_ERROR;
}
unsigned int get_rand_int(unsigned int range){
static FILE *fp;
unsigned int randval;
if (!fp) {
fp = fopen("/dev/urandom", "r");
}
if(fread(&randval, sizeof(randval), 1, fp)) {
return (randval % range);
} else {
srand((unsigned int)time(NULL));
return (rand() % range);
}
}
static proxy_data *select_proxy(select_type how, proxy_data * pd, unsigned int proxy_count, unsigned int *offset) {
unsigned int i = 0, k = 0;
if(*offset >= proxy_count)
@@ -466,7 +549,7 @@ static proxy_data *select_proxy(select_type how, proxy_data * pd, unsigned int p
case RANDOMLY:
do {
k++;
i = 0 + (unsigned int) (proxy_count * 1.0 * rand() / (RAND_MAX + 1.0));
i = 0 + get_rand_int(proxy_count);
} while(pd[i].ps != PLAY_STATE && k < proxy_count * 100);
break;
case FIFOLY:
@@ -510,25 +593,24 @@ 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;
char hostname_buf[MSG_LEN_MAX];
char ip_buf[16];
PFUNC();
PDEBUG("chain_step: core.c: init chain_step()\n");
if(pto->ip.octet[0] == remote_dns_subnet) {
if(!at_get_host_for_ip(pto->ip, hostname_buf)) goto usenumericip;
else hostname = hostname_buf;
hostname = string_from_internal_ip(pto->ip);
if(!hostname)
goto usenumericip;
} else {
usenumericip:
pc_stringfromipv4(&pto->ip.octet[0], ip_buf);
hostname = ip_buf;
}
proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port));
proxybound_write_log(LOG_PREFIX TP "%s:%d\n", hostname, htons(pto->port));
retcode = tunnel_to(ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
switch (retcode) {
case SUCCESS:
@@ -536,12 +618,12 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
break;
case BLOCKED:
pto->ps = BLOCKED_STATE;
proxychains_write_log("<--denied\n");
proxybound_write_log(LOG_PREFIX "denied\n");
close(ns);
break;
case SOCKET_ERROR:
pto->ps = DOWN_STATE;
proxychains_write_log("<--socket error or timeout!\n");
proxybound_write_log(LOG_PREFIX "socket error or timeout!\n");
close(ns);
break;
}
@@ -560,7 +642,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
p3 = &p4;
PFUNC();
PDEBUG("connect: core.c: connect_proxy_chain\n");
again:
@@ -577,12 +659,12 @@ int connect_proxy_chain(int sock, ip_type target_ip,
if(!p2)
break;
if(SUCCESS != chain_step(ns, p1, p2)) {
PDEBUG("GOTO AGAIN 1\n");
PDEBUG("connect: core.c: goto again x1\n");
goto again;
}
p1 = p2;
}
//proxychains_write_log(TP);
//proxybound_write_log(TP);
p3->ip = target_ip;
p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3))
@@ -593,23 +675,23 @@ int connect_proxy_chain(int sock, ip_type target_ip,
alive_count = calc_alive(pd, proxy_count);
offset = 0;
if(!(p1 = select_proxy(FIFOLY, pd, proxy_count, &offset))) {
PDEBUG("select_proxy failed\n");
PDEBUG("connect: core.c: select_proxy failed\n");
goto error_strict;
}
if(SUCCESS != start_chain(&ns, p1, ST)) {
PDEBUG("start_chain failed\n");
PDEBUG("connect: core.c: start_chain failed\n");
goto error_strict;
}
while(offset < proxy_count) {
if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset)))
break;
if(SUCCESS != chain_step(ns, p1, p2)) {
PDEBUG("chain_step failed\n");
PDEBUG("connect: core.c: chain_step failed\n");
goto error_strict;
}
p1 = p2;
}
//proxychains_write_log(TP);
//proxybound_write_log(TP);
p3->ip = target_ip;
p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3))
@@ -629,12 +711,12 @@ int connect_proxy_chain(int sock, ip_type target_ip,
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
goto error_more;
if(SUCCESS != chain_step(ns, p1, p2)) {
PDEBUG("GOTO AGAIN 2\n");
PDEBUG("connect: core.c: goto again x2\n");
goto again;
}
p1 = p2;
}
//proxychains_write_log(TP);
//proxybound_write_log(TP);
p3->ip = target_ip;
p3->port = target_port;
if(SUCCESS != chain_step(ns, p1, p3))
@@ -642,7 +724,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
}
proxychains_write_log(TP " OK\n");
proxybound_write_log(LOG_PREFIX TP "ok\n");
dup2(ns, sock);
close(ns);
return 0;
@@ -653,9 +735,9 @@ int connect_proxy_chain(int sock, ip_type target_ip,
return -1;
error_more:
proxychains_write_log("\n!!!need more proxies!!!\n");
proxybound_write_log(LOG_PREFIX "ERROR: NEED MORE PROXIES!\n\n\n");
error_strict:
PDEBUG("error\n");
PDEBUG("connect: core.c: error\n");
release_all(pd, proxy_count);
if(ns != -1)
@@ -664,24 +746,17 @@ int connect_proxy_chain(int sock, ip_type target_ip,
return -1;
}
#include "hostentdb.h"
struct hostent_list hl;
void core_initialize(void) {
hdb_init(&hl);
}
void core_unload(void) {
}
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;
}
struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data* data) {
PFUNC();
char buff[256];
uint32_t i, hash;
// yep, new_mem never gets freed. once you passed a fake ip to the client, you can't "retreat" it
void *new_mem;
size_t l;
data->resolved_addr_p[0] = (char *) &data->resolved_addr;
data->resolved_addr_p[1] = NULL;
@@ -704,24 +779,79 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
}
memset(buff, 0, sizeof(buff));
// this iterates over the "known hosts" db, usually /etc/hosts
ip_type hdb_res = hdb_get(&hl, (char*) name);
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;
}
data->resolved_addr = at_get_ip_for_host((char*) name, strlen(name)).as_int;
if(data->resolved_addr == (in_addr_t) ip_type_invalid.as_int) return NULL;
MUTEX_UNLOCK(&hostdb_lock);
hash = dalias_hash((char *) name);
MUTEX_LOCK(&internal_ips_lock);
// see if we already have this dns entry saved.
if(internal_ips.counter) {
for(i = 0; i < internal_ips.counter; i++) {
if(internal_ips.list[i]->hash == hash && !strcmp(name, internal_ips.list[i]->string)) {
data->resolved_addr = make_internal_ip(i);
PDEBUG("proxy_gethostbyname: core.c: got cached ip for %s\n", name);
goto have_ip;
}
}
}
// grow list if needed.
if(internal_ips.capa < internal_ips.counter + 1) {
PDEBUG("proxy_gethostbyname: core.c: realloc\n");
new_mem = realloc(internal_ips.list, (internal_ips.capa + 16) * sizeof(void *));
if(new_mem) {
internal_ips.capa += 16;
internal_ips.list = new_mem;
} else {
// goto ------------
oom:
proxybound_write_log(LOG_PREFIX "ERROR: OUT OF MEMORY!\n\n\n");
goto err_plus_unlock;
}
}
data->resolved_addr = make_internal_ip(internal_ips.counter);
if(data->resolved_addr == (in_addr_t) - 1)
goto err_plus_unlock;
l = strlen(name);
new_mem = malloc(sizeof(string_hash_tuple) + l + 1);
if(!new_mem)
goto oom;
PDEBUG("proxy_gethostbyname: core.c: creating new entry %d for ip of %s\n", (int) internal_ips.counter, name);
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;
// goto ------------
have_ip:
MUTEX_UNLOCK(&internal_ips_lock);
// goto ------------
retname:
gethostbyname_data_setstring(data, (char*) name);
PDEBUG("return hostent space\n");
gethostbyname_data_setstring(data, (char*) name);
return &data->hostent_space;
// goto ------------
err_plus_unlock:
MUTEX_UNLOCK(&internal_ips_lock);
return NULL;
}
struct addrinfo_data {
@@ -731,7 +861,6 @@ struct addrinfo_data {
};
void proxy_freeaddrinfo(struct addrinfo *res) {
PFUNC();
free(res);
}
@@ -739,7 +868,6 @@ void proxy_freeaddrinfo(struct addrinfo *res) {
/* getservbyname on mac is using thread local storage, so we dont need mutex */
static int getservbyname_r(const char* name, const char* proto, struct servent* result_buf,
char* buf, size_t buflen, struct servent** result) {
PFUNC();
struct servent *res;
int ret;
(void) buf; (void) buflen;
@@ -765,9 +893,8 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
struct addrinfo *p;
char buf[1024];
int port;
PFUNC();
// 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

@@ -1,10 +1,11 @@
/***************************************************************************
core.h - description
-------------------
core.h
------
begin : Tue May 14 2002
copyright : netcreature (C) 2002
email : netcreature@users.sourceforge.net
copyright : netcreature (C) 2002
email : netcreature@users.sourceforge.net
***************************************************************************
* GPL *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
@@ -14,19 +15,42 @@
* *
***************************************************************************/
#include <unistd.h>
#include <stdint.h>
#include <netinet/in.h>
#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
#include "ip_type.h"
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;
#ifdef THREAD_SAFE
#include <pthread.h>
extern pthread_mutex_t internal_ips_lock;
extern pthread_mutex_t hostdb_lock;
# define MUTEX_LOCK(x) pthread_mutex_lock(x)
# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x)
# define MUTEX_INIT(x,y) pthread_mutex_init(x, y)
#else
# define MUTEX_LOCK(x)
# define MUTEX_UNLOCK(x)
# define MUTEX_INIT(x,y)
#endif
/*error codes*/
typedef enum {
@@ -80,19 +104,14 @@ 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 );
void proxychains_write_log(char *str, ...);
void proxybound_write_log(char *str, ...);
typedef int (*connect_t)(int, const struct sockaddr *, socklen_t);
typedef struct hostent* (*gethostbyname_t)(const char *);
typedef int (*freeaddrinfo_t)(struct addrinfo *);
typedef struct hostent *(*gethostbyaddr_t) (const void *, socklen_t, int);
typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *,
struct addrinfo **);
typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *,
socklen_t, char *, socklen_t, int);
typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *, struct addrinfo **);
typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);
extern connect_t true_connect;
extern gethostbyname_t true_gethostbyname;
@@ -100,6 +119,16 @@ extern getaddrinfo_t true_getaddrinfo;
extern freeaddrinfo_t true_freeaddrinfo;
extern getnameinfo_t true_getnameinfo;
extern gethostbyaddr_t true_gethostbyaddr;
typedef ssize_t (*send_t)(int, const void *, size_t, int);
typedef ssize_t (*sendto_t)(int, const void *, size_t, int, const struct sockaddr, socklen_t);
typedef ssize_t (*sendmsg_t)(int, const struct msghdr *, int);
typedef int (*bind_t)(int, const struct sockaddr *, socklen_t);
extern send_t true_send;
extern sendto_t true_sendto;
extern sendmsg_t true_sendmsg;
extern bind_t true_bind;
struct gethostbyname_data {
struct hostent hostent_space;
@@ -114,13 +143,16 @@ int proxy_getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
void proxy_freeaddrinfo(struct addrinfo *res);
void core_initialize(void);
void core_unload(void);
void pc_stringfromipv4(unsigned char *ip_buf_4_bytes, char *outbuf_16_bytes);
#include "debug.h"
#ifdef DEBUG
# define PDEBUG(fmt, args...) do { fprintf(stderr,"DEBUG:"fmt, ## args); fflush(stderr); } while(0)
#else
# define PDEBUG(fmt, args...) do {} while (0)
#endif
#endif
//RcB: DEP "core.c"
//RcB: DEP "libproxychains.c"
//RcB: DEP "libproxybound.c"
//RcB: LINK "-Wl,--no-as-needed -ldl -lpthread"

View File

@@ -1,13 +0,0 @@
#ifndef DEBUG_H
#define DEBUG_H
#ifdef DEBUG
# include <stdio.h>
# define PDEBUG(fmt, args...) do { dprintf(2,"DEBUG:"fmt, ## args); } while(0)
#else
# define PDEBUG(fmt, args...) do {} while (0)
#endif
# define PFUNC() do { PDEBUG("pid[%d]:%s\n", getpid(), __FUNCTION__); } while(0)
#endif

View File

@@ -1,12 +0,0 @@
#include "hash.h"
/* dalias' version of the elf hash */
uint32_t dalias_hash(char *s0) {
unsigned char *s = (void *) s0;
uint_fast32_t h = 0;
while(*s) {
h = 16 * h + *s++;
h ^= h >> 24 & 0xf0;
}
return h & 0xfffffff;
}

View File

@@ -1,10 +0,0 @@
#ifndef HASH_H
#define HASH_H
#include <stdint.h>
uint32_t dalias_hash(char *s0);
//RcB: DEP "hash.c"
#endif

View File

@@ -1,56 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <netdb.h>
#include <stdlib.h>
#include "ip_type.h"
#include "hash.h"
#include "stringdump.h"
#include "hostentdb.h"
#include "common.h"
#include "debug.h"
#define STEP 16
static void hdb_add(struct hostent_list* hl, char* host, ip_type ip) {
if(hl->count +1 > hl->capa) {
void * nu = realloc(hl->entries, (hl->capa + STEP) * sizeof(struct hostent_entry));
if(!nu) return;
hl->entries = nu;
hl->capa += STEP;
}
struct hostent_entry *h = &hl->entries[hl->count];
h->hash = dalias_hash(host);
h->ip.as_int = ip.as_int;
h->str = dumpstring(host, strlen(host) + 1);
if(h->str) hl->count++;
}
static void hdb_fill(struct hostent_list *hl) {
struct hostent* hp;
while((hp = gethostent()))
if(hp->h_addrtype == AF_INET && hp->h_length == sizeof(in_addr_t)) {
hdb_add(hl, hp->h_name, (ip_type) { .as_int = *((in_addr_t*)(hp->h_addr_list[0])) });
}
}
void hdb_init(struct hostent_list *hl) {
memset(hl, 0, sizeof *hl);
hdb_fill(hl);
}
ip_type hdb_get(struct hostent_list *hl, char* host) {
size_t i;
PFUNC();
uint32_t hash = dalias_hash(host);
for(i = 0; i < hl->count; i++) {
if(hl->entries[i].hash == hash && !strcmp(hl->entries[i].str, host)) {
#ifdef DEBUG
char ipbuf[16];
pc_stringfromipv4(hl->entries[i].ip.octet, ipbuf);
PDEBUG("got ip %s for hostent entry %s\n", ipbuf, host);
#endif
return hl->entries[i].ip;
}
}
return ip_type_invalid;
}

View File

@@ -1,23 +0,0 @@
#ifndef HOSTENTDB_H
#define HOSTENTDB_H
#include "ip_type.h"
#include <unistd.h>
struct hostent_entry {
uint32_t hash;
ip_type ip;
char* str;
};
struct hostent_list {
size_t count;
size_t capa;
struct hostent_entry *entries;
};
void hdb_init(struct hostent_list *hl);
ip_type hdb_get(struct hostent_list *hl, char* host);
//RcB: DEP "hostendb.c"
#endif

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;
}

10
src/ip-type.c Normal file
View File

@@ -0,0 +1,10 @@
#include "ip-type.h"
const ip_type ip_type_invalid = { .as_int = -1 };
const ip_type ip_type_localhost = { {127, 0, 0, 1} };
// Definition for ipv6
/*
const ip_type ip_type_invalid = { .addr.v4.as_int = -1 };
const ip_type ip_type_localhost = { .addr.v4.octet = {127, 0, 0, 1} };
*/

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

@@ -0,0 +1,25 @@
#include <stdint.h>
typedef union {
unsigned char octet[4];
uint32_t as_int;
} ip_type;
extern const ip_type ip_type_invalid;
extern const ip_type ip_type_localhost;
// 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;
*/

View File

@@ -1,5 +0,0 @@
#include "ip_type.h"
const ip_type ip_type_invalid = { .as_int = -1 };
const ip_type ip_type_localhost = { {127, 0, 0, 1} };

View File

@@ -1,15 +0,0 @@
#ifndef IP_TYPE_H
#define IP_TYPE_H
#include <stdint.h>
typedef union {
unsigned char octet[4];
uint32_t as_int;
} ip_type;
extern const ip_type ip_type_invalid;
extern const ip_type ip_type_localhost;
//RcB: DEP "ip_type.c"
#endif

937
src/libproxybound.c Normal file
View File

@@ -0,0 +1,937 @@
/***************************************************************************
libproxybound.c
---------------
copyright: intika (C) 2019 intika@librefox.org
copyright: rofl0r (C) 2012 https://github.com/rofl0r
copyright: haad (C) 2012 https://github.com/haad
copyright: netcreature (C) 2002 netcreature@users.sourceforge.net
***************************************************************************
* GPL *
***************************************************************************
* *
* 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 Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#undef _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <dlfcn.h>
#include "core.h"
#include "common.h"
#define satosin(x) ((struct sockaddr_in *) &(x))
#define SOCKADDR(x) (satosin(x)->sin_addr.s_addr)
#define SOCKADDR_2(x) (satosin(x)->sin_addr)
#define SOCKPORT(x) (satosin(x)->sin_port)
#define SOCKFAMILY(x) (satosin(x)->sin_family)
#define MAX_CHAIN 512
connect_t true_connect;
gethostbyname_t true_gethostbyname;
getaddrinfo_t true_getaddrinfo;
freeaddrinfo_t true_freeaddrinfo;
getnameinfo_t true_getnameinfo;
gethostbyaddr_t true_gethostbyaddr;
send_t true_send;
sendto_t true_sendto;
sendmsg_t true_sendmsg;
bind_t true_bind;
int tcp_read_time_out;
int tcp_connect_time_out;
chain_type proxybound_ct;
proxy_data proxybound_pd[MAX_CHAIN];
unsigned int proxybound_proxy_count = 0;
int proxybound_got_chain_data = 0;
unsigned int proxybound_max_chain = 1;
int proxybound_quiet_mode = 0;
int proxybound_allow_leak = 0;
int proxybound_allow_dns = 0;
int proxybound_working_indicator = 0;
int proxybound_resolver = 1;
localaddr_arg localnet_addr[MAX_LOCALNET];
size_t num_localnet_addr = 0;
unsigned int remote_dns_subnet = 224;
#ifdef THREAD_SAFE
pthread_once_t init_once = PTHREAD_ONCE_INIT;
#endif
static int init_l = 0;
static void init_additional_settings(chain_type *ct);
static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
static void manual_socks5_env(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
static int is_dns_port(unsigned short port);
static void create_tmp_proof_file();
static void* load_sym(char* symname, void* proxyfunc) {
void *funcptr = dlsym(RTLD_NEXT, symname);
if(!funcptr) {
fprintf(stderr, "Cannot load symbol '%s' %s\n", symname, dlerror());
exit(1);
} else {
PDEBUG("proxybound: loaded symbol '%s'" " real addr %p wrapped addr %p\n", symname, funcptr, proxyfunc);
}
if(funcptr == proxyfunc) {
PDEBUG("proxybound: circular reference detected, aborting!\n");
abort();
}
return funcptr;
}
#define INIT() init_lib_wrapper(__FUNCTION__)
#define SETUP_SYM(X) do { true_ ## X = load_sym( # X, X ); } while(0)
static void do_init(void) {
MUTEX_INIT(&internal_ips_lock, NULL);
MUTEX_INIT(&hostdb_lock, NULL);
//file to indicate that the injection is working
char *env; env = getenv(PROXYBOUND_WORKING_INDICATOR_ENV_VAR);
if(env && *env == '1') proxybound_working_indicator = 1;
if (proxybound_working_indicator) create_tmp_proof_file();
/* check for simple SOCKS5 proxy setup */
manual_socks5_env(proxybound_pd, &proxybound_proxy_count, &proxybound_ct);
/* read the config file */
get_chain_data(proxybound_pd, &proxybound_proxy_count, &proxybound_ct);
proxybound_write_log(LOG_PREFIX "DLL init\n");
SETUP_SYM(connect);
SETUP_SYM(gethostbyname);
SETUP_SYM(getaddrinfo);
SETUP_SYM(freeaddrinfo);
SETUP_SYM(gethostbyaddr);
SETUP_SYM(getnameinfo);
SETUP_SYM(send);
SETUP_SYM(sendto);
SETUP_SYM(sendmsg);
SETUP_SYM(bind);
init_l = 1;
}
static void init_lib_wrapper(const char* caller) {
#ifndef DEBUG
(void) caller;
#endif
#ifndef THREAD_SAFE
if(init_l) return;
PDEBUG("proxybound: %s called from %s\n", __FUNCTION__, caller);
do_init();
#else
if(!init_l) PDEBUG("proxybound: %s called from %s\n", __FUNCTION__, caller);
pthread_once(&init_once, do_init);
#endif
}
static void create_tmp_proof_file() {
FILE *fp;
if ((fp = fopen("/tmp/proxybound.tmp", "w")) == NULL ) {exit(1); exit(1);}
fprintf(fp, "injected\n");
fflush(fp);fclose(fp);
}
/* if we use gcc >= 3, we can instruct the dynamic loader
* to call init_lib at link time. otherwise it gets loaded
* lazily, which has the disadvantage that there's a potential
* race condition if 2 threads call it before init_l is set
* and PTHREAD support was disabled */
#if __GNUC__ > 2
__attribute__((constructor))
static void gcc_init(void) {
INIT();
}
#endif
static void init_additional_settings(chain_type *ct) {
char *env;
tcp_read_time_out = 4 * 1000;
tcp_connect_time_out = 10 * 1000;
*ct = DYNAMIC_TYPE;
env = getenv(PROXYBOUND_ALLOW_LEAKS_ENV_VAR);
if(env && *env == '1')
proxybound_allow_leak = 1;
env = getenv(PROXYBOUND_ALLOW_DNS_ENV_VAR);
if(env && *env == '1')
proxybound_allow_dns = 1;
env = getenv(PROXYBOUND_QUIET_MODE_ENV_VAR);
if(env && *env == '1')
proxybound_quiet_mode = 1;
}
/* get configuration from config file */
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) {
int count = 0, port_n = 0, list = 0;
char buff[1024], type[1024], host[1024], user[1024];
char *env;
char local_in_addr_port[32];
char local_in_addr[32], local_in_port[32], local_netmask[32];
FILE *file = NULL;
if(proxybound_got_chain_data)
return;
//Some defaults
init_additional_settings(ct);
env = get_config_path(getenv(PROXYBOUND_CONF_FILE_ENV_VAR), buff, sizeof(buff));
file = fopen(env, "r");
while(fgets(buff, sizeof(buff), file)) {
if(buff[0] != '\n' && buff[strspn(buff, " ")] != '#') {
/* proxylist has to come last */
if(list) {
if(count >= MAX_CHAIN)
break;
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.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 && pd[count].ip.as_int != (uint32_t) - 1)
count++;
} else {
if(strstr(buff, "[ProxyList]")) {
list = 1;
} else if(strstr(buff, "random_chain")) {
*ct = RANDOM_TYPE;
} else if(strstr(buff, "strict_chain")) {
*ct = STRICT_TYPE;
} else if(strstr(buff, "dynamic_chain")) {
*ct = DYNAMIC_TYPE;
} 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")) {
sscanf(buff, "%s %d", user, &tcp_connect_time_out);
} else if(strstr(buff, "remote_dns_subnet")) {
sscanf(buff, "%s %d", user, &remote_dns_subnet);
if(remote_dns_subnet >= 256) {
fprintf(stderr,
"remote_dns_subnet: invalid value. requires a number between 0 and 255.\n");
exit(1);
}
} else if(strstr(buff, "localnet")) {
if(sscanf(buff, "%s %21[^/]/%15s", user, local_in_addr_port, local_netmask) < 3) {
fprintf(stderr, "localnet format error");
exit(1);
}
/* clean previously used buffer */
memset(local_in_port, 0, sizeof(local_in_port) / sizeof(local_in_port[0]));
if(sscanf(local_in_addr_port, "%15[^:]:%5s", local_in_addr, local_in_port) < 2) {
PDEBUG("proxybound: added localnet: netaddr=%s, netmask=%s\n",
local_in_addr, local_netmask);
} else {
PDEBUG("proxybound: added localnet: netaddr=%s, port=%s, netmask=%s\n",
local_in_addr, local_in_port, local_netmask);
}
if(num_localnet_addr < MAX_LOCALNET) {
int error;
error =
inet_pton(AF_INET, local_in_addr,
&localnet_addr[num_localnet_addr].in_addr);
if(error <= 0) {
fprintf(stderr, "localnet address error\n");
exit(1);
}
error =
inet_pton(AF_INET, local_netmask,
&localnet_addr[num_localnet_addr].netmask);
if(error <= 0) {
fprintf(stderr, "localnet netmask error\n");
exit(1);
}
if(local_in_port[0]) {
localnet_addr[num_localnet_addr].port =
(short) atoi(local_in_port);
} else {
localnet_addr[num_localnet_addr].port = 0;
}
++num_localnet_addr;
} else {
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
}
} else if(strstr(buff, "chain_len")) {
char *pc;
int len;
pc = strchr(buff, '=');
len = atoi(++pc);
proxybound_max_chain = (len ? len : 1);
} else if(strstr(buff, "quiet_mode")) {
proxybound_quiet_mode = 1;
} else if(strstr(buff, "proxy_dns")) {
proxybound_resolver = 1;
}
}
}
}
fclose(file);
*proxy_count = count;
proxybound_got_chain_data = 1;
}
static void manual_socks5_env(proxy_data *pd, unsigned int *proxy_count, chain_type *ct) {
char *port_string;
char *host_string;
if(proxybound_got_chain_data)
return;
init_additional_settings(ct);
port_string = getenv(PROXYBOUND_SOCKS5_PORT_ENV_VAR);
if(!port_string)
return;
host_string = getenv(PROXYBOUND_SOCKS5_HOST_ENV_VAR);
if(!host_string)
host_string = "127.0.0.1";
memset(pd, 0, sizeof(proxy_data));
pd[0].ps = PLAY_STATE;
pd[0].ip.as_int = (uint32_t) inet_addr(host_string);
pd[0].port = htons((unsigned short) strtol(port_string, NULL, 0));
pd[0].pt = SOCKS5_TYPE;
proxybound_max_chain = 1;
if(getenv(PROXYBOUND_FORCE_DNS_ENV_VAR) && (*getenv(PROXYBOUND_FORCE_DNS_ENV_VAR) == '1'))
proxybound_resolver = 1;
*proxy_count = 1;
proxybound_got_chain_data = 1;
}
static int is_dns_port(unsigned short port) {
if ((port == 53) || (port == 853)) {
if (proxybound_allow_dns) {PDEBUG("is_dns_port: allowing direct udp dns request on port: %d\n",port);}
return 1;
}
return 0;
}
/**************************************************************************************************************************************************************/
/******* HOOK FUNCTIONS *************************************************************************************************************************************/
// Sock family list (not complete)
// AF_UNIX_CCSID /* - Unix domain sockets */
// AF_UNIX /* 1 - Unix domain sockets */
// AF_INET /* 2 - Internet IP Protocol */
// AF_INET6 /* 10 - IPv6 */
// AF_UNSPEC /* 0 */
// AF_AX25 /* 3 - Amateur Radio AX.25 */
// AF_IPX /* 4 - Novell IPX */
// AF_APPLETALK /* 5 - Appletalk DDP */
// AF_NETROM /* 6 - Amateur radio NetROM */
// AF_BRIDGE /* 7 - Multiprotocol bridge */
// AF_AAL5 /* 8 - Reserved for Werner's ATM */
// AF_X25 /* 9 - Reserved for X.25 project */
// AF_MAX /* 12 - For now.. */
// MSG_PROXY /* 16 - ... */
// PF_FILE /* ?? - ... */
// ...
//SOCK_STREAM // 1
//SOCK_DGRAM // 2
//SOCK_SEQPACKET // 5
//SOCK_RAW // 3
//SOCK_RDM // 4
//SOCK_PACKET // 10
// ...
//struct msghdr {
// void *msg_name; /* optional address */
// socklen_t msg_namelen; /* size of address */
// struct iovec *msg_iov; /* scatter/gather array */
// size_t msg_iovlen; /* # elements in msg_iov */
// void *msg_control; /* ancillary data, see below */
// size_t msg_controllen; /* ancillary data buffer len */
// int msg_flags; /* flags on received message */
//};
/**************************************************************************************************************************************************************/
int connect(int sock, const struct sockaddr *addr, socklen_t len) {
PDEBUG("\n\n\n\n\n\n\n\n\n\n\n\n...CONNECT........................................................................................................... \n\n");
if (true_connect == NULL) {
PDEBUG("violation: connect: rejecting, unresolved symbol: connect\n");
errno = ECONNREFUSED; return -1;
}
int socktype = 0, flags = 0, ret = 0;
socklen_t optlen = 0;
ip_type dest_ip;
char ip[256];
struct in_addr *p_addr_in;
unsigned short port;
size_t i;
int remote_dns_connect = 0;
INIT();
optlen = sizeof(socktype);
getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
if (!socktype) {
PDEBUG("violation: connect: allowing, no socket_type\n");
return true_connect(sock, addr, len);
}
/*if ((SOCKFAMILY(*addr) < 1) && (!proxybound_allow_leak)) {
PDEBUG("violation: connect: rejecting, unresolved, socket family\n");
errno = ECONNREFUSED; return -1;
}*/
//Allow direct unix
if ((SOCKFAMILY(*addr) != AF_INET) && (SOCKFAMILY(*addr) != AF_INET6) ) {
PDEBUG("connect: requested SOCK =%d\n",socktype);
PDEBUG("connect: requested SOCKFAMILY =%d\n",SOCKFAMILY(*addr));
PDEBUG("-------------------------------------------------\n");
PDEBUG("connect: allowing non inet connect()\n");
return true_connect(sock, addr, len);
}
p_addr_in = &((struct sockaddr_in *) addr)->sin_addr;
port = ntohs(((struct sockaddr_in *) addr)->sin_port);
//inet_ntop - convert IPv4 and IPv6 addresses from binary to text form
inet_ntop(AF_INET, p_addr_in, ip, sizeof(ip));
#ifdef DEBUG
//PDEBUG("connect: localnet: %s\n", inet_ntop(AF_INET, &in_addr_localnet, ip, sizeof(ip)));
//PDEBUG("connect: netmask: %s\n" , inet_ntop(AF_INET, &in_addr_netmask, ip, sizeof(ip)));
if (strlen(ip) == 0) {PDEBUG("violation: connect: null ip\n");} else {PDEBUG("connect: target: %s\n", ip);}
if (port < 0) {PDEBUG("violation: connect: null port\n");} else {PDEBUG("connect: port: %d\n", port);}
#endif
//Allow direct local 127.x.x.x
if ((strlen(ip) != 0) && (ip[0] == '1') && (ip[1] == '2') && (ip[2] == '7') && (ip[3] == '.')) {
PDEBUG("connect: local ip detected... ignoring\n");
return true_connect(sock, addr, len);
}
//Check if connect called from proxydns
remote_dns_connect = (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet);
for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) {
if((localnet_addr[i].in_addr.s_addr & localnet_addr[i].netmask.s_addr) == (p_addr_in->s_addr & localnet_addr[i].netmask.s_addr)) {
if(!localnet_addr[i].port || localnet_addr[i].port == port) {
PDEBUG("connect: accessing localnet using true_connect\n");
return true_connect(sock, addr, len);
}
}
}
//Block unsupported sock
//WARNING: this block other unrelated network connect
if (socktype != SOCK_STREAM) {
if (proxybound_allow_leak) {
PDEBUG("connect: allowing leak connect()\n");
return true_connect(sock, addr, len);
} else {
if (port < 0) {PDEBUG("violation: connect: rejecting leak connect() null port\n"); errno = ECONNREFUSED; return -1;}
if ((proxybound_allow_dns) && (is_dns_port(port))) {return true_connect(sock, addr, len);}
PDEBUG("connect: rejecting leak connect()\n"); errno = ECONNREFUSED; return -1;
}
}
//Proxify connect
flags = fcntl(sock, F_GETFL, 0);
if(flags & O_NONBLOCK) {fcntl(sock, F_SETFL, !O_NONBLOCK);}
dest_ip.as_int = SOCKADDR(*addr);
ret = connect_proxy_chain(sock, dest_ip, SOCKPORT(*addr), proxybound_pd, proxybound_proxy_count, proxybound_ct, proxybound_max_chain);
fcntl(sock, F_SETFL, flags);
if(ret != SUCCESS) errno = ECONNREFUSED;
return ret;
}
//int connect(int sock, const struct sockaddr *addr, socklen_t len)
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
PDEBUG("bind: got a bind request ------------------------\n");
if (true_bind == NULL) {
PDEBUG("violation: bind: rejecting, unresolved symbol: bind\n");
errno = EFAULT; return -1;
}
int socktype = 0;
socklen_t optlen = 0;
char ip[256];
struct in_addr *p_addr_in;
unsigned short port;
size_t i;
int remote_dns_bind = 0;
optlen = sizeof(socktype);
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
if (!socktype) {
PDEBUG("violation: bind: allowing, no socket_type\n");
return true_bind(sockfd, addr, addrlen);
}
/*if ((SOCKFAMILY(*addr) < 1) && (!proxybound_allow_leak)) {
PDEBUG("violation: bind: rejecting, unresolved, socket family\n");
errno = EFAULT; return -1;
}*/
//Allow direct unix
if ((SOCKFAMILY(*addr) != AF_INET) && (SOCKFAMILY(*addr) != AF_INET6) ) {
PDEBUG("bind: allowing non inet sock bind()\n");
return true_bind(sockfd, addr, addrlen);
}
p_addr_in = &((struct sockaddr_in *) addr)->sin_addr;
port = ntohs(((struct sockaddr_in *) addr)->sin_port);
//inet_ntop - convert IPv4 and IPv6 addresses from binary to text form
inet_ntop(AF_INET, p_addr_in, ip, sizeof(ip));
#ifdef DEBUG
if (strlen(ip) == 0) {PDEBUG("violation: bind: null ip\n");} else {PDEBUG("bind: target: %s\n", ip);}
if (port < 0) {PDEBUG("violation: bind: null port\n");} else {PDEBUG("bind: port: %d\n", port);}
PDEBUG("-------------------------------------------------\n");
#endif
//Allow direct local 127.x.x.x
if ((strlen(ip) == 0) && (ip[0] == '1') && (ip[1] == '2') && (ip[2] == '7') && (ip[3] == '.')) {
PDEBUG("bind: local ip detected... ignoring\n");
return true_bind(sockfd, addr, addrlen);
}
//Check if bind called from proxydns
remote_dns_bind = (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet);
for(i = 0; i < num_localnet_addr && !remote_dns_bind; i++) {
if((localnet_addr[i].in_addr.s_addr & localnet_addr[i].netmask.s_addr) == (p_addr_in->s_addr & localnet_addr[i].netmask.s_addr)) {
if(!localnet_addr[i].port || localnet_addr[i].port == port) {
PDEBUG("bind: accessing localnet using true_bind\n");
return true_bind(sockfd, addr, addrlen);
}
}
}
#ifdef DEBUG
PDEBUG("bind() sock SOCK_STREAM = %d\n",SOCK_STREAM);
PDEBUG("bind() sock SOCK_DGRAM = %d\n",SOCK_DGRAM);
PDEBUG("bind() sock SOCK_SEQPACKET = %d\n",SOCK_SEQPACKET);
PDEBUG("bind() sock SOCK_RAW = %d\n",SOCK_RAW);
PDEBUG("bind() sock SOCK_RDM = %d\n",SOCK_RDM);
PDEBUG("bind() sock SOCK_PACKET = %d\n",SOCK_PACKET);
PDEBUG("-------------------------------------------------\n");
PDEBUG("bind: requested SOCK =%d\n",socktype);
PDEBUG("bind: requested SOCKFAMILY =%d\n",SOCKFAMILY(*addr));
PDEBUG("-------------------------------------------------\n");
#endif
//Required for proxify, type raw, 0.0.0.0, MSG_PROXY
/*if ((socktype == SOCK_RAW) && (SOCKFAMILY(*addr) == MSG_PROXY)) {
if ((ip[0] == '0') && (ip[1] == '.') && (ip[2] == '0') && (ip[3] == '.' ) && (ip[4] == '0') && (ip[5] == '.') && (ip[6] == '0')) {
PDEBUG("bind: bind allowing, 0.0.0.0, MSG_PROXY...\n");
return true_bind(sockfd, addr, addrlen);
}
}*/
//Block unsupported sock
//WARNING: this block other unrelated network connect
if ((socktype != SOCK_STREAM) && (!proxybound_allow_leak)) {
if (port < 0) {PDEBUG("violation: bind: rejecting un-managed protocol bind() null port\n"); errno = EFAULT; return -1;}
if ((proxybound_allow_dns) && (is_dns_port(port))) {return true_bind(sockfd, addr, addrlen);}
PDEBUG("bind: rejecting un-managed protocol bind()\n");
errno = EFAULT; return -1;
} else {
return true_bind(sockfd, addr, addrlen);
}
if (proxybound_allow_leak) {
return true_bind(sockfd, addr, addrlen);
}
PDEBUG("bind: rejecting un-managed protocol bind()\n");
errno = EFAULT; return -1;
}
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
PDEBUG("sendmsg: got sendmsg request --------------------\n");
return true_sendmsg(sockfd, msg, flags);
if (true_sendmsg == NULL) {
PDEBUG("violation: sendmsg: rejecting, unresolved symbol: sendmsg\n");
errno = EFAULT; return -1;
}
int sock_type = -1;
unsigned int sock_type_len = sizeof(sock_type);
const struct sockaddr_in *addr = (const struct sockaddr_in *)msg->msg_name; //optional adress
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len); //get the type of the socket
if (!sock_type) {
PDEBUG("violation: sendmsg: allowing unknown sock\n");
return true_sendmsg(sockfd, msg, flags);
}
if (addr) {
if (addr->sin_family) {
PDEBUG("sendmsg: sock familly %d\n",addr->sin_family);
if ((addr->sin_family != AF_INET) && (addr->sin_family != AF_INET6)) {
PDEBUG("sendmsg: allowing non inet\n");
return true_sendmsg(sockfd, msg, flags);
}
} else {
//This require connect on the first place...
PDEBUG("violation: sendmsg: allowing unknown sin_family\n");
return true_sendmsg(sockfd, msg, flags);
}
} else {
//This require connect on the first place...
PDEBUG("violation: sendmsg: allowing unknown addr\n");
return true_sendmsg(sockfd, msg, flags);
}
//Block unsupported sock
//WARNING: this block other unrelated network connect
if (sock_type == SOCK_STREAM) {
PDEBUG("sendmsg: allowing tcp sock stream\n");
return true_sendmsg(sockfd, msg, flags);
} else {
PDEBUG("sendmsg sock SOCK_STREAM = %d\n",SOCK_STREAM);
PDEBUG("sendmsg sock SOCK_DGRAM = %d\n",SOCK_DGRAM);
PDEBUG("sendmsg sock SOCK_SEQPACKET = %d\n",SOCK_SEQPACKET);
PDEBUG("sendmsg sock SOCK_RAW = %d\n",SOCK_RAW);
PDEBUG("sendmsg sock SOCK_RDM = %d\n",SOCK_RDM);
PDEBUG("sendmsg sock SOCK_PACKET = %d\n",SOCK_PACKET);
PDEBUG("-------------------------------------------------\n");
PDEBUG("sendmsg: sock %d\n",sock_type);
PDEBUG("-------------------------------------------------\n");
}
/*if (((sock_type == SOCK_SEQPACKET) || (sock_type == SOCK_SEQPACKET)) && (!addr)) {
PDEBUG("sendmsg: allowing seqpacket stream\n");
return true_sendmsg(sockfd, msg, flags);
}*/
if (proxybound_allow_leak) {
PDEBUG("sendmsg: allow leak\n");
return true_sendmsg(sockfd, msg, flags);
} else {
if (addr) {
char ip[256];
struct in_addr *p_addr_in;
p_addr_in = &((struct sockaddr_in *) addr)->sin_addr;
inet_ntop(AF_INET, p_addr_in, ip, sizeof(ip));
if (strlen(ip) == 0) {PDEBUG("violation: sendmsg: rejecting null ip\n"); errno = EFAULT; return -1;}
PDEBUG("sendmsg: ip: %s\n",ip);
unsigned short port;
port = ntohs(((struct sockaddr_in *) addr)->sin_port);
if (port < 0) {PDEBUG("violation: sendmsg: rejecting null port\n"); errno = EFAULT; return -1;}
PDEBUG("sendmsg: port: %d\n", port);
//Allow local
if ((strlen(ip) != 0) && ((ip[0] == '1') && (ip[1] == '2') && (ip[2] == '7') && (ip[3] == '.'))) {
PDEBUG("sendmsg: allowing local 127.0.0.1\n");
return true_sendmsg(sockfd, msg, flags);
}
if ((proxybound_allow_dns) && (is_dns_port(port))) {return true_sendmsg(sockfd, msg, flags);}
PDEBUG("sendmsg: rejecting c\n");
errno = EFAULT; return -1;
}
PDEBUG("sendmsg: rejecting d\n");
errno = EFAULT; return -1;
}
}
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) {
PDEBUG("sendto: got sendto request ----------------------\n");
if (true_sendto == NULL) {
PDEBUG("violation: sendto: rejecting, unresolved symbol: sendto\n");
errno = EFAULT; return -1;
}
int sock_type = -1;
unsigned int sock_type_len = sizeof(sock_type);
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len); //get the type of the socket
if (!sock_type) {
PDEBUG("violation: sendto: allowing, no socket_type\n");
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
}
struct sockaddr_in *connaddr;
connaddr = (struct sockaddr_in *) dest_addr;
if (!connaddr) {
PDEBUG("violation: sendto: null dest_addr\n");
//send(sockfd, buf, len, flags) = sendto(sockfd, buf, len, flags, NULL, 0)
//send require connect on the first place...
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
}
if ((connaddr->sin_family != AF_INET) && (connaddr->sin_family != AF_INET6)) {
PDEBUG("sendto: allowing non inet socket\n");
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
}
//Block unsupported sock
//WARNING: this block other unrelated network connect
if ((sock_type != SOCK_STREAM) && (!proxybound_allow_leak)) {
PDEBUG("sendto: is on a udp/unsupported stream\n");
PDEBUG("sendto: requested SOCK =%d\n",sock_type);
char ip[256];
struct in_addr *p_addr_in;
unsigned short port;
p_addr_in = &((struct sockaddr_in *) connaddr)->sin_addr;
port = ntohs(((struct sockaddr_in *) connaddr)->sin_port);
inet_ntop(AF_INET, p_addr_in, ip, sizeof(ip));
if (!connaddr->sin_family) {PDEBUG("violation: sendto: rejecting null sin_family\n"); errno = EFAULT; return -1;}
if (strlen(ip) == 0) {PDEBUG("violation: sendmsg: rejecting null ip\n"); errno = EFAULT; return -1;}
if (port < 0) {PDEBUG("violation: sendmsg: rejecting null port\n"); errno = EFAULT; return -1;}
PDEBUG("sendto: requested SOCKFAMILY =%d\n",connaddr->sin_family);
PDEBUG("sendto: ip: %s\n",ip);
PDEBUG("sendto: port: %d\n", port);
PDEBUG("sendto: -----------------------------------------\n");
//Allow local
if ((ip[0] == '1') && (ip[1] == '2') && (ip[2] == '7') && (ip[3] == '.')) {
PDEBUG("sendto: allowing local 127.0.0.1\n");
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
}
//Blocking the connection
if (proxybound_allow_leak) {
PDEBUG("sendto: allowing udp/unsupported sendto()\n");
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
} else {
//if (port < 0) {PDEBUG("violation: sendto: rejecting null port\n"); errno = EFAULT; return -1;}
//if ((proxybound_allow_dns) && (is_dns_port(port))) {return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);}
PDEBUG("sendto: rejecting.\n");
errno = EFAULT; return -1;
}
} else {
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
}
if (proxybound_allow_leak) {
return true_sendto(sockfd, buf, len, flags, *dest_addr, addrlen);
}
PDEBUG("sendto: rejecting.\n");
errno = EFAULT; return -1;
}
ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
//PDEBUG("send: got send request --------------------------\n"); //avoid too talkative logs
//The send() call may be used only when the socket is in a connected state (so that the intended recipient is known)
//To avoid any hack this is watched for leak too
/* If the real connect doesn't exist, we're stuffed */
if (true_send == NULL) {
PDEBUG("violation: send: rejecting, unresolved symbol: send\n");
errno = EFAULT; return -1;
}
//send require connect/sendto in the first place...
return true_send(sockfd, buf, len, flags);
/*if (proxybound_allow_leak) {
PDEBUG("send: allowing direct send()\n");
return true_send(sockfd, buf, len, flags);
} else {
int sock_type = -1;
unsigned int sock_type_len = sizeof(sock_type);
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len); //Get the type of the socket
if (!sock_type) {
PDEBUG("violation: send: allowing empty sock_type send()\n");
return true_send(sockfd, buf, len, flags);
}
//SOCK_STREAM SOCK_DGRAM SOCK_SEQPACKET SOCK_RAW SOCK_RDM SOCK_PACKET
if (sock_type == SOCK_STREAM) {return true_send(sockfd, buf, len, flags);}
PDEBUG("send: sock SOCK_STREAM = %d\n",SOCK_STREAM);
PDEBUG("send: sock SOCK_DGRAM = %d\n",SOCK_DGRAM);
PDEBUG("send: sock SOCK_SEQPACKET = %d\n",SOCK_SEQPACKET);
PDEBUG("send: sock SOCK_RAW = %d\n",SOCK_RAW);
PDEBUG("send: sock SOCK_RDM = %d\n",SOCK_RDM);
PDEBUG("send: sock SOCK_PACKET = %d\n",SOCK_PACKET);
PDEBUG("-------------------------------------------------\n");
PDEBUG("send: sock %d\n",sock_type);
PDEBUG("-------------------------------------------------\n");
PDEBUG("send: rejecting send request unsupported sock\n");
errno = EFAULT; return -1;
}*/
}
//TODO: DNS LEAK: OTHER RESOLVER FUNCTION
//=======================================
//realresinit = dlsym(lib, "res_init");
//realresquery = dlsym(lib, "res_query");
//realressend = dlsym(lib, "res_send");
//realresquerydomain = dlsym(lib, "res_querydomain");
//realressearch = dlsym(lib, "res_search");
//realgethostbyaddr = dlsym(lib, "gethostbyaddr"); //Needs rewrite
//realgetipnodebyname = dlsym(lib, "getipnodebyname");
//UDP & DNS LEAK
//==============
//realsendto = dlsym(lib, "sendto");
//realsendmsg = dlsym(lib, "sendmsg");
static struct gethostbyname_data ghbndata;
struct hostent *gethostbyname(const char *name) {
PDEBUG("gethostbyname: got gethostbyname request --------\n");
INIT();
PDEBUG("gethostbyname: gethostbyname: %s\n", name);
if(proxybound_resolver)
return proxy_gethostbyname(name, &ghbndata);
else
return true_gethostbyname(name);
return NULL;
}
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
PDEBUG("getaddrinfo: got getaddrinfo request ------------\n");
int ret = 0;
INIT();
PDEBUG("getaddrinfo: %s %s\n", node, service);
if(proxybound_resolver)
ret = proxy_getaddrinfo(node, service, hints, res);
else
ret = true_getaddrinfo(node, service, hints, res);
return ret;
}
void freeaddrinfo(struct addrinfo *res) {
PDEBUG("freeaddrinfo: got freeaddrinfo request ----------\n");
INIT();
PDEBUG("freeaddrinfo: %p \n", res);
if(!proxybound_resolver)
true_freeaddrinfo(res);
else
proxy_freeaddrinfo(res);
return;
}
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) {
PDEBUG("getnameinfo: got getnameinfo request ------------\n");
char ip_buf[16];
int ret = 0;
INIT();
PDEBUG("getnameinfo: %s %s\n", host, serv);
if(!proxybound_resolver) {
ret = true_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
} else {
if(hostlen) {
pc_stringfromipv4((unsigned char*) &(SOCKADDR_2(*sa)), ip_buf);
strncpy(host, ip_buf, hostlen);
}
if(servlen)
snprintf(serv, servlen, "%d", ntohs(SOCKPORT(*sa)));
}
return ret;
}
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
PDEBUG("gethostbyaddr: got gethostbyaddr request --------\n");
static char buf[16];
static char ipv4[4];
static char *list[2];
static char *aliases[1];
static struct hostent he;
INIT();
//TODO: proper gethostbyaddr hook
PDEBUG("hostent: todo: proper gethostbyaddr hook\n");
if(!proxybound_resolver)
return true_gethostbyaddr(addr, len, type);
else {
PDEBUG("hostent: len %u\n", len);
if(len != 4)
return NULL;
he.h_name = buf;
memcpy(ipv4, addr, 4);
list[0] = ipv4;
list[1] = NULL;
he.h_addr_list = list;
he.h_addrtype = AF_INET;
aliases[0] = NULL;
he.h_aliases = aliases;
he.h_length = 4;
pc_stringfromipv4((unsigned char *) addr, buf);
return &he;
}
return NULL;
}

View File

@@ -1,445 +0,0 @@
/***************************************************************************
libproxychains.c - description
-------------------
begin : Tue May 14 2002
copyright : netcreature (C) 2002
email : netcreature@users.sourceforge.net
***************************************************************************/
/* GPL */
/***************************************************************************
* *
* 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 Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#undef _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <pthread.h>
#include "core.h"
#include "common.h"
#define satosin(x) ((struct sockaddr_in *) &(x))
#define SOCKADDR(x) (satosin(x)->sin_addr.s_addr)
#define SOCKADDR_2(x) (satosin(x)->sin_addr)
#define SOCKPORT(x) (satosin(x)->sin_port)
#define SOCKFAMILY(x) (satosin(x)->sin_family)
#define MAX_CHAIN 512
connect_t true_connect;
gethostbyname_t true_gethostbyname;
getaddrinfo_t true_getaddrinfo;
freeaddrinfo_t true_freeaddrinfo;
getnameinfo_t true_getnameinfo;
gethostbyaddr_t true_gethostbyaddr;
int tcp_read_time_out;
int tcp_connect_time_out;
chain_type proxychains_ct;
proxy_data proxychains_pd[MAX_CHAIN];
unsigned int proxychains_proxy_count = 0;
int proxychains_got_chain_data = 0;
unsigned int proxychains_max_chain = 1;
int proxychains_quiet_mode = 0;
int proxychains_resolver = 0;
localaddr_arg localnet_addr[MAX_LOCALNET];
size_t num_localnet_addr = 0;
unsigned int remote_dns_subnet = 224;
pthread_once_t init_once = PTHREAD_ONCE_INIT;
static int init_l = 0;
static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
static void* load_sym(char* symname, void* proxyfunc) {
void *funcptr = dlsym(RTLD_NEXT, symname);
if(!funcptr) {
fprintf(stderr, "Cannot load symbol '%s' %s\n", symname, dlerror());
exit(1);
} else {
PDEBUG("loaded symbol '%s'" " real addr %p wrapped addr %p\n", symname, funcptr, proxyfunc);
}
if(funcptr == proxyfunc) {
PDEBUG("circular reference detected, aborting!\n");
abort();
}
return funcptr;
}
#define INIT() init_lib_wrapper(__FUNCTION__)
#define SETUP_SYM(X) do { true_ ## X = load_sym( # X, X ); } while(0)
#include "shm.h"
#include "allocator_thread.h"
#include "stringdump.h"
static void do_init(void) {
srand(time(NULL));
dumpstring_init(); // global string garbage can
core_initialize();
at_init();
/* read the config file */
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
proxychains_write_log(LOG_PREFIX "DLL init\n");
SETUP_SYM(connect);
SETUP_SYM(gethostbyname);
SETUP_SYM(getaddrinfo);
SETUP_SYM(freeaddrinfo);
SETUP_SYM(gethostbyaddr);
SETUP_SYM(getnameinfo);
init_l = 1;
}
#if 0
/* FIXME this is currently unused.
* it is not strictly needed.
* maybe let it be called by a gcc destructor, if that doesnt
* have negative consequences (e.g. when a child calles exit) */
static void unload(void) {
at_close();
core_unload();
}
#endif
static void init_lib_wrapper(const char* caller) {
#ifndef DEBUG
(void) caller;
#endif
if(!init_l) PDEBUG("%s called from %s\n", __FUNCTION__, caller);
pthread_once(&init_once, do_init);
}
/* if we use gcc >= 3, we can instruct the dynamic loader
* to call init_lib at link time. otherwise it gets loaded
* lazily, which has the disadvantage that there's a potential
* race condition if 2 threads call it before init_l is set
* and PTHREAD support was disabled */
#if __GNUC__ > 2
__attribute__((constructor))
static void gcc_init(void) {
INIT();
}
#endif
/* get configuration from config file */
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) {
int count = 0, port_n = 0, list = 0;
char buff[1024], type[1024], host[1024], user[1024];
char *env;
char local_in_addr_port[32];
char local_in_addr[32], local_in_port[32], local_netmask[32];
FILE *file = NULL;
if(proxychains_got_chain_data)
return;
//Some defaults
tcp_read_time_out = 4 * 1000;
tcp_connect_time_out = 10 * 1000;
*ct = DYNAMIC_TYPE;
env = get_config_path(getenv(PROXYCHAINS_CONF_FILE_ENV_VAR), buff, sizeof(buff));
file = fopen(env, "r");
env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR);
if(env && *env == '1')
proxychains_quiet_mode = 1;
while(fgets(buff, sizeof(buff), file)) {
if(buff[0] != '\n' && buff[strspn(buff, " ")] != '#') {
/* proxylist has to come last */
if(list) {
if(count >= MAX_CHAIN)
break;
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.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 && pd[count].ip.as_int != (uint32_t) - 1)
count++;
} else {
if(strstr(buff, "[ProxyList]")) {
list = 1;
} else if(strstr(buff, "random_chain")) {
*ct = RANDOM_TYPE;
} else if(strstr(buff, "strict_chain")) {
*ct = STRICT_TYPE;
} else if(strstr(buff, "dynamic_chain")) {
*ct = DYNAMIC_TYPE;
} 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")) {
sscanf(buff, "%s %d", user, &tcp_connect_time_out);
} else if(strstr(buff, "remote_dns_subnet")) {
sscanf(buff, "%s %d", user, &remote_dns_subnet);
if(remote_dns_subnet >= 256) {
fprintf(stderr,
"remote_dns_subnet: invalid value. requires a number between 0 and 255.\n");
exit(1);
}
} else if(strstr(buff, "localnet")) {
if(sscanf(buff, "%s %21[^/]/%15s", user, local_in_addr_port, local_netmask) < 3) {
fprintf(stderr, "localnet format error");
exit(1);
}
/* clean previously used buffer */
memset(local_in_port, 0, sizeof(local_in_port) / sizeof(local_in_port[0]));
if(sscanf(local_in_addr_port, "%15[^:]:%5s", local_in_addr, local_in_port) < 2) {
PDEBUG("added localnet: netaddr=%s, netmask=%s\n",
local_in_addr, local_netmask);
} else {
PDEBUG("added localnet: netaddr=%s, port=%s, netmask=%s\n",
local_in_addr, local_in_port, local_netmask);
}
if(num_localnet_addr < MAX_LOCALNET) {
int error;
error =
inet_pton(AF_INET, local_in_addr,
&localnet_addr[num_localnet_addr].in_addr);
if(error <= 0) {
fprintf(stderr, "localnet address error\n");
exit(1);
}
error =
inet_pton(AF_INET, local_netmask,
&localnet_addr[num_localnet_addr].netmask);
if(error <= 0) {
fprintf(stderr, "localnet netmask error\n");
exit(1);
}
if(local_in_port[0]) {
localnet_addr[num_localnet_addr].port =
(short) atoi(local_in_port);
} else {
localnet_addr[num_localnet_addr].port = 0;
}
++num_localnet_addr;
} else {
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
}
} 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")) {
proxychains_quiet_mode = 1;
} else if(strstr(buff, "proxy_dns")) {
proxychains_resolver = 1;
}
}
}
}
fclose(file);
*proxy_count = count;
proxychains_got_chain_data = 1;
}
/******* HOOK FUNCTIONS *******/
int connect(int sock, const struct sockaddr *addr, unsigned int len) {
PFUNC();
int socktype = 0, flags = 0, ret = 0;
socklen_t optlen = 0;
ip_type dest_ip;
#ifdef DEBUG
char str[256];
#endif
struct in_addr *p_addr_in;
unsigned short port;
size_t i;
int remote_dns_connect = 0;
INIT();
optlen = sizeof(socktype);
getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
if(!(SOCKFAMILY(*addr) == AF_INET && socktype == SOCK_STREAM))
return true_connect(sock, addr, len);
p_addr_in = &((struct sockaddr_in *) addr)->sin_addr;
port = ntohs(((struct sockaddr_in *) addr)->sin_port);
#ifdef DEBUG
// PDEBUG("localnet: %s; ", inet_ntop(AF_INET,&in_addr_localnet, str, sizeof(str)));
// PDEBUG("netmask: %s; " , inet_ntop(AF_INET, &in_addr_netmask, str, sizeof(str)));
PDEBUG("target: %s\n", inet_ntop(AF_INET, p_addr_in, str, sizeof(str)));
PDEBUG("port: %d\n", port);
#endif
// check if connect called from proxydns
remote_dns_connect = (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet);
for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) {
if((localnet_addr[i].in_addr.s_addr & localnet_addr[i].netmask.s_addr)
== (p_addr_in->s_addr & localnet_addr[i].netmask.s_addr)) {
if(!localnet_addr[i].port || localnet_addr[i].port == port) {
PDEBUG("accessing localnet using true_connect\n");
return true_connect(sock, addr, len);
}
}
}
flags = fcntl(sock, F_GETFL, 0);
if(flags & O_NONBLOCK)
fcntl(sock, F_SETFL, !O_NONBLOCK);
dest_ip.as_int = SOCKADDR(*addr);
ret = connect_proxy_chain(sock,
dest_ip,
SOCKPORT(*addr),
proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain);
fcntl(sock, F_SETFL, flags);
if(ret != SUCCESS)
errno = ECONNREFUSED;
return ret;
}
static struct gethostbyname_data ghbndata;
struct hostent *gethostbyname(const char *name) {
INIT();
PDEBUG("gethostbyname: %s\n", name);
if(proxychains_resolver)
return proxy_gethostbyname(name, &ghbndata);
else
return true_gethostbyname(name);
return NULL;
}
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
int ret = 0;
INIT();
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
if(proxychains_resolver)
ret = proxy_getaddrinfo(node, service, hints, res);
else
ret = true_getaddrinfo(node, service, hints, res);
return ret;
}
void freeaddrinfo(struct addrinfo *res) {
INIT();
PDEBUG("freeaddrinfo %p \n", res);
if(!proxychains_resolver)
true_freeaddrinfo(res);
else
proxy_freeaddrinfo(res);
return;
}
// work around a buggy prototype in GLIBC. according to the bugtracker it has been fixed in git at 02 May 2011.
// 2.14 came out in June 2011 so that should be the first fixed version
#if defined(__GLIBC__) && (__GLIBC__ < 3) && (__GLIBC_MINOR__ < 14)
int getnameinfo(const struct sockaddr *sa,
socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, unsigned int flags)
#else
int getnameinfo(const struct sockaddr *sa,
socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
#endif
{
char ip_buf[16];
int ret = 0;
INIT();
PDEBUG("getnameinfo: %s %s\n", host, serv);
if(!proxychains_resolver) {
ret = true_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
} else {
if(hostlen) {
pc_stringfromipv4((unsigned char*) &(SOCKADDR_2(*sa)), ip_buf);
strncpy(host, ip_buf, hostlen);
}
if(servlen)
snprintf(serv, servlen, "%d", ntohs(SOCKPORT(*sa)));
}
return ret;
}
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
static char buf[16];
static char ipv4[4];
static char *list[2];
static char *aliases[1];
static struct hostent he;
INIT();
PDEBUG("TODO: proper gethostbyaddr hook\n");
if(!proxychains_resolver)
return true_gethostbyaddr(addr, len, type);
else {
PDEBUG("len %u\n", len);
if(len != 4)
return NULL;
he.h_name = buf;
memcpy(ipv4, addr, 4);
list[0] = ipv4;
list[1] = NULL;
he.h_addr_list = list;
he.h_addrtype = AF_INET;
aliases[0] = NULL;
he.h_aliases = aliases;
he.h_length = 4;
pc_stringfromipv4((unsigned char *) addr, buf);
return &he;
}
return NULL;
}

View File

@@ -1,4 +1,7 @@
/* (C) 2011, 2012 rofl0r
/***************************************************************************
* *
* (C) 2019 intika *
* (C) 2011, 2012 rofl0r *
* *
* 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 *
@@ -15,25 +18,21 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include "common.h"
static int usage(char **argv) {
printf("\nUsage:\t%s -q -f config_file program_name [arguments]\n"
"\t-q makes proxychains quiet - this overrides the config setting\n"
"\t-f allows to manually specify a configfile to use\n"
"\tfor example : proxychains telnet somehost.com\n" "More help in README file\n\n", argv[0]);
return EXIT_FAILURE;
}
static char appVersion[5] = "5.60\n";
static const char *dll_name = DLL_NAME;
static pid_t child_pid = -1 ;
static char own_dir[256];
static const char *dll_dirs[] = {
".",
//".",
own_dir,
LIB_DIR,
"/lib",
@@ -43,18 +42,93 @@ static const char *dll_dirs[] = {
NULL
};
static int usage(char **argv) {
printf("\nProxybound version %s", appVersion);
printf("https://github.com/Intika-Linux-Proxy/Proxybound\n");
printf("\nUsage:\n");
printf("%s -q -f config_file command-or-app arguments\n", argv[0]);
printf("\nOptions:\n");
printf("-q \t makes proxybound quiet, this overrides the config setting\n");
printf("-f \t allows to manually specify a configfile to use\n");
printf("-v \t or --version, disaplay application version\n");
printf("\nExample:\n");
printf("proxybound telnet somehost.com\n");
printf("\nAvailable environment variables:\n");
printf("- PROXYBOUND_CONF_FILE: Path to config file (default ./proxybound.conf then /etc/proxybound.conf)\n");
printf("- PROXYBOUND_QUIET_MODE: Quiet mode (1 or 0, default 0)\n");
printf("- PROXYBOUND_SOCKS5_HOST: Specify unique socks 5 proxy to use (default not used)\n");
printf("- PROXYBOUND_SOCKS5_PORT: Socks 5 port (default not used)\n");
printf("- PROXYBOUND_FORCE_DNS: Force dns resolv requests through (1 or 0, default 1)\n");
printf("- PROXYBOUND_ALLOW_DNS: Allow direct dns, allow udp port 53 and 853 (1 or 0, default 0)\n");
printf("- PROXYBOUND_ALLOW_LEAKS: Allow/Block unproxyfied protocols 'UDP/ICMP/RAW', blocked by default (1 or 0, default 0)\n");
printf("- PROXYBOUND_WORKING_INDICATOR: Create '/tmp/proxybound.tmp' when dll is working as intended (1 or 0, default 0)\n");
printf("\nMore help:\n");
printf("More help is available in README.md file https://github.com/Intika-Linux-Proxy/Proxybound\n\n");
return EXIT_FAILURE;
}
static int version(char **argv) {
printf("\nProxybound version %s", appVersion);
printf("https://github.com/Intika-Linux-Proxy/Proxybound\n\n");
return EXIT_FAILURE;
}
static void set_own_dir(const char *argv0) {
size_t l = strlen(argv0);
while(l && argv0[l - 1] != '/')
l--;
if(l == 0)
memcpy(own_dir, ".", 2);
//memcpy(own_dir, ".", 2);
memcpy(own_dir, "/dev/null/", 2);
else {
memcpy(own_dir, argv0, l - 1);
own_dir[l] = 0;
}
}
static int file_exist(const char * filename){
if (access( filename, F_OK ) != -1 ) {
return 1;
} else {
return 0;
}
}
static void wait_timer() {
//Wait 2 sec
int msec = 0, trigger = 2000; /* 10ms */
clock_t before = clock();
do {
clock_t difference = clock() - before;
msec = difference * 1000 / CLOCKS_PER_SEC;
//iterations++;
} while ( msec < trigger );
//printf("Time taken %d seconds %d milliseconds (%d iterations)\n", msec/1000, msec%1000, iterations);
}
static int check_injection() {
if (file_exist("/tmp/proxybound.tmp")) {
//File already exist we can not do a lot
remove("/tmp/proxybound.tmp");
fprintf(stderr, LOG_PREFIX "injected dll loaded\n");
return 1;
} else {
wait_timer();
if (file_exist("/tmp/proxybound.tmp")) {
remove("/tmp/proxybound.tmp");
fprintf(stderr, LOG_PREFIX "injected dll loaded\n");
return 1;
}
else {
kill(child_pid,SIGKILL);
perror("Proxybound can't be injected, it's not compatible with this application");
return -1;
}
}
return -1;
}
#define MAX_COMMANDLINE_FLAGS 2
int main(int argc, char *argv[]) {
@@ -66,6 +140,14 @@ int main(int argc, char *argv[]) {
size_t i;
const char *prefix = NULL;
if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
return usage(argv);
}
if (argc != 2 || !strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
return version(argv);
}
for(i = 0; i < MAX_COMMANDLINE_FLAGS; i++) {
if(start_argv < argc && argv[start_argv][0] == '-') {
if(argv[start_argv][1] == 'q') {
@@ -93,17 +175,17 @@ int main(int argc, char *argv[]) {
if(!quiet)
fprintf(stderr, LOG_PREFIX "config file found: %s\n", path);
/* Set PROXYCHAINS_CONF_FILE to get proxychains lib to use new config file. */
setenv(PROXYCHAINS_CONF_FILE_ENV_VAR, path, 1);
/* Set PROXYBOUND_CONF_FILE to get proxybound lib to use new config file. */
setenv(PROXYBOUND_CONF_FILE_ENV_VAR, path, 1);
setenv(PROXYBOUND_WORKING_INDICATOR_ENV_VAR, "1", 1);
if(quiet)
setenv(PROXYCHAINS_QUIET_MODE_ENV_VAR, "1", 1);
setenv(PROXYBOUND_QUIET_MODE_ENV_VAR, "1", 1);
// search DLL
set_own_dir(argv[0]);
i = 0;
while(dll_dirs[i]) {
@@ -121,7 +203,7 @@ int main(int argc, char *argv[]) {
}
if(!quiet)
fprintf(stderr, LOG_PREFIX "preloading %s/%s\n", prefix, dll_name);
#ifndef IS_MAC
snprintf(buf, sizeof(buf), "LD_PRELOAD=%s/%s", prefix, dll_name);
putenv(buf);
@@ -130,8 +212,22 @@ int main(int argc, char *argv[]) {
putenv(buf);
putenv("DYLD_FORCE_FLAT_NAMESPACE=1");
#endif
execvp(argv[start_argv], &argv[start_argv]);
perror("proxychains can't load process....");
return EXIT_FAILURE;
//Running child process ************************************************************
//execvp(argv[start_argv], &argv[start_argv]);
child_pid = fork();
if(child_pid == 0){
//Child process injected application
execvp(argv[start_argv], &argv[start_argv]);
exit(0);
} else {
//Parent code
}
if (check_injection())
return 0;
else {
perror("Proxybound can't load process....");
return EXIT_FAILURE;
}
}

View File

@@ -1,10 +0,0 @@
#ifndef MUTEX_H
#define MUTEX_H
#include <pthread.h>
# define MUTEX_LOCK(x) pthread_mutex_lock(x)
# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x)
# define MUTEX_INIT(x) pthread_mutex_init(x, NULL)
# define MUTEX_DESTROY(x) pthread_mutex_destroy(x)
#endif

View File

@@ -1,42 +1,52 @@
# proxychains.conf VER 4.x
#
# HTTP, SOCKS4a, SOCKS5 tunneling proxifier with DNS.
# proxybound.conf
#
# HTTP, SOCKS4a, SOCKS5, DNS.
#
# ========================================================================================
# The option below identifies how the ProxyList is treated.
# only one option should be uncommented at time,
# otherwise the last appearing option will be accepted
#
#dynamic_chain
#
# Dynamic - Each connection will be done via chained proxies
# all proxies chained in the order as they appear in the list
# at least one proxy must be online to play in chain
# (dead proxies are skipped)
# otherwise EINTR is returned to the app
#
strict_chain
#
# Strict - Each connection will be done via chained proxies
# all proxies chained in the order as they appear in the list
# all proxies must be online to play in chain
# otherwise EINTR is returned to the app
#
#random_chain
#
# Random - Each connection will be done via random proxy
# (or proxy chain, see chain_len) from the list.
# this option is good to test your IDS :)
#
# Only one chaining option should be uncommented at time,
# otherwise the last appearing option will be accepted
#dynamic_chain
strict_chain
#random_chain
# ========================================================================================
# Make sense only if random_chain
#chain_len = 2
# ========================================================================================
# Quiet mode (no output from library)
#quiet_mode
# ========================================================================================
# Proxy DNS requests - no leak for DNS data
proxy_dns
#remote_dns_subnet 127
#remote_dns_subnet 10
remote_dns_subnet 224
# set the class A subnet number to use for the internal remote DNS mapping
# we use the reserved 224.x.x.x range by default,
# if the proxified app does a DNS request, we will return an IP from that range.
@@ -46,55 +56,58 @@ proxy_dns
# of course you should make sure that the proxified app does not need
# *real* access to this subnet.
# i.e. dont use the same subnet then in the localnet section
#remote_dns_subnet 127
#remote_dns_subnet 10
remote_dns_subnet 224
# ========================================================================================
# Some timeouts in milliseconds
tcp_read_time_out 15000
tcp_connect_time_out 8000
### Examples for localnet exclusion
## localnet ranges will *not* use a proxy to connect.
## Exclude connections to 192.168.1.0/24 with port 80
# ========================================================================================
# Examples for localnet exclusion
# localnet ranges will *not* use a proxy to connect.
# Exclude connections to 192.168.1.0/24 with port 80
# localnet 192.168.1.0:80/255.255.255.0
## Exclude connections to 192.168.100.0/24
# Exclude connections to 192.168.100.0/24
# localnet 192.168.100.0/255.255.255.0
## Exclude connections to ANYwhere with port 80
# Exclude connections to ANYwhere with port 80
# localnet 0.0.0.0:80/0.0.0.0
## RFC5735 Loopback address range
## if you enable this, you have to make sure remote_dns_subnet is not 127
## you'll need to enable it if you want to use an application that
## connects to localhost.
# RFC5735 Loopback address range
# if you enable this, you have to make sure remote_dns_subnet is not 127
# you'll need to enable it if you want to use an application that
# connects to localhost.
# localnet 127.0.0.0/255.0.0.0
## RFC1918 Private Address Ranges
# RFC1918 Private Address Ranges
# localnet 10.0.0.0/255.0.0.0
# localnet 172.16.0.0/255.240.0.0
# localnet 192.168.0.0/255.255.0.0
# ProxyList format
# type host port [user pass]
# (values separated by 'tab' or 'blank')
#
#
# Examples:
#
# socks5 192.168.67.78 1080 lamer secret
# http 192.168.89.3 8080 justu hidden
# socks4 192.168.1.49 1080
# http 192.168.39.93 8080
#
#
# proxy types: http, socks4, socks5
# ( auth types supported: "basic"-http "user/pass"-socks )
#
# ========================================================================================
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks4 127.0.0.1 9050
# ========================================================================================
# ProxyList format
# type host port [user pass]
# (values separated by 'tab' or 'blank')
#
# Examples:
# socks5 192.168.67.78 1080 lamer secret
# http 1 92.168.89.3 8080 justu hidden
# socks4 192.168.1.49 1080
# http 192.168.39.93 8080
#
# proxy types: http, socks4, socks5
# ( auth types supported: "basic"-http "user/pass"-socks )
# ========================================================================================

View File

@@ -1,26 +0,0 @@
#!/bin/sh
echo "ProxyChains-3.1 (http://proxychains.sf.net)"
usage() {
echo " usage:"
echo " $0 [h] [f config-file] <prog> [args]"
exit
}
if [ $# = 0 ] ; then
usage
fi
if [ $1 = "-h" ]; then
usage
fi
if [ "$1" = "-f" ]; then
export PROXYCHAINS_CONF_FILE=$2;
shift;
shift;
fi
export LD_PRELOAD=libproxychains.so.3
exec "$@"

View File

@@ -1,8 +1,8 @@
#!/bin/sh
# This script is called by proxychains to resolve DNS names
# This script is called by proxybound to resolve DNS names
# DNS server used to resolve names
DNS_SERVER=4.2.2.2
DNS_SERVER=1.1.1.1
if [ $# = 0 ] ; then
@@ -12,5 +12,5 @@ if [ $# = 0 ] ; then
fi
export LD_PRELOAD=libproxychains.so
export LD_PRELOAD=libproxybound.so
dig $1 @$DNS_SERVER +tcp | awk '/A.+[0-9]+\.[0-9]+\.[0-9]/{print $5;}'

View File

@@ -1,53 +0,0 @@
#include <assert.h>
#include <string.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#include "shm.h"
#include "debug.h"
#if 0
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>
/* allocates shared memory which can be accessed from the parent and its childs */
void *shm_realloc(void* old, size_t old_size, size_t new_size) {
//PFUNC();
void *nu = mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if(old) {
if(!nu) return NULL;
assert(new_size >= old_size);
memcpy(nu, old, old_size);
munmap(old, old_size);
}
return nu;
}
#endif
void stringpool_init(struct stringpool* sp) {
PFUNC();
memset(sp, 0, sizeof *sp);
}
char* stringpool_add(struct stringpool *sp, char* s, size_t len) {
//PFUNC();
if(len > sp->alloced - sp->used) {
size_t newsz = sp->used + len;
size_t inc = PAGE_SIZE - (newsz % PAGE_SIZE);
newsz += (inc == PAGE_SIZE) ? 0 : inc;
void* p = realloc(sp->start, newsz);
if(p) {
sp->start = p;
sp->alloced = newsz;
} else
return 0;
}
char* ret = sp->start + sp->used;
memcpy(ret, s, len);
sp->used += len;
return ret;
}

View File

@@ -1,17 +0,0 @@
#ifndef SHM_H
#define SHM_H
#include <unistd.h>
struct stringpool {
size_t alloced;
size_t used;
char* start;
};
void stringpool_init(struct stringpool* sp);
char* stringpool_add(struct stringpool *sp, char* s, size_t len);
#if 0
void *shm_realloc(void* old, size_t old_size, size_t new_size);
#endif
//RcB: DEP "shm.c"
#endif

View File

@@ -1,13 +0,0 @@
#include "stringdump.h"
#include "debug.h"
struct stringpool mem;
char *dumpstring(char* s, size_t len) {
PFUNC();
return stringpool_add(&mem, s, len);
}
void dumpstring_init(void) {
stringpool_init(&mem);
}

View File

@@ -1,12 +0,0 @@
#ifndef STRINGDUMP_H
#define STRINGDUMP_H
#include "shm.h"
#include <unistd.h>
char *dumpstring(char* s, size_t len);
void dumpstring_init(void);
//RcB: DEP "stringdump.h"
#endif

View File

@@ -1,6 +1,6 @@
#include <netdb.h>
#include <stdio.h>
#include "../src/common.h"
#include "../src/core.h"
void printhostent(struct hostent *hp) {
char ipbuf[16];

View File

@@ -1,61 +0,0 @@
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include "../src/common.h"
/*
int gethostent_r(
struct hostent *ret, char *buf, size_t buflen,
struct hostent **result, int *h_errnop);
Glibc2 also has reentrant versions gethostent_r(), gethostbyaddr_r(),
gethostbyname_r() and gethostbyname2_r().
The caller supplies a hostent structure ret which will be filled in on success,
and a temporary work buffer buf of size buflen.
After the call, result will point to the result on success.
In case of an error or if no entry is found result will be NULL.
The functions return 0 on success and a nonzero error number on failure.
In addition to the errors returned by the nonreentrant versions of these functions,
if buf is too small, the functions will return ERANGE, and the call should be retried
with a larger buffer.
The global variable h_errno is not modified, but the address of a variable in which
to store error numbers is passed in h_errnop.
*/
void printhostent(struct hostent *hp) {
char ipbuf[16];
pc_stringfromipv4(hp->h_addr_list[0], ipbuf);
printf("alias: %p, len: %d, name: %s, addrlist: %p, addrtype: %d, ip: %s\n",
hp->h_aliases,
hp->h_length,
hp->h_name,
hp->h_addr_list,
hp->h_addrtype,
ipbuf
);
}
int main(int argc, char** argv) {
struct hostent he_buf;
struct hostent *he_res;
char h_buf[1024];
int ch_errno;
int ret;
do {
ret = gethostent_r(&he_buf, h_buf, sizeof(h_buf), &he_res, &ch_errno);
printf("ret: %d, h_errno: %d\n", ret, ch_errno);
if(ret != 0) {
errno = ret;
ret = -1;
}
if(ret == -1) {
perror("gethostent_r");
break;
}
if(he_res) {
printhostent(he_res);
}
} while (he_res);
return 0;
}

View File

@@ -1,5 +1,4 @@
#include "../src/core.h"
#include "../src/common.h"
#include <stdio.h>
void printhostent(struct hostent *hp) {

View File

@@ -1,39 +0,0 @@
#include "../src/shm.h"
#include <assert.h>
#define s(A) (sizeof(A) - 1)
#define ss(A) (A), s(A)
int main() {
char buf4096[4096];
struct stringpool sp;
stringpool_init(&sp);
char *r;
size_t pos = 0;
r = stringpool_add(&sp, ss("AAAAA"));
assert(r == sp.start);
pos += s("AAAAA");
assert(sp.alloced == 4096);
assert(sp.used == pos);
r = stringpool_add(&sp, buf4096, sizeof(buf4096));
assert(r == sp.start + pos);
pos += sizeof(buf4096);
assert(sp.alloced == 4096 * 2);
assert(sp.used == pos);
r = stringpool_add(&sp, buf4096, 4096 - s("AAAAA"));
assert(r == sp.start + pos);
pos += 4096 - s("AAAAA");
assert(pos == 4096 * 2);
assert(sp.alloced == 4096 * 2);
assert(sp.used == pos);
return 0;
}