mirror of
https://github.com/rofl0r/proxychains-ng
synced 2026-05-13 17:03:07 +08:00
Compare commits
1 Commits
@@ -19,7 +19,7 @@ DOBJS = src/daemon/hsearch.o \
|
||||
src/daemon/sblist.o src/daemon/sblist_delete.o \
|
||||
src/daemon/daemon.o src/daemon/udpserver.o
|
||||
|
||||
LOBJS = src/version.o \
|
||||
LOBJS = src/nameinfo.o src/version.o \
|
||||
src/core.o src/common.o src/libproxychains.o \
|
||||
src/allocator_thread.o src/rdns.o \
|
||||
src/hostsreader.o src/hash.o src/debug.o
|
||||
@@ -29,7 +29,8 @@ GENH = src/version.h
|
||||
|
||||
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe
|
||||
NO_AS_NEEDED = -Wl,--no-as-needed
|
||||
LDFLAGS = -fPIC $(NO_AS_NEEDED) $(LIBDL) $(PTHREAD)
|
||||
LIBDL = -ldl
|
||||
LDFLAGS = -fPIC $(NO_AS_NEEDED) $(LIBDL) -lpthread
|
||||
INC =
|
||||
PIC = -fPIC
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ProxyChains-NG ver 4.16 README
|
||||
ProxyChains-NG ver 4.14 README
|
||||
=============================
|
||||
|
||||
ProxyChains is a UNIX program, that hooks network-related libc functions
|
||||
@@ -52,27 +52,6 @@ ProxyChains-NG ver 4.16 README
|
||||
|
||||
Changelog:
|
||||
----------
|
||||
Version 4.16
|
||||
- fix regression in configure script linker flag detection
|
||||
- remove 10 year old workaround for wrong glibc getnameinfo signature
|
||||
- support for new DYLD hooking method for OSX Monterey
|
||||
- netbsd compilation fix
|
||||
- support IPv6 localnets
|
||||
- more user-friendly error message when execvp fails
|
||||
- proxy_getaddrinfo(): fill in ai_socktype if requested
|
||||
|
||||
Version 4.15
|
||||
- fix configure script for buggy binutils version
|
||||
- initialize rand_seed with nano-second granularity
|
||||
- add support for numeric ipv6 in getaddrinfo
|
||||
- fix bug in getaddrinfo when node is null and !passive
|
||||
- add dnat feature
|
||||
- add raw proxy type
|
||||
- add haiku support
|
||||
- add proxy_dns_old to emulate proxychains 3.1 behaviour
|
||||
- add new proxy_dns_daemon feature (experimental)
|
||||
- various other fixes
|
||||
|
||||
Version 4.14
|
||||
- allow alternative proto://user:pass@ip:port syntax for proxylist
|
||||
- fix endless loop in round robin mode when all proxies are down (#147)
|
||||
@@ -257,7 +236,7 @@ Known Problems:
|
||||
|
||||
Community:
|
||||
----------
|
||||
#proxychains on irc.libera.chat
|
||||
#proxychains on irc.freenode.net
|
||||
|
||||
Donations:
|
||||
----------
|
||||
|
||||
@@ -19,29 +19,18 @@ check_compile() {
|
||||
printf "checking %s ... " "$1"
|
||||
printf "$3" > "$tmpc"
|
||||
local res=0
|
||||
$CC $OUR_CPPFLAGS $CPPFLAGS $2 $CFLAGS "$tmpc" -o "$tmpc".out >/dev/null 2>&1 \
|
||||
$CC $OUR_CPPFLAGS $CPPFLAGS $2 $CFLAGS "$tmpc" -o /dev/null >/dev/null 2>&1 \
|
||||
|| res=1
|
||||
test x$res = x0 && \
|
||||
{ printf "yes\n" ; test x"$2" = x || OUR_CPPFLAGS="$OUR_CPPFLAGS $2" ; } \
|
||||
|| printf "no\n"
|
||||
rm -f "$tmpc".out
|
||||
return $res
|
||||
}
|
||||
|
||||
get_define() {
|
||||
$CC $OUR_CPPFLAGS $CPPFLAGS $CFLAGS -dM -E - </dev/null | grep "$1"
|
||||
}
|
||||
|
||||
get_define_stripped() {
|
||||
local output=$(get_define "$1")
|
||||
test "$?" = 0 || return 1
|
||||
printf "%s\n" "$output" | sed 's/^.* .* //'
|
||||
}
|
||||
|
||||
check_define() {
|
||||
printf "checking whether \$CC defines %s ... " "$1"
|
||||
local res=1
|
||||
get_define "$1" >/dev/null && res=0
|
||||
$CC $OUR_CPPFLAGS $CPPFLAGS $CFLAGS -dM -E - </dev/null | grep "$1" >/dev/null && res=0
|
||||
test x$res = x0 && printf "yes\n" || printf "no\n"
|
||||
return $res
|
||||
}
|
||||
@@ -60,10 +49,7 @@ check_compile_run() {
|
||||
|
||||
check_link_silent() {
|
||||
printf "$2" > "$tmpc"
|
||||
local res=0
|
||||
$CC $OUR_CPPFLAGS $CPPFLAGS $1 $CFLAGS "$tmpc" -o "$tmpc".out >/dev/null 2>&1 || res=1
|
||||
rm -f "$tmpc".out
|
||||
return $res
|
||||
$CC $OUR_CPPFLAGS $CPPFLAGS $1 $CFLAGS "$tmpc" -o /dev/null >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_link() {
|
||||
@@ -84,10 +70,8 @@ usage() {
|
||||
echo "--sysconfdir=/path default: $prefix/etc"
|
||||
echo "--ignore-cve default: no"
|
||||
echo " if set to yes ignores CVE-2015-3887 and makes it possible"
|
||||
echo " to preload from current dir (possibly insecure, but handy)"
|
||||
echo " to preload from current dir (insecure)"
|
||||
echo "--fat-binary : build for both i386 and x86_64 architectures on 64-bit Macs"
|
||||
echo "--hookmethod=dlsym|dyld hook method for osx. default: auto"
|
||||
echo " if OSX >= 12 is detected, dyld method will be used if auto."
|
||||
echo "--help : show this text"
|
||||
exit 1
|
||||
}
|
||||
@@ -101,8 +85,6 @@ spliteq() {
|
||||
|
||||
fat_binary=
|
||||
ignore_cve=no
|
||||
hookmethod=auto
|
||||
|
||||
parsearg() {
|
||||
case "$1" in
|
||||
--prefix=*) prefix=`spliteq $1`;;
|
||||
@@ -113,7 +95,6 @@ parsearg() {
|
||||
--sysconfdir=*) sysconfdir=`spliteq $1`;;
|
||||
--ignore-cve) ignore_cve=1;;
|
||||
--ignore-cve=*) ignore_cve=`spliteq $1`;;
|
||||
--hookmethod=*) hookmethod=`spliteq $1`;;
|
||||
--fat-binary) fat_binary=1;;
|
||||
--help) usage;;
|
||||
esac
|
||||
@@ -170,7 +151,7 @@ issolaris() {
|
||||
}
|
||||
haiku_detected=false
|
||||
ishaiku() {
|
||||
$haiku_detected
|
||||
$haiku_detected
|
||||
}
|
||||
|
||||
check_compile 'whether C compiler works' '' 'int main() {return 0;}' || fail 'error: install a C compiler and library'
|
||||
@@ -184,16 +165,9 @@ check_compile 'whether we have pipe2() and O_CLOEXEC' "-DHAVE_PIPE2" \
|
||||
check_compile 'whether we have SOCK_CLOEXEC' "-DHAVE_SOCK_CLOEXEC" \
|
||||
'#define _GNU_SOURCE\n#include <sys/socket.h>\nint main() {\nreturn socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);}'
|
||||
|
||||
check_compile 'whether we have clock_gettime' "-DHAVE_CLOCK_GETTIME" \
|
||||
'#define _GNU_SOURCE\n#include <time.h>\nint main() {\nstruct timespec now;clock_gettime(CLOCK_REALTIME, &now);\nreturn now.tv_sec ^ now.tv_nsec;}'
|
||||
|
||||
check_define __APPLE__ && {
|
||||
mac_detected=true
|
||||
check_define __x86_64__ && mac_64=true
|
||||
if test "$hookmethod" = auto ; then
|
||||
osver=$(get_define_stripped __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 2>/dev/null)
|
||||
test "$osver" -gt $((120000 - 1)) && hookmethod=dyld
|
||||
fi
|
||||
}
|
||||
check_define __FreeBSD__ && bsd_detected=true
|
||||
check_define __OpenBSD__ && {
|
||||
@@ -234,32 +208,14 @@ fi
|
||||
echo "$LD_SONAME_FLAG"
|
||||
echo "LD_SET_SONAME = -Wl,$LD_SONAME_FLAG," >> config.mak
|
||||
|
||||
if check_link "checking whether we can use -ldl" "-ldl" \
|
||||
"int main(){return 0;}" ; then
|
||||
echo "LIBDL = -ldl" >> config.mak
|
||||
fi
|
||||
|
||||
if check_link "checking whether we can use -lpthread" "-lpthread" \
|
||||
"int main(){return 0;}" ; then
|
||||
echo "PTHREAD = -lpthread" >> config.mak
|
||||
else
|
||||
check_link "checking whether we can use -pthread" "-pthread" \
|
||||
"int main(){return 0;}" || fail "no pthread support detected"
|
||||
echo "PTHREAD = -pthread" >> config.mak
|
||||
fi
|
||||
|
||||
make_cmd=make
|
||||
if ismac ; then
|
||||
echo LDSO_SUFFIX=dylib>>config.mak
|
||||
echo MAC_CFLAGS+=-DIS_MAC=1>>config.mak
|
||||
if test "$hookmethod" = dyld ; then
|
||||
echo "using Monterey style DYLD hooking"
|
||||
echo "CFLAGS+=-DMONTEREY_HOOKING">>config.mak
|
||||
fi
|
||||
if ismac64 && [ "$fat_binary" = 1 ] ; then
|
||||
echo "Configuring a fat binary for i386 and x86_64"
|
||||
echo "MAC_CFLAGS+=-arch i386 -arch x86_64">>config.mak
|
||||
echo "LDFLAGS+=-arch i386 -arch x86_64">>config.mak
|
||||
echo MAC_CFLAGS+=-arch i386 -arch x86_64>>config.mak
|
||||
echo LDFLAGS+=-arch i386 -arch x86_64>>config.mak
|
||||
fi
|
||||
elif isbsd ; then
|
||||
echo LIBDL=>>config.mak
|
||||
|
||||
+50
-22
@@ -475,7 +475,8 @@ static proxy_data *select_proxy(select_type how, proxy_data * pd, unsigned int p
|
||||
case RANDOMLY:
|
||||
do {
|
||||
k++;
|
||||
i = rand() % proxy_count;
|
||||
i = rand() % (proxy_count-proxychains_fixed_chain);
|
||||
i += proxychains_fixed_chain;
|
||||
} while(pd[i].ps != PLAY_STATE && k < proxy_count * 100);
|
||||
break;
|
||||
case FIFOLY:
|
||||
@@ -563,9 +564,38 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int strict_connect(
|
||||
unsigned *alive_count,
|
||||
unsigned *offset,
|
||||
int *ns,
|
||||
proxy_data **p1, proxy_data **p2,
|
||||
unsigned proxy_count, proxy_data * pd)
|
||||
{
|
||||
*alive_count = calc_alive(pd, proxy_count);
|
||||
*offset = 0;
|
||||
if(!(*p1 = select_proxy(FIFOLY, pd, proxy_count, offset))) {
|
||||
PDEBUG("select_proxy failed\n");
|
||||
return 0;
|
||||
}
|
||||
if(SUCCESS != start_chain(ns, *p1, ST)) {
|
||||
PDEBUG("start_chain failed\n");
|
||||
return 0;
|
||||
}
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
*p1 = *p2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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) {
|
||||
unsigned int proxy_count, chain_type ct) {
|
||||
proxy_data p4;
|
||||
proxy_data *p1, *p2, *p3;
|
||||
int ns = -1;
|
||||
@@ -575,6 +605,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
unsigned int curr_len = 0;
|
||||
unsigned int looped = 0; // went back to start of list in RR mode
|
||||
unsigned int rr_loop_max = 14;
|
||||
unsigned int max_chain = proxychains_max_chain;
|
||||
|
||||
p3 = &p4;
|
||||
|
||||
@@ -583,9 +614,14 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
again:
|
||||
rc = -1;
|
||||
DUMP_PROXY_CHAIN(pd, proxy_count);
|
||||
if(proxychains_fixed_chain) {
|
||||
if(!strict_connect(&alive_count, &offset, &ns, &p1, &p2, proxychains_fixed_chain, pd))
|
||||
goto error_strict;
|
||||
}
|
||||
|
||||
switch (ct) {
|
||||
case DYNAMIC_TYPE:
|
||||
if(proxychains_fixed_chain) goto dyn_fixed_resume;
|
||||
alive_count = calc_alive(pd, proxy_count);
|
||||
offset = 0;
|
||||
do {
|
||||
@@ -601,6 +637,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
goto again;
|
||||
}
|
||||
p1 = p2;
|
||||
dyn_fixed_resume:;
|
||||
}
|
||||
//proxychains_write_log(TP);
|
||||
p3->ip = target_ip;
|
||||
@@ -610,6 +647,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
break;
|
||||
|
||||
case ROUND_ROBIN_TYPE:
|
||||
// FIXME: add support for fixed_len
|
||||
alive_count = calc_alive(pd, proxy_count);
|
||||
offset = proxychains_proxy_offset;
|
||||
if(alive_count < max_chain)
|
||||
@@ -660,25 +698,8 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
break;
|
||||
|
||||
case STRICT_TYPE:
|
||||
alive_count = calc_alive(pd, proxy_count);
|
||||
offset = 0;
|
||||
if(!(p1 = select_proxy(FIFOLY, pd, proxy_count, &offset))) {
|
||||
PDEBUG("select_proxy failed\n");
|
||||
if(!strict_connect(&alive_count, &offset, &ns, &p1, &p2, proxy_count, pd))
|
||||
goto error_strict;
|
||||
}
|
||||
if(SUCCESS != start_chain(&ns, p1, ST)) {
|
||||
PDEBUG("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");
|
||||
goto error_strict;
|
||||
}
|
||||
p1 = p2;
|
||||
}
|
||||
//proxychains_write_log(TP);
|
||||
p3->ip = target_ip;
|
||||
p3->port = target_port;
|
||||
@@ -687,6 +708,12 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
break;
|
||||
|
||||
case RANDOM_TYPE:
|
||||
if(proxychains_fixed_chain) {
|
||||
if(alive_count < max_chain)
|
||||
goto error_more;
|
||||
curr_len = proxychains_fixed_chain - 1;
|
||||
goto random_fixed_resume;
|
||||
}
|
||||
alive_count = calc_alive(pd, proxy_count);
|
||||
if(alive_count < max_chain)
|
||||
goto error_more;
|
||||
@@ -695,6 +722,9 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
||||
if(!(p1 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
|
||||
goto error_more;
|
||||
} while(SUCCESS != start_chain(&ns, p1, RT) && offset < max_chain);
|
||||
|
||||
random_fixed_resume:;
|
||||
|
||||
while(++curr_len < max_chain) {
|
||||
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
|
||||
goto error_more;
|
||||
@@ -1018,8 +1048,6 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
|
||||
p->ai_socktype = hints->ai_socktype;
|
||||
p->ai_flags = hints->ai_flags;
|
||||
p->ai_protocol = hints->ai_protocol;
|
||||
if(!p->ai_socktype && p->ai_protocol == IPPROTO_TCP)
|
||||
p->ai_socktype = SOCK_STREAM;
|
||||
} else {
|
||||
#ifndef AI_V4MAPPED
|
||||
#define AI_V4MAPPED 0
|
||||
|
||||
+5
-13
@@ -65,18 +65,8 @@ typedef enum {
|
||||
} select_type;
|
||||
|
||||
typedef struct {
|
||||
sa_family_t family;
|
||||
struct in_addr in_addr, netmask;
|
||||
unsigned short port;
|
||||
union {
|
||||
struct {
|
||||
struct in_addr in_addr;
|
||||
struct in_addr in_mask;
|
||||
};
|
||||
struct {
|
||||
struct in6_addr in6_addr;
|
||||
unsigned char in6_prefix;
|
||||
};
|
||||
};
|
||||
} localaddr_arg;
|
||||
|
||||
typedef struct {
|
||||
@@ -94,8 +84,7 @@ typedef struct {
|
||||
} proxy_data;
|
||||
|
||||
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 );
|
||||
proxy_data * pd, unsigned int proxy_count, chain_type ct );
|
||||
|
||||
void proxychains_write_log(char *str, ...);
|
||||
|
||||
@@ -140,6 +129,9 @@ void proxy_freeaddrinfo(struct addrinfo *res);
|
||||
void core_initialize(void);
|
||||
void core_unload(void);
|
||||
|
||||
extern unsigned int proxychains_max_chain;
|
||||
extern unsigned int proxychains_fixed_chain;
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#endif
|
||||
|
||||
+77
-145
@@ -22,7 +22,6 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
@@ -72,6 +71,7 @@ unsigned int proxychains_proxy_count = 0;
|
||||
unsigned int proxychains_proxy_offset = 0;
|
||||
int proxychains_got_chain_data = 0;
|
||||
unsigned int proxychains_max_chain = 1;
|
||||
unsigned int proxychains_fixed_chain = 0;
|
||||
int proxychains_quiet_mode = 0;
|
||||
enum dns_lookup_flavor proxychains_resolver = DNSLF_LIBC;
|
||||
localaddr_arg localnet_addr[MAX_LOCALNET];
|
||||
@@ -105,28 +105,31 @@ static void* load_sym(char* symname, void* proxyfunc) {
|
||||
|
||||
#define INIT() init_lib_wrapper(__FUNCTION__)
|
||||
|
||||
#define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = load_sym( # X, X ); } while(0)
|
||||
|
||||
#include "allocator_thread.h"
|
||||
|
||||
const char *proxychains_get_version(void);
|
||||
|
||||
static void setup_hooks(void);
|
||||
static void setup_hooks(void) {
|
||||
SETUP_SYM(connect);
|
||||
SETUP_SYM(sendto);
|
||||
SETUP_SYM(gethostbyname);
|
||||
SETUP_SYM(getaddrinfo);
|
||||
SETUP_SYM(freeaddrinfo);
|
||||
SETUP_SYM(gethostbyaddr);
|
||||
SETUP_SYM(getnameinfo);
|
||||
#ifdef IS_SOLARIS
|
||||
SETUP_SYM(__xnet_connect);
|
||||
#endif
|
||||
SETUP_SYM(close);
|
||||
}
|
||||
|
||||
static int close_fds[16];
|
||||
static int close_fds_cnt = 0;
|
||||
|
||||
static unsigned get_rand_seed(void) {
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
return now.tv_sec ^ now.tv_nsec;
|
||||
#else
|
||||
return time(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void do_init(void) {
|
||||
srand(get_rand_seed());
|
||||
srand(time(NULL));
|
||||
core_initialize();
|
||||
|
||||
/* read the config file */
|
||||
@@ -270,7 +273,8 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
|
||||
int count = 0, port_n = 0, list = 0;
|
||||
char buf[1024], type[1024], host[1024], user[1024];
|
||||
char *buff, *env, *p;
|
||||
char local_addr_port[64], local_addr[64], local_netmask[32];
|
||||
char local_in_addr_port[32];
|
||||
char local_in_addr[32], local_in_port[32], local_netmask[32];
|
||||
char dnat_orig_addr_port[32], dnat_new_addr_port[32];
|
||||
char dnat_orig_addr[32], dnat_orig_port[32], dnat_new_addr[32], dnat_new_port[32];
|
||||
char rdnsd_addr[32], rdnsd_port[8];
|
||||
@@ -385,76 +389,42 @@ inv_host:
|
||||
exit(1);
|
||||
}
|
||||
} else if(STR_STARTSWITH(buff, "localnet")) {
|
||||
char colon, extra, right_bracket[2];
|
||||
unsigned short local_port = 0, local_prefix;
|
||||
int local_family, n, valid;
|
||||
if(sscanf(buff, "%s %53[^/]/%15s%c", user, local_addr_port, local_netmask, &extra) != 3) {
|
||||
if(sscanf(buff, "%s %21[^/]/%15s", user, local_in_addr_port, local_netmask) < 3) {
|
||||
fprintf(stderr, "localnet format error");
|
||||
exit(1);
|
||||
}
|
||||
p = strchr(local_addr_port, ':');
|
||||
if(!p || p == strrchr(local_addr_port, ':')) {
|
||||
local_family = AF_INET;
|
||||
n = sscanf(local_addr_port, "%15[^:]%c%5hu%c", local_addr, &colon, &local_port, &extra);
|
||||
valid = n == 1 || (n == 3 && colon == ':');
|
||||
} else if(local_addr_port[0] == '[') {
|
||||
local_family = AF_INET6;
|
||||
n = sscanf(local_addr_port, "[%45[^][]%1[]]%c%5hu%c", local_addr, right_bracket, &colon, &local_port, &extra);
|
||||
valid = n == 2 || (n == 4 && colon == ':');
|
||||
} else {
|
||||
local_family = AF_INET6;
|
||||
valid = sscanf(local_addr_port, "%45[^][]%c", local_addr, &extra) == 1;
|
||||
}
|
||||
if(!valid) {
|
||||
fprintf(stderr, "localnet address or port error\n");
|
||||
exit(1);
|
||||
}
|
||||
if(local_port) {
|
||||
PDEBUG("added localnet: netaddr=%s, port=%u, netmask=%s\n",
|
||||
local_addr, local_port, local_netmask);
|
||||
} else {
|
||||
/* 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_addr, local_netmask);
|
||||
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) {
|
||||
localnet_addr[num_localnet_addr].family = local_family;
|
||||
localnet_addr[num_localnet_addr].port = local_port;
|
||||
valid = 0;
|
||||
if (local_family == AF_INET) {
|
||||
valid =
|
||||
inet_pton(local_family, local_addr,
|
||||
&localnet_addr[num_localnet_addr].in_addr) > 0;
|
||||
} else if(local_family == AF_INET6) {
|
||||
valid =
|
||||
inet_pton(local_family, local_addr,
|
||||
&localnet_addr[num_localnet_addr].in6_addr) > 0;
|
||||
}
|
||||
if(!valid) {
|
||||
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);
|
||||
}
|
||||
if(local_family == AF_INET && strchr(local_netmask, '.')) {
|
||||
valid =
|
||||
inet_pton(local_family, local_netmask,
|
||||
&localnet_addr[num_localnet_addr].in_mask) > 0;
|
||||
} else {
|
||||
valid = sscanf(local_netmask, "%hu%c", &local_prefix, &extra) == 1;
|
||||
if (valid) {
|
||||
if(local_family == AF_INET && local_prefix <= 32) {
|
||||
localnet_addr[num_localnet_addr].in_mask.s_addr =
|
||||
htonl(0xFFFFFFFFu << (32u - local_prefix));
|
||||
} else if(local_family == AF_INET6 && local_prefix <= 128) {
|
||||
localnet_addr[num_localnet_addr].in6_prefix =
|
||||
local_prefix;
|
||||
} else {
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!valid) {
|
||||
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);
|
||||
@@ -469,6 +439,16 @@ inv_host:
|
||||
}
|
||||
len = atoi(++pc);
|
||||
proxychains_max_chain = (len ? len : 1);
|
||||
} else if(STR_STARTSWITH(buff, "fixed_len")) {
|
||||
char *pc;
|
||||
int len;
|
||||
pc = strchr(buff, '=');
|
||||
if(!pc) {
|
||||
fprintf(stderr, "error: missing equals sign '=' in fixed_len directive.\n");
|
||||
exit(1);
|
||||
}
|
||||
len = atoi(++pc);
|
||||
proxychains_fixed_chain = (len ? len : 1);
|
||||
} else if(!strcmp(buff, "quiet_mode")) {
|
||||
proxychains_quiet_mode = 1;
|
||||
} else if(!strcmp(buff, "proxy_dns_old")) {
|
||||
@@ -551,6 +531,14 @@ inv_host:
|
||||
fprintf(stderr, "error: no valid proxy found in config\n");
|
||||
exit(1);
|
||||
}
|
||||
if(proxychains_max_chain <= proxychains_fixed_chain) {
|
||||
fprintf(stderr, "error: fixed_len needs to be smaller than chain_len\n");
|
||||
exit(1);
|
||||
}
|
||||
if(proxychains_fixed_chain > count) {
|
||||
fprintf(stderr, "error: fixed_len > proxycount\n");
|
||||
exit(1);
|
||||
}
|
||||
*proxy_count = count;
|
||||
proxychains_got_chain_data = 1;
|
||||
PDEBUG("proxy_dns: %s\n", rdns_resolver_string(proxychains_resolver));
|
||||
@@ -558,14 +546,7 @@ inv_host:
|
||||
|
||||
/******* HOOK FUNCTIONS *******/
|
||||
|
||||
#define EXPAND( args...) args
|
||||
#ifdef MONTEREY_HOOKING
|
||||
#define HOOKFUNC(R, N, args...) R pxcng_ ## N ( EXPAND(args) )
|
||||
#else
|
||||
#define HOOKFUNC(R, N, args...) R N ( EXPAND(args) )
|
||||
#endif
|
||||
|
||||
HOOKFUNC(int, close, int fd) {
|
||||
int close(int fd) {
|
||||
if(!init_l) {
|
||||
if(close_fds_cnt>=(sizeof close_fds/sizeof close_fds[0])) goto err;
|
||||
close_fds[close_fds_cnt++] = fd;
|
||||
@@ -586,8 +567,7 @@ HOOKFUNC(int, close, int fd) {
|
||||
static int is_v4inv6(const struct in6_addr *a) {
|
||||
return !memcmp(a->s6_addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
|
||||
}
|
||||
|
||||
HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) {
|
||||
int connect(int sock, const struct sockaddr *addr, unsigned int len) {
|
||||
INIT();
|
||||
PFUNC();
|
||||
|
||||
@@ -650,24 +630,14 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len)
|
||||
port = dnat->new_port;
|
||||
}
|
||||
|
||||
for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) {
|
||||
if (localnet_addr[i].port && localnet_addr[i].port != port)
|
||||
continue;
|
||||
if (localnet_addr[i].family != (v6 ? AF_INET6 : AF_INET))
|
||||
continue;
|
||||
if (v6) {
|
||||
size_t prefix_bytes = localnet_addr[i].in6_prefix / CHAR_BIT;
|
||||
size_t prefix_bits = localnet_addr[i].in6_prefix % CHAR_BIT;
|
||||
if (prefix_bytes && memcmp(p_addr_in6->s6_addr, localnet_addr[i].in6_addr.s6_addr, prefix_bytes) != 0)
|
||||
continue;
|
||||
if (prefix_bits && (p_addr_in6->s6_addr[prefix_bytes] ^ localnet_addr[i].in6_addr.s6_addr[prefix_bytes]) >> (CHAR_BIT - prefix_bits))
|
||||
continue;
|
||||
} else {
|
||||
if((p_addr_in->s_addr ^ localnet_addr[i].in_addr.s_addr) & localnet_addr[i].in_mask.s_addr)
|
||||
continue;
|
||||
if (!v6) 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);
|
||||
}
|
||||
}
|
||||
PDEBUG("accessing localnet using true_connect\n");
|
||||
return true_connect(sock, addr, len);
|
||||
}
|
||||
|
||||
flags = fcntl(sock, F_GETFL, 0);
|
||||
@@ -679,7 +649,7 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len)
|
||||
ret = connect_proxy_chain(sock,
|
||||
dest_ip,
|
||||
htons(port),
|
||||
proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain);
|
||||
proxychains_pd, proxychains_proxy_count, proxychains_ct);
|
||||
|
||||
fcntl(sock, F_SETFL, flags);
|
||||
if(ret != SUCCESS)
|
||||
@@ -688,13 +658,13 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len)
|
||||
}
|
||||
|
||||
#ifdef IS_SOLARIS
|
||||
HOOKFUNC(int, __xnet_connect, int sock, const struct sockaddr *addr, unsigned int len)
|
||||
int __xnet_connect(int sock, const struct sockaddr *addr, unsigned int len) {
|
||||
return connect(sock, addr, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct gethostbyname_data ghbndata;
|
||||
HOOKFUNC(struct hostent*, gethostbyname, const char *name) {
|
||||
struct hostent *gethostbyname(const char *name) {
|
||||
INIT();
|
||||
PDEBUG("gethostbyname: %s\n", name);
|
||||
|
||||
@@ -708,7 +678,7 @@ HOOKFUNC(struct hostent*, gethostbyname, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HOOKFUNC(int, getaddrinfo, const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||
INIT();
|
||||
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
|
||||
|
||||
@@ -718,7 +688,7 @@ HOOKFUNC(int, getaddrinfo, const char *node, const char *service, const struct a
|
||||
return true_getaddrinfo(node, service, hints, res);
|
||||
}
|
||||
|
||||
HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
|
||||
void freeaddrinfo(struct addrinfo *res) {
|
||||
INIT();
|
||||
PDEBUG("freeaddrinfo %p \n", (void *) res);
|
||||
|
||||
@@ -728,7 +698,7 @@ HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
|
||||
proxy_freeaddrinfo(res);
|
||||
}
|
||||
|
||||
HOOKFUNC(int, getnameinfo, const struct sockaddr *sa, socklen_t salen,
|
||||
int pc_getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
||||
char *host, socklen_t hostlen, char *serv,
|
||||
socklen_t servlen, int flags)
|
||||
{
|
||||
@@ -772,7 +742,7 @@ HOOKFUNC(int, getnameinfo, const struct sockaddr *sa, socklen_t salen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
HOOKFUNC(struct hostent*, gethostbyaddr, const void *addr, socklen_t len, int type) {
|
||||
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
||||
INIT();
|
||||
PDEBUG("TODO: proper gethostbyaddr hook\n");
|
||||
|
||||
@@ -808,7 +778,7 @@ HOOKFUNC(struct hostent*, gethostbyaddr, const void *addr, socklen_t len, int ty
|
||||
# define MSG_FASTOPEN 0x20000000
|
||||
#endif
|
||||
|
||||
HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
||||
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
||||
const struct sockaddr *dest_addr, socklen_t addrlen) {
|
||||
INIT();
|
||||
PFUNC();
|
||||
@@ -822,41 +792,3 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
||||
}
|
||||
return true_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
|
||||
}
|
||||
|
||||
#ifdef MONTEREY_HOOKING
|
||||
#define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = &X; } while(0)
|
||||
#else
|
||||
#define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = load_sym( # X, X ); } while(0)
|
||||
#endif
|
||||
|
||||
static void setup_hooks(void) {
|
||||
SETUP_SYM(connect);
|
||||
SETUP_SYM(sendto);
|
||||
SETUP_SYM(gethostbyname);
|
||||
SETUP_SYM(getaddrinfo);
|
||||
SETUP_SYM(freeaddrinfo);
|
||||
SETUP_SYM(gethostbyaddr);
|
||||
SETUP_SYM(getnameinfo);
|
||||
#ifdef IS_SOLARIS
|
||||
SETUP_SYM(__xnet_connect);
|
||||
#endif
|
||||
SETUP_SYM(close);
|
||||
}
|
||||
|
||||
#ifdef MONTEREY_HOOKING
|
||||
|
||||
#define DYLD_INTERPOSE(_replacement,_replacee) \
|
||||
__attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \
|
||||
__attribute__((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee };
|
||||
#define DYLD_HOOK(F) DYLD_INTERPOSE(pxcng_ ## F, F)
|
||||
|
||||
DYLD_HOOK(connect);
|
||||
DYLD_HOOK(sendto);
|
||||
DYLD_HOOK(gethostbyname);
|
||||
DYLD_HOOK(getaddrinfo);
|
||||
DYLD_HOOK(freeaddrinfo);
|
||||
DYLD_HOOK(gethostbyaddr);
|
||||
DYLD_HOOK(getnameinfo);
|
||||
DYLD_HOOK(close);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-2
@@ -154,8 +154,7 @@ int main(int argc, char *argv[]) {
|
||||
old_val ? old_val : "");
|
||||
putenv(buf);
|
||||
execvp(argv[start_argv], &argv[start_argv]);
|
||||
fprintf(stderr, "proxychains: can't load process '%s'.", argv[start_argv]);
|
||||
perror(" (hint: it's probably a typo)");
|
||||
perror("proxychains can't load process....");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
extern int pc_getnameinfo(const void *sa, socklen_t salen,
|
||||
char *host, socklen_t hostlen, char *serv,
|
||||
socklen_t servlen, int flags);
|
||||
|
||||
|
||||
int getnameinfo(const void *sa, socklen_t salen,
|
||||
char *host, socklen_t hostlen, char *serv,
|
||||
socklen_t servlen, int flags) {
|
||||
return pc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
|
||||
}
|
||||
|
||||
+10
-6
@@ -45,6 +45,12 @@ strict_chain
|
||||
# Make sense only if random_chain or round_robin_chain
|
||||
#chain_len = 2
|
||||
|
||||
# use this if you want to use e.g. random_chain but always have
|
||||
# e.g. tor as first proxy. in that case only chain_len - fixed_len proxies
|
||||
# will be used for random chain.
|
||||
# currently only implemented for dynamic_chain and random_chain.
|
||||
#fixed_len = 1
|
||||
|
||||
# Quiet mode (no output from library)
|
||||
#quiet_mode
|
||||
|
||||
@@ -53,9 +59,9 @@ strict_chain
|
||||
|
||||
# method 1. this uses the proxychains4 style method to do remote dns:
|
||||
# a thread is spawned that serves DNS requests and hands down an ip
|
||||
# assigned from an internal list (via remote_dns_subnet).
|
||||
# assigned from an internal list (via remote_dns_subset).
|
||||
# this is the easiest (setup-wise) and fastest method, however on
|
||||
# systems with buggy libcs and very complex software like webbrowsers
|
||||
# systems with buggy libcs and very complex software like webbrosers
|
||||
# this might not work and/or cause crashes.
|
||||
proxy_dns
|
||||
|
||||
@@ -94,7 +100,7 @@ tcp_connect_time_out 8000
|
||||
|
||||
### Examples for localnet exclusion
|
||||
## localnet ranges will *not* use a proxy to connect.
|
||||
## note that localnet works only when plain IP addresses are passed to the app,
|
||||
## note that localnet works only when plain IPv4 addresses are passed to the app,
|
||||
## the hostname resolves via /etc/hosts, or proxy_dns is disabled or proxy_dns_old used.
|
||||
|
||||
## Exclude connections to 192.168.1.0/24 with port 80
|
||||
@@ -105,14 +111,12 @@ tcp_connect_time_out 8000
|
||||
|
||||
## Exclude connections to ANYwhere with port 80
|
||||
# localnet 0.0.0.0:80/0.0.0.0
|
||||
# localnet [::]:80/0
|
||||
|
||||
## RFC6890 Loopback address range
|
||||
## 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
|
||||
# localnet ::1/128
|
||||
|
||||
## RFC1918 Private Address Ranges
|
||||
# localnet 10.0.0.0/255.0.0.0
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef NI_MAXHOST
|
||||
#define NI_MAXHOST 1025
|
||||
@@ -45,42 +43,9 @@ static int doit(const char* host, const char* service) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* reproduce use of getaddrinfo as used by nmap 7.91's canonicalize_address */
|
||||
int canonicalize_address(struct sockaddr_storage *ss, struct sockaddr_storage *output) {
|
||||
char canonical_ip_string[NI_MAXHOST];
|
||||
struct addrinfo *ai;
|
||||
int rc;
|
||||
/* Convert address to string. */
|
||||
rc = getnameinfo((struct sockaddr *) ss, sizeof(*ss),
|
||||
canonical_ip_string, sizeof(canonical_ip_string), NULL, 0, NI_NUMERICHOST);
|
||||
assert(rc == 0);
|
||||
struct addrinfo hints = {
|
||||
.ai_family = ss->ss_family,
|
||||
.ai_socktype = SOCK_DGRAM,
|
||||
.ai_flags = AI_NUMERICHOST,
|
||||
};
|
||||
rc = getaddrinfo(canonical_ip_string, NULL, &hints, &ai);
|
||||
if (rc != 0 || ai == NULL)
|
||||
return -1;
|
||||
assert(ai->ai_addrlen > 0 && ai->ai_addrlen <= (int) sizeof(*output));
|
||||
memcpy(output, ai->ai_addr, ai->ai_addrlen);
|
||||
freeaddrinfo(ai);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int ret;
|
||||
ret = doit("www.example.com", NULL);
|
||||
ret = doit("www.example.com", "80");
|
||||
struct sockaddr_storage o, ss = {.ss_family = PF_INET};
|
||||
struct sockaddr_in *v4 = &ss;
|
||||
struct sockaddr_in6 *v6 = &ss;
|
||||
memcpy(&v4->sin_addr, "\x7f\0\0\1", 4);
|
||||
ret = canonicalize_address(&ss, &o);
|
||||
assert (ret == 0);
|
||||
ss.ss_family = PF_INET6;
|
||||
memcpy(&v6->sin6_addr, "\0\0\0\0" "\0\0\0\0" "\0\0\0\0""\0\0\0\1", 16);
|
||||
ret = canonicalize_address(&ss, &o);
|
||||
assert (ret == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -123,17 +123,5 @@ int main() {
|
||||
|
||||
ASSERT(ret == 0);
|
||||
|
||||
b.sin6_port = 0;
|
||||
b.sin6_scope_id = 0;
|
||||
memcpy(&b.sin6_addr,"\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\1", 16);
|
||||
|
||||
if ((ret = getnameinfo((void*)sb, sizeof b, hbuf, sizeof(hbuf), NULL,
|
||||
0, NI_NUMERICHOST)) == 0)
|
||||
printf("host=%s\n", hbuf);
|
||||
else
|
||||
printf("%s\n", gai_strerror(ret));
|
||||
|
||||
ASSERT(ret == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user