Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remotenet #573

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#ifndef __CORE_HEADER
#define __CORE_HEADER
#define MAX_LOCALNET 64
#define MAX_REMOTENET 64
#define MAX_DNAT 64

#include "ip_type.h"
Expand Down Expand Up @@ -77,7 +78,7 @@ typedef struct {
unsigned char in6_prefix;
};
};
} localaddr_arg;
} addr_arg;

typedef struct {
struct in_addr orig_dst, new_dst;
Expand Down Expand Up @@ -106,10 +107,10 @@ typedef struct hostent* (*gethostbyname_t)(const char *);
typedef void (*freeaddrinfo_t)(struct addrinfo *);
typedef struct hostent *(*gethostbyaddr_t) (const void *, socklen_t, int);

typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *,
typedef int (*getaddrinfo_t)(const char *, const char *, const struct addrinfo *,
struct addrinfo **);

typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *,
typedef int (*getnameinfo_t) (const struct sockaddr *, socklen_t, char *,
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,
Expand All @@ -134,7 +135,7 @@ struct gethostbyname_data {
struct hostent* proxy_gethostbyname(const char *name, struct gethostbyname_data *data);
struct hostent* proxy_gethostbyname_old(const char *name);

int proxy_getaddrinfo(const char *node, const char *service,
int proxy_getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res);
void proxy_freeaddrinfo(struct addrinfo *res);

Expand Down
109 changes: 106 additions & 3 deletions src/libproxychains.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ int proxychains_got_chain_data = 0;
unsigned int proxychains_max_chain = 1;
int proxychains_quiet_mode = 0;
enum dns_lookup_flavor proxychains_resolver = DNSLF_LIBC;
localaddr_arg localnet_addr[MAX_LOCALNET];
addr_arg localnet_addr[MAX_LOCALNET];
addr_arg remotenet_addr[MAX_REMOTENET];
size_t num_localnet_addr = 0;
size_t num_remotenet_addr = 0;
dnat_arg dnats[MAX_DNAT];
size_t num_dnats = 0;
unsigned int remote_dns_subnet = 224;
Expand Down Expand Up @@ -115,7 +117,7 @@ typedef struct {
unsigned int first, last, flags;
} close_range_args_t;

/* If there is some `close` or `close_range` system call before do_init,
/* 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_cnt = 0;
Expand Down Expand Up @@ -291,6 +293,7 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
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 remote_addr_port[64], remote_addr[64], remote_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];
Expand Down Expand Up @@ -475,6 +478,81 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
} else {
fprintf(stderr, "# of localnet exceed %d.\n", MAX_LOCALNET);
}
} else if(STR_STARTSWITH(buff, "remotenet")) {
char colon, extra, right_bracket[2];
unsigned short remote_port = 0, remote_prefix;
int remote_family, n, valid;
if(sscanf(buff, "%s %53[^/]/%15s%c", user, remote_addr_port, remote_netmask, &extra) != 3) {
fprintf(stderr, "remotenet format error");
exit(1);
}
p = strchr(remote_addr_port, ':');
if(!p || p == strrchr(remote_addr_port, ':')) {
remote_family = AF_INET;
n = sscanf(remote_addr_port, "%15[^:]%c%5hu%c", remote_addr, &colon, &remote_port, &extra);
valid = n == 1 || (n == 3 && colon == ':');
} else if(remote_addr_port[0] == '[') {
remote_family = AF_INET6;
n = sscanf(remote_addr_port, "[%45[^][]%1[]]%c%5hu%c", remote_addr, right_bracket, &colon, &remote_port, &extra);
valid = n == 2 || (n == 4 && colon == ':');
} else {
remote_family = AF_INET6;
valid = sscanf(remote_addr_port, "%45[^][]%c", remote_addr, &extra) == 1;
}
if(!valid) {
fprintf(stderr, "remotenet address or port error\n");
exit(1);
}
if(remote_port) {
PDEBUG("added remotenet: netaddr=%s, port=%u, netmask=%s\n",
remote_addr, remote_port, remote_netmask);
} else {
PDEBUG("added remotenet: netaddr=%s, netmask=%s\n",
remote_addr, remote_netmask);
}
if(num_remotenet_addr < MAX_REMOTENET) {
remotenet_addr[num_remotenet_addr].family = remote_family;
remotenet_addr[num_remotenet_addr].port = remote_port;
valid = 0;
if (remote_family == AF_INET) {
valid =
inet_pton(remote_family, remote_addr,
&remotenet_addr[num_remotenet_addr].in_addr) > 0;
} else if(remote_family == AF_INET6) {
valid =
inet_pton(remote_family, remote_addr,
&remotenet_addr[num_remotenet_addr].in6_addr) > 0;
}
if(!valid) {
fprintf(stderr, "remotenet address error\n");
exit(1);
}
if(remote_family == AF_INET && strchr(remote_netmask, '.')) {
valid =
inet_pton(remote_family, remote_netmask,
&remotenet_addr[num_remotenet_addr].in_mask) > 0;
} else {
valid = sscanf(remote_netmask, "%hu%c", &remote_prefix, &extra) == 1;
if (valid) {
if(remote_family == AF_INET && remote_prefix <= 32) {
remotenet_addr[num_remotenet_addr].in_mask.s_addr =
htonl(0xFFFFFFFFu << (32u - remote_prefix));
} else if(remote_family == AF_INET6 && remote_prefix <= 128) {
remotenet_addr[num_remotenet_addr].in6_prefix =
remote_prefix;
} else {
valid = 0;
}
}
}
if(!valid) {
fprintf(stderr, "remotenet netmask error\n");
exit(1);
}
++num_remotenet_addr;
} else {
fprintf(stderr, "# of remotenet exceed %d.\n", MAX_REMOTENET);
}
} else if(STR_STARTSWITH(buff, "chain_len")) {
char *pc;
int len;
Expand Down Expand Up @@ -639,7 +717,7 @@ HOOKFUNC(int, close_range, unsigned first, unsigned last, int flags) {
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.
* 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]
*/
Expand Down Expand Up @@ -749,6 +827,31 @@ HOOKFUNC(int, connect, int sock, const struct sockaddr *addr, unsigned int len)
return true_connect(sock, addr, len);
}

int remote_connect = (remote_dns_connect||num_remotenet_addr==0);
for(i = 0; i < num_remotenet_addr && !remote_connect; i++) {
if (remotenet_addr[i].port && remotenet_addr[i].port != port)
continue;
if (remotenet_addr[i].family != (v6 ? AF_INET6 : AF_INET))
continue;
if (v6) {
size_t prefix_bytes = remotenet_addr[i].in6_prefix / CHAR_BIT;
size_t prefix_bits = remotenet_addr[i].in6_prefix % CHAR_BIT;
if (prefix_bytes && memcmp(p_addr_in6->s6_addr, remotenet_addr[i].in6_addr.s6_addr, prefix_bytes) != 0)
continue;
if (prefix_bits && (p_addr_in6->s6_addr[prefix_bytes] ^ remotenet_addr[i].in6_addr.s6_addr[prefix_bytes]) >> (CHAR_BIT - prefix_bits))
continue;
} else {
if((p_addr_in->s_addr ^ remotenet_addr[i].in_addr.s_addr) & remotenet_addr[i].in_mask.s_addr)
continue;
}
remote_connect = 1;
}

if( !remote_connect ) {
PDEBUG("accessing non-remotenet using true_connect\n");
return true_connect(sock, addr, len);
}

flags = fcntl(sock, F_GETFL, 0);
if(flags & O_NONBLOCK)
fcntl(sock, F_SETFL, !O_NONBLOCK);
Expand Down
26 changes: 20 additions & 6 deletions src/proxychains.conf
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ proxy_dns
# we use the reserved 224.x.x.x range by default,
# if the proxified app does a DNS request, we will return an IP from that range.
# on further accesses to this ip we will send the saved DNS name to the proxy.
# in case some control-freak app checks the returned ip, and denies to
# in case some control-freak app checks the returned ip, and denies to
# connect, you can use another subnet, e.g. 10.x.x.x or 127.x.x.x.
# of course you should make sure that the proxified app does not need
# *real* access to this subnet.
# *real* access to this subnet.
# i.e. dont use the same subnet then in the localnet section
#remote_dns_subnet 127
#remote_dns_subnet 127
#remote_dns_subnet 10
remote_dns_subnet 224

Expand All @@ -109,7 +109,7 @@ tcp_connect_time_out 8000

## RFC6890 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
## 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
Expand All @@ -119,6 +119,20 @@ tcp_connect_time_out 8000
# localnet 172.16.0.0/255.240.0.0
# localnet 192.168.0.0/255.255.0.0

### Examples for remotenet that will use a proxy to connect
## only remotenet ranges except localnet ranges will use a proxy to connect.
## default(means all connections except localnet ranges will use a proxy):
## remotenet ::/0
## remotenet 0.0.0.0/0.0.0.0

## Connections to 31.13.94.36 with port 80 and 443 will use a proxy:
# remotenet 31.13.94.36:80/255.255.255.255
# remotenet 31.13.94.36:443/255.255.255.255

## Connections to anywhere with port 25 will use a proxy:
# remotenet 0.0.0.0:25/0.0.0.0
# remotenet [::]:25/0

### Examples for dnat
## Trying to proxy connections to destinations which are dnatted,
## will result in proxying connections to the new given destinations.
Expand Down Expand Up @@ -147,8 +161,8 @@ tcp_connect_time_out 8000
# socks5 192.168.67.78 1080 lamer secret
# http 192.168.89.3 8080 justu hidden
# socks4 192.168.1.49 1080
# http 192.168.39.93 8080
#
# http 192.168.39.93 8080
#
#
# proxy types: http, socks4, socks5, raw
# * raw: The traffic is simply forwarded to the proxy without modification.
Expand Down