mirror of
https://github.com/rofl0r/proxychains-ng
synced 2026-05-14 17:42:36 +08:00
Compare commits
36 Commits
@@ -1,4 +1,5 @@
|
|||||||
proxychains4
|
proxychains4
|
||||||
|
proxychains4-daemon
|
||||||
*.bz2
|
*.bz2
|
||||||
*.xz
|
*.xz
|
||||||
*.o
|
*.o
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ bindir = $(exec_prefix)/bin
|
|||||||
prefix = /usr/local/
|
prefix = /usr/local/
|
||||||
includedir = $(prefix)/include
|
includedir = $(prefix)/include
|
||||||
libdir = $(prefix)/lib
|
libdir = $(prefix)/lib
|
||||||
sysconfdir=$(prefix)/etc
|
sysconfdir = $(prefix)/etc
|
||||||
|
zshcompletiondir = $(prefix)/share/zsh/site-functions
|
||||||
|
|
||||||
OBJS = src/common.o src/main.o
|
OBJS = src/common.o src/main.o
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ DOBJS = src/daemon/hsearch.o \
|
|||||||
src/daemon/sblist.o src/daemon/sblist_delete.o \
|
src/daemon/sblist.o src/daemon/sblist_delete.o \
|
||||||
src/daemon/daemon.o src/daemon/udpserver.o
|
src/daemon/daemon.o src/daemon/udpserver.o
|
||||||
|
|
||||||
LOBJS = src/nameinfo.o src/version.o \
|
LOBJS = src/version.o \
|
||||||
src/core.o src/common.o src/libproxychains.o \
|
src/core.o src/common.o src/libproxychains.o \
|
||||||
src/allocator_thread.o src/rdns.o \
|
src/allocator_thread.o src/rdns.o \
|
||||||
src/hostsreader.o src/hash.o src/debug.o
|
src/hostsreader.o src/hash.o src/debug.o
|
||||||
@@ -29,8 +30,7 @@ GENH = src/version.h
|
|||||||
|
|
||||||
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe
|
CFLAGS += -Wall -O0 -g -std=c99 -D_GNU_SOURCE -pipe
|
||||||
NO_AS_NEEDED = -Wl,--no-as-needed
|
NO_AS_NEEDED = -Wl,--no-as-needed
|
||||||
LIBDL = -ldl
|
LDFLAGS = -fPIC $(NO_AS_NEEDED) $(LIBDL) $(PTHREAD)
|
||||||
LDFLAGS = -fPIC $(NO_AS_NEEDED) $(LIBDL) -lpthread
|
|
||||||
INC =
|
INC =
|
||||||
PIC = -fPIC
|
PIC = -fPIC
|
||||||
AR = $(CROSS_COMPILE)ar
|
AR = $(CROSS_COMPILE)ar
|
||||||
@@ -49,6 +49,7 @@ PXCHAINS = proxychains4
|
|||||||
PXCHAINS_D = proxychains4-daemon
|
PXCHAINS_D = proxychains4-daemon
|
||||||
ALL_TOOLS = $(PXCHAINS) $(PXCHAINS_D)
|
ALL_TOOLS = $(PXCHAINS) $(PXCHAINS_D)
|
||||||
ALL_CONFIGS = src/proxychains.conf
|
ALL_CONFIGS = src/proxychains.conf
|
||||||
|
ZSH_COMPLETION = completions/zsh/_proxychains4
|
||||||
|
|
||||||
-include config.mak
|
-include config.mak
|
||||||
|
|
||||||
@@ -69,9 +70,13 @@ $(DESTDIR)$(libdir)/%: %
|
|||||||
$(DESTDIR)$(sysconfdir)/%: src/%
|
$(DESTDIR)$(sysconfdir)/%: src/%
|
||||||
$(INSTALL) -D -m 644 $< $@
|
$(INSTALL) -D -m 644 $< $@
|
||||||
|
|
||||||
|
$(DESTDIR)$(zshcompletiondir)/%: completions/zsh/%
|
||||||
|
$(INSTALL) -D -m 644 $< $@
|
||||||
|
|
||||||
install-libs: $(ALL_LIBS:%=$(DESTDIR)$(libdir)/%)
|
install-libs: $(ALL_LIBS:%=$(DESTDIR)$(libdir)/%)
|
||||||
install-tools: $(ALL_TOOLS:%=$(DESTDIR)$(bindir)/%)
|
install-tools: $(ALL_TOOLS:%=$(DESTDIR)$(bindir)/%)
|
||||||
install-config: $(ALL_CONFIGS:src/%=$(DESTDIR)$(sysconfdir)/%)
|
install-config: $(ALL_CONFIGS:src/%=$(DESTDIR)$(sysconfdir)/%)
|
||||||
|
install-zsh-completion: $(ZSH_COMPLETION:completions/zsh/%=$(DESTDIR)$(zshcompletiondir)/%)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(ALL_LIBS)
|
rm -f $(ALL_LIBS)
|
||||||
@@ -88,14 +93,14 @@ src/version.o: src/version.h
|
|||||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_MAIN) $(INC) $(PIC) -c -o $@ $<
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_MAIN) $(INC) $(PIC) -c -o $@ $<
|
||||||
|
|
||||||
$(LDSO_PATHNAME): $(LOBJS)
|
$(LDSO_PATHNAME): $(LOBJS)
|
||||||
$(CC) $(LDFLAGS) $(LD_SET_SONAME)$(LDSO_PATHNAME) $(USER_LDFLAGS) \
|
$(CC) $(LDFLAGS) $(FAT_LDFLAGS) $(LD_SET_SONAME)$(LDSO_PATHNAME) \
|
||||||
-shared -o $@ $^ $(SOCKET_LIBS)
|
$(USER_LDFLAGS) -shared -o $@ $^ $(SOCKET_LIBS)
|
||||||
|
|
||||||
$(PXCHAINS): $(OBJS)
|
$(PXCHAINS): $(OBJS)
|
||||||
$(CC) $^ $(USER_LDFLAGS) $(LIBDL) -o $@
|
$(CC) $^ $(FAT_BIN_LDFLAGS) $(USER_LDFLAGS) $(LIBDL) -o $@
|
||||||
|
|
||||||
$(PXCHAINS_D): $(DOBJS)
|
$(PXCHAINS_D): $(DOBJS)
|
||||||
$(CC) $^ $(USER_LDFLAGS) -o $@
|
$(CC) $^ $(FAT_BIN_LDFLAGS) $(USER_LDFLAGS) -o $@
|
||||||
|
|
||||||
|
|
||||||
.PHONY: all clean install install-config install-libs install-tools
|
.PHONY: all clean install install-config install-libs install-tools install-zsh-completion
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
ProxyChains-NG ver 4.14 README
|
ProxyChains-NG ver 4.17 README
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
ProxyChains is a UNIX program, that hooks network-related libc functions
|
ProxyChains is a UNIX program, that hooks network-related libc functions
|
||||||
@@ -52,6 +52,36 @@ ProxyChains-NG ver 4.14 README
|
|||||||
|
|
||||||
Changelog:
|
Changelog:
|
||||||
----------
|
----------
|
||||||
|
Version 4.17
|
||||||
|
- add hook for close_range function, fixing newer versions of openssh
|
||||||
|
- fat-binary-m1 option for mac
|
||||||
|
- fix DNS error handling in proxy_dns_old
|
||||||
|
- simplify init code
|
||||||
|
- fix openbsd preloading
|
||||||
|
- fix double-close in multithreaded apps
|
||||||
|
- various improvements to configure script
|
||||||
|
|
||||||
|
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
|
Version 4.14
|
||||||
- allow alternative proto://user:pass@ip:port syntax for proxylist
|
- allow alternative proto://user:pass@ip:port syntax for proxylist
|
||||||
- fix endless loop in round robin mode when all proxies are down (#147)
|
- fix endless loop in round robin mode when all proxies are down (#147)
|
||||||
@@ -236,7 +266,7 @@ Known Problems:
|
|||||||
|
|
||||||
Community:
|
Community:
|
||||||
----------
|
----------
|
||||||
#proxychains on irc.freenode.net
|
#proxychains on irc.libera.chat
|
||||||
|
|
||||||
Donations:
|
Donations:
|
||||||
----------
|
----------
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#compdef proxychains4
|
||||||
|
|
||||||
|
_arguments \
|
||||||
|
'(- : *)--help[More help in README file]' \
|
||||||
|
'-q[makes proxychains quiet - this overrides the config setting]' \
|
||||||
|
'-f[allows one to manually specify a configfile to use]: :_files' \
|
||||||
|
'(-)1: :{_command_names -e}' \
|
||||||
|
'*:: :_normal'
|
||||||
@@ -19,18 +19,29 @@ check_compile() {
|
|||||||
printf "checking %s ... " "$1"
|
printf "checking %s ... " "$1"
|
||||||
printf "$3" > "$tmpc"
|
printf "$3" > "$tmpc"
|
||||||
local res=0
|
local res=0
|
||||||
$CC $OUR_CPPFLAGS $CPPFLAGS $2 $CFLAGS "$tmpc" -o /dev/null >/dev/null 2>&1 \
|
$CC $OUR_CPPFLAGS $CPPFLAGS $2 $CFLAGS "$tmpc" -o "$tmpc".out >/dev/null 2>&1 \
|
||||||
|| res=1
|
|| res=1
|
||||||
test x$res = x0 && \
|
test x$res = x0 && \
|
||||||
{ printf "yes\n" ; test x"$2" = x || OUR_CPPFLAGS="$OUR_CPPFLAGS $2" ; } \
|
{ printf "yes\n" ; test x"$2" = x || OUR_CPPFLAGS="$OUR_CPPFLAGS $2" ; } \
|
||||||
|| printf "no\n"
|
|| printf "no\n"
|
||||||
|
rm -f "$tmpc".out
|
||||||
return $res
|
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() {
|
check_define() {
|
||||||
printf "checking whether \$CC defines %s ... " "$1"
|
printf "checking whether \$CC defines %s ... " "$1"
|
||||||
local res=1
|
local res=1
|
||||||
$CC $OUR_CPPFLAGS $CPPFLAGS $CFLAGS -dM -E - </dev/null | grep "$1" >/dev/null && res=0
|
get_define "$1" >/dev/null && res=0
|
||||||
test x$res = x0 && printf "yes\n" || printf "no\n"
|
test x$res = x0 && printf "yes\n" || printf "no\n"
|
||||||
return $res
|
return $res
|
||||||
}
|
}
|
||||||
@@ -49,7 +60,10 @@ check_compile_run() {
|
|||||||
|
|
||||||
check_link_silent() {
|
check_link_silent() {
|
||||||
printf "$2" > "$tmpc"
|
printf "$2" > "$tmpc"
|
||||||
$CC $OUR_CPPFLAGS $CPPFLAGS $1 $CFLAGS "$tmpc" -o /dev/null >/dev/null 2>&1
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
check_link() {
|
check_link() {
|
||||||
@@ -70,8 +84,11 @@ usage() {
|
|||||||
echo "--sysconfdir=/path default: $prefix/etc"
|
echo "--sysconfdir=/path default: $prefix/etc"
|
||||||
echo "--ignore-cve default: no"
|
echo "--ignore-cve default: no"
|
||||||
echo " if set to yes ignores CVE-2015-3887 and makes it possible"
|
echo " if set to yes ignores CVE-2015-3887 and makes it possible"
|
||||||
echo " to preload from current dir (insecure)"
|
echo " to preload from current dir (possibly insecure, but handy)"
|
||||||
echo "--fat-binary : build for both i386 and x86_64 architectures on 64-bit Macs"
|
echo "--fat-binary : build for both i386 and x86_64 architectures on 64-bit Macs"
|
||||||
|
echo "--fat-binary-m1 : build for both arm64e and x86_64 architectures on M1 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"
|
echo "--help : show this text"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -84,7 +101,10 @@ spliteq() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fat_binary=
|
fat_binary=
|
||||||
|
fat_binary_m1=
|
||||||
ignore_cve=no
|
ignore_cve=no
|
||||||
|
hookmethod=auto
|
||||||
|
|
||||||
parsearg() {
|
parsearg() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--prefix=*) prefix=`spliteq $1`;;
|
--prefix=*) prefix=`spliteq $1`;;
|
||||||
@@ -95,7 +115,9 @@ parsearg() {
|
|||||||
--sysconfdir=*) sysconfdir=`spliteq $1`;;
|
--sysconfdir=*) sysconfdir=`spliteq $1`;;
|
||||||
--ignore-cve) ignore_cve=1;;
|
--ignore-cve) ignore_cve=1;;
|
||||||
--ignore-cve=*) ignore_cve=`spliteq $1`;;
|
--ignore-cve=*) ignore_cve=`spliteq $1`;;
|
||||||
|
--hookmethod=*) hookmethod=`spliteq $1`;;
|
||||||
--fat-binary) fat_binary=1;;
|
--fat-binary) fat_binary=1;;
|
||||||
|
--fat-binary-m1) fat_binary_m1=1;;
|
||||||
--help) usage;;
|
--help) usage;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -151,10 +173,28 @@ issolaris() {
|
|||||||
}
|
}
|
||||||
haiku_detected=false
|
haiku_detected=false
|
||||||
ishaiku() {
|
ishaiku() {
|
||||||
$haiku_detected
|
$haiku_detected
|
||||||
}
|
}
|
||||||
|
|
||||||
check_compile 'whether C compiler works' '' 'int main() {return 0;}' || fail 'error: install a C compiler and library'
|
check_compile 'whether C compiler works' '' 'int main() {return 0;}' || fail 'error: install a C compiler and library'
|
||||||
|
check_compile 'whether libc headers are complete' '' '#include <netdb.h>\nint main() {return 0;}' || fail 'error: necessary libc headers are not installed'
|
||||||
|
check_compile 'whether C compiler understands -Wno-unknown-pragmas' '-Wno-unknown-pragmas' 'int main() {return 0;}'
|
||||||
|
|
||||||
|
if ! check_compile 'whether getnameinfo() servlen argument is POSIX compliant (socklen_t)' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=socklen_t -DGN_FLAGS_T=int" \
|
||||||
|
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int);int main() {\nreturn 0;}' ; then
|
||||||
|
# GLIBC < 2.14
|
||||||
|
if ! check_compile 'whether getnameinfo() flags argument is unsigned' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=socklen_t -DGN_FLAGS_T=unsigned" \
|
||||||
|
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, unsigned);int main() {\nreturn 0;}' ; then
|
||||||
|
if ! check_compile 'whether getnameinfo() servlen argument is size_t' "-DGN_NODELEN_T=socklen_t -DGN_SERVLEN_T=size_t -DGN_FLAGS_T=int" \
|
||||||
|
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, size_t, int);int main() {\nreturn 0;}' ; then
|
||||||
|
# OpenBSD & FreeBSD
|
||||||
|
if ! check_compile 'whether getnameinfo() servlen and nodelen argument is size_t' "-DGN_NODELEN_T=size_t -DGN_SERVLEN_T=size_t -DGN_FLAGS_T=int" \
|
||||||
|
'#define _GNU_SOURCE\n#include <netdb.h>\nint getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int);int main() {\nreturn 0;}' ; then
|
||||||
|
fail "failed to detect getnameinfo signature"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
check_compile 'whether we have GNU-style getservbyname_r()' "-DHAVE_GNU_GETSERVBYNAME_R" \
|
check_compile 'whether we have GNU-style getservbyname_r()' "-DHAVE_GNU_GETSERVBYNAME_R" \
|
||||||
'#define _GNU_SOURCE\n#include <netdb.h>\nint main() {\nstruct servent *se = 0;struct servent se_buf;char buf[1024];\ngetservbyname_r("foo", (void*) 0, &se_buf, buf, sizeof(buf), &se);\nreturn 0;}'
|
'#define _GNU_SOURCE\n#include <netdb.h>\nint main() {\nstruct servent *se = 0;struct servent se_buf;char buf[1024];\ngetservbyname_r("foo", (void*) 0, &se_buf, buf, sizeof(buf), &se);\nreturn 0;}'
|
||||||
@@ -165,9 +205,16 @@ check_compile 'whether we have pipe2() and O_CLOEXEC' "-DHAVE_PIPE2" \
|
|||||||
check_compile 'whether we have SOCK_CLOEXEC' "-DHAVE_SOCK_CLOEXEC" \
|
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);}'
|
'#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__ && {
|
check_define __APPLE__ && {
|
||||||
mac_detected=true
|
mac_detected=true
|
||||||
check_define __x86_64__ && mac_64=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 __FreeBSD__ && bsd_detected=true
|
||||||
check_define __OpenBSD__ && {
|
check_define __OpenBSD__ && {
|
||||||
@@ -208,14 +255,39 @@ fi
|
|||||||
echo "$LD_SONAME_FLAG"
|
echo "$LD_SONAME_FLAG"
|
||||||
echo "LD_SET_SONAME = -Wl,$LD_SONAME_FLAG," >> config.mak
|
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
|
make_cmd=make
|
||||||
if ismac ; then
|
if ismac ; then
|
||||||
echo LDSO_SUFFIX=dylib>>config.mak
|
echo LDSO_SUFFIX=dylib>>config.mak
|
||||||
echo MAC_CFLAGS+=-DIS_MAC=1>>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
|
if ismac64 && [ "$fat_binary" = 1 ] ; then
|
||||||
echo "Configuring a fat binary for i386 and x86_64"
|
echo "Configuring a fat binary for i386 and x86_64"
|
||||||
echo MAC_CFLAGS+=-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
|
echo "FAT_LDFLAGS=-arch i386 -arch x86_64">>config.mak
|
||||||
|
echo "FAT_BIN_LDFLAGS=-arch i386 -arch x86_64">>config.mak
|
||||||
|
fi
|
||||||
|
if [ "$fat_binary_m1" = 1 ] ; then
|
||||||
|
echo "Configuring a fat binary for arm64[e] and x86_64"
|
||||||
|
echo "MAC_CFLAGS+=-arch arm64 -arch arm64e -arch x86_64">>config.mak
|
||||||
|
echo "FAT_LDFLAGS=-arch arm64 -arch arm64e -arch x86_64">>config.mak
|
||||||
|
echo "FAT_BIN_LDFLAGS=-arch arm64 -arch x86_64">>config.mak
|
||||||
fi
|
fi
|
||||||
elif isbsd ; then
|
elif isbsd ; then
|
||||||
echo LIBDL=>>config.mak
|
echo LIBDL=>>config.mak
|
||||||
|
|||||||
+34
-33
@@ -462,8 +462,10 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
|
|||||||
error1:
|
error1:
|
||||||
proxychains_write_log(TP " timeout\n");
|
proxychains_write_log(TP " timeout\n");
|
||||||
error:
|
error:
|
||||||
if(*fd != -1)
|
if(*fd != -1) {
|
||||||
close(*fd);
|
close(*fd);
|
||||||
|
*fd = -1;
|
||||||
|
}
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,9 +522,9 @@ static unsigned int calc_alive(proxy_data * pd, unsigned int proxy_count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
|
static int chain_step(int *ns, proxy_data * pfrom, proxy_data * pto) {
|
||||||
int retcode = -1;
|
int retcode = -1;
|
||||||
char *hostname;
|
char *hostname, *errmsg = 0;
|
||||||
char hostname_buf[MSG_LEN_MAX];
|
char hostname_buf[MSG_LEN_MAX];
|
||||||
char ip_buf[INET6_ADDRSTRLEN];
|
char ip_buf[INET6_ADDRSTRLEN];
|
||||||
int v6 = pto->ip.is_v6;
|
int v6 = pto->ip.is_v6;
|
||||||
@@ -536,31 +538,34 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
|
|||||||
usenumericip:
|
usenumericip:
|
||||||
if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) {
|
if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) {
|
||||||
pto->ps = DOWN_STATE;
|
pto->ps = DOWN_STATE;
|
||||||
proxychains_write_log("<--ip conversion error!\n");
|
errmsg = "<--ip conversion error!\n";
|
||||||
close(ns);
|
retcode = SOCKET_ERROR;
|
||||||
return SOCKET_ERROR;
|
goto err;
|
||||||
}
|
}
|
||||||
hostname = ip_buf;
|
hostname = ip_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port));
|
proxychains_write_log(TP " %s:%d ", hostname, htons(pto->port));
|
||||||
retcode = tunnel_to(ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
|
retcode = tunnel_to(*ns, pto->ip, pto->port, pfrom->pt, pfrom->user, pfrom->pass);
|
||||||
switch (retcode) {
|
switch (retcode) {
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
pto->ps = BUSY_STATE;
|
pto->ps = BUSY_STATE;
|
||||||
break;
|
break;
|
||||||
case BLOCKED:
|
case BLOCKED:
|
||||||
pto->ps = BLOCKED_STATE;
|
pto->ps = BLOCKED_STATE;
|
||||||
proxychains_write_log("<--denied\n");
|
errmsg = "<--denied\n";
|
||||||
close(ns);
|
goto err;
|
||||||
break;
|
|
||||||
case SOCKET_ERROR:
|
case SOCKET_ERROR:
|
||||||
pto->ps = DOWN_STATE;
|
pto->ps = DOWN_STATE;
|
||||||
proxychains_write_log("<--socket error or timeout!\n");
|
errmsg = "<--socket error or timeout!\n";
|
||||||
close(ns);
|
goto err;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return retcode;
|
return retcode;
|
||||||
|
err:
|
||||||
|
if(errmsg) proxychains_write_log(errmsg);
|
||||||
|
if(*ns != -1) close(*ns);
|
||||||
|
*ns = -1;
|
||||||
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int connect_proxy_chain(int sock, ip_type target_ip,
|
int connect_proxy_chain(int sock, ip_type target_ip,
|
||||||
@@ -596,7 +601,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
p2 = select_proxy(FIFOLY, pd, proxy_count, &offset);
|
p2 = select_proxy(FIFOLY, pd, proxy_count, &offset);
|
||||||
if(!p2)
|
if(!p2)
|
||||||
break;
|
break;
|
||||||
if(SUCCESS != chain_step(ns, p1, p2)) {
|
if(SUCCESS != chain_step(&ns, p1, p2)) {
|
||||||
PDEBUG("GOTO AGAIN 1\n");
|
PDEBUG("GOTO AGAIN 1\n");
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
@@ -605,7 +610,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
//proxychains_write_log(TP);
|
//proxychains_write_log(TP);
|
||||||
p3->ip = target_ip;
|
p3->ip = target_ip;
|
||||||
p3->port = target_port;
|
p3->port = target_port;
|
||||||
if(SUCCESS != chain_step(ns, p1, p3))
|
if(SUCCESS != chain_step(&ns, p1, p3))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -643,7 +648,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
/* Try from the beginning to where we started */
|
/* Try from the beginning to where we started */
|
||||||
offset = 0;
|
offset = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if(SUCCESS != chain_step(ns, p1, p2)) {
|
} else if(SUCCESS != chain_step(&ns, p1, p2)) {
|
||||||
PDEBUG("GOTO AGAIN 1\n");
|
PDEBUG("GOTO AGAIN 1\n");
|
||||||
goto again;
|
goto again;
|
||||||
} else
|
} else
|
||||||
@@ -655,7 +660,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
p3->port = target_port;
|
p3->port = target_port;
|
||||||
proxychains_proxy_offset = offset+1;
|
proxychains_proxy_offset = offset+1;
|
||||||
PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len);
|
PDEBUG("pd_offset = %d, curr_len = %d\n", proxychains_proxy_offset, curr_len);
|
||||||
if(SUCCESS != chain_step(ns, p1, p3))
|
if(SUCCESS != chain_step(&ns, p1, p3))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -673,7 +678,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
while(offset < proxy_count) {
|
while(offset < proxy_count) {
|
||||||
if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset)))
|
if(!(p2 = select_proxy(FIFOLY, pd, proxy_count, &offset)))
|
||||||
break;
|
break;
|
||||||
if(SUCCESS != chain_step(ns, p1, p2)) {
|
if(SUCCESS != chain_step(&ns, p1, p2)) {
|
||||||
PDEBUG("chain_step failed\n");
|
PDEBUG("chain_step failed\n");
|
||||||
goto error_strict;
|
goto error_strict;
|
||||||
}
|
}
|
||||||
@@ -682,7 +687,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
//proxychains_write_log(TP);
|
//proxychains_write_log(TP);
|
||||||
p3->ip = target_ip;
|
p3->ip = target_ip;
|
||||||
p3->port = target_port;
|
p3->port = target_port;
|
||||||
if(SUCCESS != chain_step(ns, p1, p3))
|
if(SUCCESS != chain_step(&ns, p1, p3))
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -698,7 +703,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
while(++curr_len < max_chain) {
|
while(++curr_len < max_chain) {
|
||||||
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
|
if(!(p2 = select_proxy(RANDOMLY, pd, proxy_count, &offset)))
|
||||||
goto error_more;
|
goto error_more;
|
||||||
if(SUCCESS != chain_step(ns, p1, p2)) {
|
if(SUCCESS != chain_step(&ns, p1, p2)) {
|
||||||
PDEBUG("GOTO AGAIN 2\n");
|
PDEBUG("GOTO AGAIN 2\n");
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
@@ -707,7 +712,7 @@ int connect_proxy_chain(int sock, ip_type target_ip,
|
|||||||
//proxychains_write_log(TP);
|
//proxychains_write_log(TP);
|
||||||
p3->ip = target_ip;
|
p3->ip = target_ip;
|
||||||
p3->port = target_port;
|
p3->port = target_port;
|
||||||
if(SUCCESS != chain_step(ns, p1, p3))
|
if(SUCCESS != chain_step(&ns, p1, p3))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -824,7 +829,8 @@ struct hostent* proxy_gethostbyname_old(const char *name)
|
|||||||
close(pipe_fd[0]);
|
close(pipe_fd[0]);
|
||||||
got_buff:
|
got_buff:
|
||||||
l = strlen(buff);
|
l = strlen(buff);
|
||||||
if(l && buff[l-1] == '\n') buff[l-1] = 0;
|
if (!l) goto err_dns;
|
||||||
|
if (buff[l-1] == '\n') buff[l-1] = 0;
|
||||||
addr = inet_addr(buff);
|
addr = inet_addr(buff);
|
||||||
if (addr == (in_addr_t) (-1))
|
if (addr == (in_addr_t) (-1))
|
||||||
goto err_dns;
|
goto err_dns;
|
||||||
@@ -839,8 +845,7 @@ got_buff:
|
|||||||
name, inet_ntoa(*(struct in_addr*)&addr));
|
name, inet_ntoa(*(struct in_addr*)&addr));
|
||||||
return &hostent_space;
|
return &hostent_space;
|
||||||
err_dns:
|
err_dns:
|
||||||
proxychains_write_log("|DNS-response|: %s does not exist\n", name);
|
proxychains_write_log("|DNS-response|: %s lookup error\n", name);
|
||||||
perror("err_dns");
|
|
||||||
err:
|
err:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -969,12 +974,13 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
|
|||||||
node?node:"",service?service:"",hints?(int)hints->ai_flags:0);
|
node?node:"",service?service:"",hints?(int)hints->ai_flags:0);
|
||||||
|
|
||||||
space = calloc(1, sizeof(struct addrinfo_data));
|
space = calloc(1, sizeof(struct addrinfo_data));
|
||||||
if(!space) goto err1;
|
if(!space) return EAI_MEMORY;
|
||||||
|
|
||||||
if(node && !my_inet_aton(node, space)) {
|
if(node && !my_inet_aton(node, space)) {
|
||||||
/* some folks (nmap) use getaddrinfo() with AI_NUMERICHOST to check whether a string
|
/* some folks (nmap) use getaddrinfo() with AI_NUMERICHOST to check whether a string
|
||||||
containing a numeric ip was passed. we must return failure in that case. */
|
containing a numeric ip was passed. we must return failure in that case. */
|
||||||
if(hints && (hints->ai_flags & AI_NUMERICHOST)) {
|
if(hints && (hints->ai_flags & AI_NUMERICHOST)) {
|
||||||
|
err_nn:
|
||||||
free(space);
|
free(space);
|
||||||
return EAI_NONAME;
|
return EAI_NONAME;
|
||||||
}
|
}
|
||||||
@@ -987,7 +993,7 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
|
|||||||
memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr,
|
memcpy(&((struct sockaddr_in *) &space->sockaddr_space)->sin_addr,
|
||||||
*(hp->h_addr_list), sizeof(in_addr_t));
|
*(hp->h_addr_list), sizeof(in_addr_t));
|
||||||
else
|
else
|
||||||
goto err2;
|
goto err_nn;
|
||||||
} else if(node) {
|
} else if(node) {
|
||||||
af = ((struct sockaddr_in *) &space->sockaddr_space)->sin_family;
|
af = ((struct sockaddr_in *) &space->sockaddr_space)->sin_family;
|
||||||
} else if(!node && !(hints->ai_flags & AI_PASSIVE)) {
|
} else if(!node && !(hints->ai_flags & AI_PASSIVE)) {
|
||||||
@@ -1018,18 +1024,13 @@ int proxy_getaddrinfo(const char *node, const char *service, const struct addrin
|
|||||||
p->ai_socktype = hints->ai_socktype;
|
p->ai_socktype = hints->ai_socktype;
|
||||||
p->ai_flags = hints->ai_flags;
|
p->ai_flags = hints->ai_flags;
|
||||||
p->ai_protocol = hints->ai_protocol;
|
p->ai_protocol = hints->ai_protocol;
|
||||||
|
if(!p->ai_socktype && p->ai_protocol == IPPROTO_TCP)
|
||||||
|
p->ai_socktype = SOCK_STREAM;
|
||||||
} else {
|
} else {
|
||||||
#ifndef AI_V4MAPPED
|
#ifndef AI_V4MAPPED
|
||||||
#define AI_V4MAPPED 0
|
#define AI_V4MAPPED 0
|
||||||
#endif
|
#endif
|
||||||
p->ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
|
p->ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto out;
|
|
||||||
err2:
|
|
||||||
free(space);
|
|
||||||
err1:
|
|
||||||
return 1;
|
|
||||||
out:
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-2
@@ -65,8 +65,18 @@ typedef enum {
|
|||||||
} select_type;
|
} select_type;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct in_addr in_addr, netmask;
|
sa_family_t family;
|
||||||
unsigned short port;
|
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;
|
} localaddr_arg;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -90,6 +100,7 @@ int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port
|
|||||||
void proxychains_write_log(char *str, ...);
|
void proxychains_write_log(char *str, ...);
|
||||||
|
|
||||||
typedef int (*close_t)(int);
|
typedef int (*close_t)(int);
|
||||||
|
typedef int (*close_range_t)(unsigned, unsigned, int);
|
||||||
typedef int (*connect_t)(int, const struct sockaddr *, socklen_t);
|
typedef int (*connect_t)(int, const struct sockaddr *, socklen_t);
|
||||||
typedef struct hostent* (*gethostbyname_t)(const char *);
|
typedef struct hostent* (*gethostbyname_t)(const char *);
|
||||||
typedef int (*freeaddrinfo_t)(struct addrinfo *);
|
typedef int (*freeaddrinfo_t)(struct addrinfo *);
|
||||||
@@ -99,7 +110,7 @@ typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *
|
|||||||
struct addrinfo **);
|
struct addrinfo **);
|
||||||
|
|
||||||
typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *,
|
typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *,
|
||||||
socklen_t, char *, socklen_t, int);
|
GN_NODELEN_T, char *, GN_SERVLEN_T, GN_FLAGS_T);
|
||||||
|
|
||||||
typedef ssize_t (*sendto_t) (int sockfd, const void *buf, size_t len, int flags,
|
typedef ssize_t (*sendto_t) (int sockfd, const void *buf, size_t len, int flags,
|
||||||
const struct sockaddr *dest_addr, socklen_t addrlen);
|
const struct sockaddr *dest_addr, socklen_t addrlen);
|
||||||
|
|||||||
+247
-77
@@ -22,6 +22,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -55,6 +56,7 @@ connect_t true___xnet_connect;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
close_t true_close;
|
close_t true_close;
|
||||||
|
close_range_t true_close_range;
|
||||||
connect_t true_connect;
|
connect_t true_connect;
|
||||||
gethostbyname_t true_gethostbyname;
|
gethostbyname_t true_gethostbyname;
|
||||||
getaddrinfo_t true_getaddrinfo;
|
getaddrinfo_t true_getaddrinfo;
|
||||||
@@ -85,13 +87,14 @@ static int init_l = 0;
|
|||||||
|
|
||||||
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
|
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
|
||||||
|
|
||||||
static void* load_sym(char* symname, void* proxyfunc) {
|
static void* load_sym(char* symname, void* proxyfunc, int is_mandatory) {
|
||||||
|
|
||||||
void *funcptr = dlsym(RTLD_NEXT, symname);
|
void *funcptr = dlsym(RTLD_NEXT, symname);
|
||||||
|
|
||||||
if(!funcptr) {
|
if(is_mandatory && !funcptr) {
|
||||||
fprintf(stderr, "Cannot load symbol '%s' %s\n", symname, dlerror());
|
fprintf(stderr, "Cannot load symbol '%s' %s\n", symname, dlerror());
|
||||||
exit(1);
|
exit(1);
|
||||||
|
} else if (!funcptr) {
|
||||||
|
return funcptr;
|
||||||
} else {
|
} else {
|
||||||
PDEBUG("loaded symbol '%s'" " real addr %p wrapped addr %p\n", symname, funcptr, proxyfunc);
|
PDEBUG("loaded symbol '%s'" " real addr %p wrapped addr %p\n", symname, funcptr, proxyfunc);
|
||||||
}
|
}
|
||||||
@@ -102,44 +105,56 @@ static void* load_sym(char* symname, void* proxyfunc) {
|
|||||||
return funcptr;
|
return funcptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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"
|
#include "allocator_thread.h"
|
||||||
|
|
||||||
const char *proxychains_get_version(void);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int first, last, flags;
|
||||||
|
} close_range_args_t;
|
||||||
|
|
||||||
|
/* If there is some `close` or `close_range` system call before do_init,
|
||||||
|
we buffer it, and actually execute them in do_init. */
|
||||||
static int close_fds[16];
|
static int close_fds[16];
|
||||||
static int close_fds_cnt = 0;
|
static int close_fds_cnt = 0;
|
||||||
|
static close_range_args_t close_range_buffer[16];
|
||||||
|
static int close_range_buffer_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) {
|
static void do_init(void) {
|
||||||
srand(time(NULL));
|
char *env;
|
||||||
|
|
||||||
|
srand(get_rand_seed());
|
||||||
core_initialize();
|
core_initialize();
|
||||||
|
|
||||||
/* read the config file */
|
env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR);
|
||||||
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
|
if(env && *env == '1')
|
||||||
DUMP_PROXY_CHAIN(proxychains_pd, proxychains_proxy_count);
|
proxychains_quiet_mode = 1;
|
||||||
|
|
||||||
proxychains_write_log(LOG_PREFIX "DLL init: proxychains-ng %s\n", proxychains_get_version());
|
proxychains_write_log(LOG_PREFIX "DLL init: proxychains-ng %s\n", proxychains_get_version());
|
||||||
|
|
||||||
setup_hooks();
|
setup_hooks();
|
||||||
|
|
||||||
|
/* read the config file */
|
||||||
|
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
|
||||||
|
DUMP_PROXY_CHAIN(proxychains_pd, proxychains_proxy_count);
|
||||||
|
|
||||||
while(close_fds_cnt) true_close(close_fds[--close_fds_cnt]);
|
while(close_fds_cnt) true_close(close_fds[--close_fds_cnt]);
|
||||||
|
while(close_range_buffer_cnt) {
|
||||||
|
int i = --close_range_buffer_cnt;
|
||||||
|
true_close_range(close_range_buffer[i].first, close_range_buffer[i].last, close_range_buffer[i].flags);
|
||||||
|
}
|
||||||
init_l = 1;
|
init_l = 1;
|
||||||
|
|
||||||
rdns_init(proxychains_resolver);
|
rdns_init(proxychains_resolver);
|
||||||
@@ -153,16 +168,19 @@ static void init_lib_wrapper(const char* caller) {
|
|||||||
pthread_once(&init_once, do_init);
|
pthread_once(&init_once, do_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we use gcc >= 3, we can instruct the dynamic loader
|
/* if we use gcc >= 3, we can instruct the dynamic loader
|
||||||
* to call init_lib at link time. otherwise it gets loaded
|
* to call init_lib at link time. otherwise it gets loaded
|
||||||
* lazily, which has the disadvantage that there's a potential
|
* lazily, which has the disadvantage that there's a potential
|
||||||
* race condition if 2 threads call it before init_l is set
|
* race condition if 2 threads call it before init_l is set
|
||||||
* and PTHREAD support was disabled */
|
* and PTHREAD support was disabled */
|
||||||
#if __GNUC__ > 2
|
#if __GNUC__+0 > 2
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void gcc_init(void) {
|
static void gcc_init(void) {
|
||||||
INIT();
|
init_lib_wrapper(__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
#define INIT() do {} while(0)
|
||||||
|
#else
|
||||||
|
#define INIT() init_lib_wrapper(__FUNCTION__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -272,8 +290,7 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
|
|||||||
int count = 0, port_n = 0, list = 0;
|
int count = 0, port_n = 0, list = 0;
|
||||||
char buf[1024], type[1024], host[1024], user[1024];
|
char buf[1024], type[1024], host[1024], user[1024];
|
||||||
char *buff, *env, *p;
|
char *buff, *env, *p;
|
||||||
char local_in_addr_port[32];
|
char local_addr_port[64], local_addr[64], local_netmask[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_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 dnat_orig_addr[32], dnat_orig_port[32], dnat_new_addr[32], dnat_new_port[32];
|
||||||
char rdnsd_addr[32], rdnsd_port[8];
|
char rdnsd_addr[32], rdnsd_port[8];
|
||||||
@@ -296,10 +313,6 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
env = getenv(PROXYCHAINS_QUIET_MODE_ENV_VAR);
|
|
||||||
if(env && *env == '1')
|
|
||||||
proxychains_quiet_mode = 1;
|
|
||||||
|
|
||||||
while(fgets(buf, sizeof(buf), file)) {
|
while(fgets(buf, sizeof(buf), file)) {
|
||||||
buff = buf;
|
buff = buf;
|
||||||
/* remove leading whitespace */
|
/* remove leading whitespace */
|
||||||
@@ -338,7 +351,7 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
|
|||||||
if(*ct == STRICT_TYPE && proxychains_resolver >= DNSLF_RDNS_START && count > 0) {
|
if(*ct == STRICT_TYPE && proxychains_resolver >= DNSLF_RDNS_START && count > 0) {
|
||||||
/* we can allow dns hostnames for all but the first proxy in the list if chaintype is strict, as remote lookup can be done */
|
/* we can allow dns hostnames for all but the first proxy in the list if chaintype is strict, as remote lookup can be done */
|
||||||
rdns_init(proxychains_resolver);
|
rdns_init(proxychains_resolver);
|
||||||
ip_type4 internal_ip = at_get_ip_for_host(host, strlen(host));
|
ip_type4 internal_ip = rdns_get_ip_for_host(host, strlen(host));
|
||||||
pd[count].ip.is_v6 = 0;
|
pd[count].ip.is_v6 = 0;
|
||||||
host_ip->addr.v4 = internal_ip;
|
host_ip->addr.v4 = internal_ip;
|
||||||
if(internal_ip.as_int == IPT4_INVALID.as_int)
|
if(internal_ip.as_int == IPT4_INVALID.as_int)
|
||||||
@@ -388,42 +401,76 @@ inv_host:
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else if(STR_STARTSWITH(buff, "localnet")) {
|
} else if(STR_STARTSWITH(buff, "localnet")) {
|
||||||
if(sscanf(buff, "%s %21[^/]/%15s", user, local_in_addr_port, local_netmask) < 3) {
|
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) {
|
||||||
fprintf(stderr, "localnet format error");
|
fprintf(stderr, "localnet format error");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* clean previously used buffer */
|
p = strchr(local_addr_port, ':');
|
||||||
memset(local_in_port, 0, sizeof(local_in_port) / sizeof(local_in_port[0]));
|
if(!p || p == strrchr(local_addr_port, ':')) {
|
||||||
|
local_family = AF_INET;
|
||||||
if(sscanf(local_in_addr_port, "%15[^:]:%5s", local_in_addr, local_in_port) < 2) {
|
n = sscanf(local_addr_port, "%15[^:]%c%5hu%c", local_addr, &colon, &local_port, &extra);
|
||||||
PDEBUG("added localnet: netaddr=%s, netmask=%s\n",
|
valid = n == 1 || (n == 3 && colon == ':');
|
||||||
local_in_addr, local_netmask);
|
} 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 {
|
} else {
|
||||||
PDEBUG("added localnet: netaddr=%s, port=%s, netmask=%s\n",
|
local_family = AF_INET6;
|
||||||
local_in_addr, local_in_port, local_netmask);
|
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 {
|
||||||
|
PDEBUG("added localnet: netaddr=%s, netmask=%s\n",
|
||||||
|
local_addr, local_netmask);
|
||||||
}
|
}
|
||||||
if(num_localnet_addr < MAX_LOCALNET) {
|
if(num_localnet_addr < MAX_LOCALNET) {
|
||||||
int error;
|
localnet_addr[num_localnet_addr].family = local_family;
|
||||||
error =
|
localnet_addr[num_localnet_addr].port = local_port;
|
||||||
inet_pton(AF_INET, local_in_addr,
|
valid = 0;
|
||||||
&localnet_addr[num_localnet_addr].in_addr);
|
if (local_family == AF_INET) {
|
||||||
if(error <= 0) {
|
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) {
|
||||||
fprintf(stderr, "localnet address error\n");
|
fprintf(stderr, "localnet address error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
error =
|
if(local_family == AF_INET && strchr(local_netmask, '.')) {
|
||||||
inet_pton(AF_INET, local_netmask,
|
valid =
|
||||||
&localnet_addr[num_localnet_addr].netmask);
|
inet_pton(local_family, local_netmask,
|
||||||
if(error <= 0) {
|
&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) {
|
||||||
fprintf(stderr, "localnet netmask error\n");
|
fprintf(stderr, "localnet netmask error\n");
|
||||||
exit(1);
|
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;
|
++num_localnet_addr;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
|
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
|
||||||
@@ -527,7 +574,14 @@ inv_host:
|
|||||||
|
|
||||||
/******* HOOK FUNCTIONS *******/
|
/******* HOOK FUNCTIONS *******/
|
||||||
|
|
||||||
int close(int fd) {
|
#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) {
|
||||||
if(!init_l) {
|
if(!init_l) {
|
||||||
if(close_fds_cnt>=(sizeof close_fds/sizeof close_fds[0])) goto err;
|
if(close_fds_cnt>=(sizeof close_fds/sizeof close_fds[0])) goto err;
|
||||||
close_fds[close_fds_cnt++] = fd;
|
close_fds[close_fds_cnt++] = fd;
|
||||||
@@ -548,7 +602,71 @@ int close(int fd) {
|
|||||||
static int is_v4inv6(const struct in6_addr *a) {
|
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);
|
return !memcmp(a->s6_addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
|
||||||
}
|
}
|
||||||
int connect(int sock, const struct sockaddr *addr, unsigned int len) {
|
|
||||||
|
static void intsort(int *a, int n) {
|
||||||
|
int i, j, s;
|
||||||
|
for(i=0; i<n; ++i)
|
||||||
|
for(j=i+1; j<n; ++j)
|
||||||
|
if(a[j] < a[i]) {
|
||||||
|
s = a[i];
|
||||||
|
a[i] = a[j];
|
||||||
|
a[j] = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Warning: Linux manual says the third arg is `unsigned int`, but unistd.h says `int`. */
|
||||||
|
HOOKFUNC(int, close_range, unsigned first, unsigned last, int flags) {
|
||||||
|
if(true_close_range == NULL) {
|
||||||
|
fprintf(stderr, "Calling close_range, but this platform does not provide this system call. ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!init_l) {
|
||||||
|
/* push back to cache, and delay the execution. */
|
||||||
|
if(close_range_buffer_cnt >= (sizeof close_range_buffer / sizeof close_range_buffer[0])) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int i = close_range_buffer_cnt++;
|
||||||
|
close_range_buffer[i].first = first;
|
||||||
|
close_range_buffer[i].last = last;
|
||||||
|
close_range_buffer[i].flags = flags;
|
||||||
|
return errno = 0;
|
||||||
|
}
|
||||||
|
if(proxychains_resolver != DNSLF_RDNS_THREAD) return true_close_range(first, last, flags);
|
||||||
|
|
||||||
|
/* prevent rude programs (like ssh) from closing our pipes */
|
||||||
|
int res = 0, uerrno = 0, i;
|
||||||
|
int protected_fds[] = {req_pipefd[0], req_pipefd[1], resp_pipefd[0], resp_pipefd[1]};
|
||||||
|
intsort(protected_fds, 4);
|
||||||
|
/* We are skipping protected_fds while calling true_close_range()
|
||||||
|
* If protected_fds cut the range into some sub-ranges, we close sub-ranges BEFORE cut point in the loop.
|
||||||
|
* [first, cut1-1] , [cut1+1, cut2-1] , [cut2+1, cut3-1]
|
||||||
|
* Finally, we delete the remaining sub-range, outside the loop. [cut3+1, tail]
|
||||||
|
*/
|
||||||
|
int next_fd_to_close = first;
|
||||||
|
for(i = 0; i < 4; ++i) {
|
||||||
|
if(protected_fds[i] < first || protected_fds[i] > last)
|
||||||
|
continue;
|
||||||
|
int prev = (i == 0 || protected_fds[i-1] < first) ? first : protected_fds[i-1]+1;
|
||||||
|
if(prev != protected_fds[i]) {
|
||||||
|
if(-1 == true_close_range(prev, protected_fds[i]-1, flags)) {
|
||||||
|
res = -1;
|
||||||
|
uerrno = errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next_fd_to_close = protected_fds[i]+1;
|
||||||
|
}
|
||||||
|
if(next_fd_to_close <= last) {
|
||||||
|
if(-1 == true_close_range(next_fd_to_close, last, flags)) {
|
||||||
|
res = -1;
|
||||||
|
uerrno = errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errno = uerrno;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len) {
|
||||||
INIT();
|
INIT();
|
||||||
PFUNC();
|
PFUNC();
|
||||||
|
|
||||||
@@ -611,14 +729,24 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
|
|||||||
port = dnat->new_port;
|
port = dnat->new_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!v6) for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) {
|
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)
|
if (localnet_addr[i].port && localnet_addr[i].port != port)
|
||||||
== (p_addr_in->s_addr & localnet_addr[i].netmask.s_addr)) {
|
continue;
|
||||||
if(!localnet_addr[i].port || localnet_addr[i].port == port) {
|
if (localnet_addr[i].family != (v6 ? AF_INET6 : AF_INET))
|
||||||
PDEBUG("accessing localnet using true_connect\n");
|
continue;
|
||||||
return true_connect(sock, addr, len);
|
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;
|
||||||
}
|
}
|
||||||
|
PDEBUG("accessing localnet using true_connect\n");
|
||||||
|
return true_connect(sock, addr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = fcntl(sock, F_GETFL, 0);
|
flags = fcntl(sock, F_GETFL, 0);
|
||||||
@@ -639,13 +767,13 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IS_SOLARIS
|
#ifdef IS_SOLARIS
|
||||||
int __xnet_connect(int sock, const struct sockaddr *addr, unsigned int len) {
|
HOOKFUNC(int, __xnet_connect, int sock, const struct sockaddr *addr, unsigned int len)
|
||||||
return connect(sock, addr, len);
|
return connect(sock, addr, len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct gethostbyname_data ghbndata;
|
static struct gethostbyname_data ghbndata;
|
||||||
struct hostent *gethostbyname(const char *name) {
|
HOOKFUNC(struct hostent*, gethostbyname, const char *name) {
|
||||||
INIT();
|
INIT();
|
||||||
PDEBUG("gethostbyname: %s\n", name);
|
PDEBUG("gethostbyname: %s\n", name);
|
||||||
|
|
||||||
@@ -659,7 +787,7 @@ struct hostent *gethostbyname(const char *name) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
HOOKFUNC(int, getaddrinfo, const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||||
INIT();
|
INIT();
|
||||||
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
|
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
|
||||||
|
|
||||||
@@ -669,7 +797,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
|
|||||||
return true_getaddrinfo(node, service, hints, res);
|
return true_getaddrinfo(node, service, hints, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeaddrinfo(struct addrinfo *res) {
|
HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
|
||||||
INIT();
|
INIT();
|
||||||
PDEBUG("freeaddrinfo %p \n", (void *) res);
|
PDEBUG("freeaddrinfo %p \n", (void *) res);
|
||||||
|
|
||||||
@@ -679,9 +807,9 @@ void freeaddrinfo(struct addrinfo *res) {
|
|||||||
proxy_freeaddrinfo(res);
|
proxy_freeaddrinfo(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pc_getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
HOOKFUNC(int, getnameinfo, const struct sockaddr *sa, socklen_t salen,
|
||||||
char *host, socklen_t hostlen, char *serv,
|
char *host, GN_NODELEN_T hostlen, char *serv,
|
||||||
socklen_t servlen, int flags)
|
GN_SERVLEN_T servlen, GN_FLAGS_T flags)
|
||||||
{
|
{
|
||||||
INIT();
|
INIT();
|
||||||
PFUNC();
|
PFUNC();
|
||||||
@@ -723,7 +851,7 @@ int pc_getnameinfo(const struct sockaddr *sa, socklen_t salen,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
HOOKFUNC(struct hostent*, gethostbyaddr, const void *addr, socklen_t len, int type) {
|
||||||
INIT();
|
INIT();
|
||||||
PDEBUG("TODO: proper gethostbyaddr hook\n");
|
PDEBUG("TODO: proper gethostbyaddr hook\n");
|
||||||
|
|
||||||
@@ -759,7 +887,7 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
|
|||||||
# define MSG_FASTOPEN 0x20000000
|
# define MSG_FASTOPEN 0x20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
||||||
const struct sockaddr *dest_addr, socklen_t addrlen) {
|
const struct sockaddr *dest_addr, socklen_t addrlen) {
|
||||||
INIT();
|
INIT();
|
||||||
PFUNC();
|
PFUNC();
|
||||||
@@ -773,3 +901,45 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||||||
}
|
}
|
||||||
return true_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
|
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)
|
||||||
|
#define SETUP_SYM_OPTIONAL(X)
|
||||||
|
#else
|
||||||
|
#define SETUP_SYM_IMPL(X, IS_MANDATORY) do { if (! true_ ## X ) true_ ## X = load_sym( # X, X, IS_MANDATORY ); } while(0)
|
||||||
|
#define SETUP_SYM(X) SETUP_SYM_IMPL(X, 1)
|
||||||
|
#define SETUP_SYM_OPTIONAL(X) SETUP_SYM_IMPL(X, 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);
|
||||||
|
SETUP_SYM_OPTIONAL(close_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
|||||||
+11
-6
@@ -135,16 +135,20 @@ int main(int argc, char *argv[]) {
|
|||||||
if(!quiet)
|
if(!quiet)
|
||||||
fprintf(stderr, LOG_PREFIX "preloading %s/%s\n", prefix, dll_name);
|
fprintf(stderr, LOG_PREFIX "preloading %s/%s\n", prefix, dll_name);
|
||||||
|
|
||||||
|
#if defined(IS_MAC) || defined(IS_OPENBSD)
|
||||||
|
#define LD_PRELOAD_SEP ":"
|
||||||
|
#else
|
||||||
|
/* Dynlinkers for Linux and most BSDs seem to support space
|
||||||
|
as LD_PRELOAD separator, with colon added only recently.
|
||||||
|
We use the old syntax for maximum compat */
|
||||||
|
#define LD_PRELOAD_SEP " "
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef IS_MAC
|
#ifdef IS_MAC
|
||||||
putenv("DYLD_FORCE_FLAT_NAMESPACE=1");
|
putenv("DYLD_FORCE_FLAT_NAMESPACE=1");
|
||||||
#define LD_PRELOAD_ENV "DYLD_INSERT_LIBRARIES"
|
#define LD_PRELOAD_ENV "DYLD_INSERT_LIBRARIES"
|
||||||
#define LD_PRELOAD_SEP ":"
|
|
||||||
#else
|
#else
|
||||||
#define LD_PRELOAD_ENV "LD_PRELOAD"
|
#define LD_PRELOAD_ENV "LD_PRELOAD"
|
||||||
/* all historic implementations of BSD and linux dynlinkers seem to support
|
|
||||||
space as LD_PRELOAD separator, with colon added only recently.
|
|
||||||
we use the old syntax for maximum compat */
|
|
||||||
#define LD_PRELOAD_SEP " "
|
|
||||||
#endif
|
#endif
|
||||||
char *old_val = getenv(LD_PRELOAD_ENV);
|
char *old_val = getenv(LD_PRELOAD_ENV);
|
||||||
snprintf(buf, sizeof(buf), LD_PRELOAD_ENV "=%s/%s%s%s",
|
snprintf(buf, sizeof(buf), LD_PRELOAD_ENV "=%s/%s%s%s",
|
||||||
@@ -154,7 +158,8 @@ int main(int argc, char *argv[]) {
|
|||||||
old_val ? old_val : "");
|
old_val ? old_val : "");
|
||||||
putenv(buf);
|
putenv(buf);
|
||||||
execvp(argv[start_argv], &argv[start_argv]);
|
execvp(argv[start_argv], &argv[start_argv]);
|
||||||
perror("proxychains can't load process....");
|
fprintf(stderr, "proxychains: can't load process '%s'.", argv[start_argv]);
|
||||||
|
perror(" (hint: it's probably a typo)");
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -53,9 +53,9 @@ strict_chain
|
|||||||
|
|
||||||
# method 1. this uses the proxychains4 style method to do remote dns:
|
# 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
|
# a thread is spawned that serves DNS requests and hands down an ip
|
||||||
# assigned from an internal list (via remote_dns_subset).
|
# assigned from an internal list (via remote_dns_subnet).
|
||||||
# this is the easiest (setup-wise) and fastest method, however on
|
# this is the easiest (setup-wise) and fastest method, however on
|
||||||
# systems with buggy libcs and very complex software like webbrosers
|
# systems with buggy libcs and very complex software like webbrowsers
|
||||||
# this might not work and/or cause crashes.
|
# this might not work and/or cause crashes.
|
||||||
proxy_dns
|
proxy_dns
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ tcp_connect_time_out 8000
|
|||||||
|
|
||||||
### Examples for localnet exclusion
|
### Examples for localnet exclusion
|
||||||
## localnet ranges will *not* use a proxy to connect.
|
## localnet ranges will *not* use a proxy to connect.
|
||||||
## note that localnet works only when plain IPv4 addresses are passed to the app,
|
## note that localnet works only when plain IP addresses are passed to the app,
|
||||||
## the hostname resolves via /etc/hosts, or proxy_dns is disabled or proxy_dns_old used.
|
## 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
|
## Exclude connections to 192.168.1.0/24 with port 80
|
||||||
@@ -105,12 +105,14 @@ tcp_connect_time_out 8000
|
|||||||
|
|
||||||
## Exclude connections to ANYwhere with port 80
|
## Exclude connections to ANYwhere with port 80
|
||||||
# localnet 0.0.0.0:80/0.0.0.0
|
# localnet 0.0.0.0:80/0.0.0.0
|
||||||
|
# localnet [::]:80/0
|
||||||
|
|
||||||
## RFC5735 Loopback address range
|
## RFC6890 Loopback address range
|
||||||
## if you enable this, you have to make sure remote_dns_subnet is not 127
|
## 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
|
## you'll need to enable it if you want to use an application that
|
||||||
## connects to localhost.
|
## connects to localhost.
|
||||||
# localnet 127.0.0.0/255.0.0.0
|
# localnet 127.0.0.0/255.0.0.0
|
||||||
|
# localnet ::1/128
|
||||||
|
|
||||||
## RFC1918 Private Address Ranges
|
## RFC1918 Private Address Ranges
|
||||||
# localnet 10.0.0.0/255.0.0.0
|
# localnet 10.0.0.0/255.0.0.0
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef NI_MAXHOST
|
#ifndef NI_MAXHOST
|
||||||
#define NI_MAXHOST 1025
|
#define NI_MAXHOST 1025
|
||||||
@@ -43,9 +45,42 @@ static int doit(const char* host, const char* service) {
|
|||||||
return EXIT_SUCCESS;
|
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 main(void) {
|
||||||
int ret;
|
int ret;
|
||||||
ret = doit("www.example.com", NULL);
|
ret = doit("www.example.com", NULL);
|
||||||
ret = doit("www.example.com", "80");
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,5 +123,17 @@ int main() {
|
|||||||
|
|
||||||
ASSERT(ret == 0);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user