diff options
author | Adam Hamsik <haaaad@gmail.com> | 2020-07-21 23:41:19 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-21 23:41:19 +0300 |
commit | 5dd8450452a31d2b466372b7d0284149795a9b64 (patch) | |
tree | b8faed658b3d79963dbd81ccddf2f51ab6ff561c | |
parent | 8dea4f9297275d8115d573104f164b298c9f84df (diff) | |
parent | d7096b4f98e17c791f98aa13ce451c1650147ca3 (diff) |
Merge pull request #99 from tomgilon/dnat
Add dnat feature
-rw-r--r-- | src/core.h | 6 | ||||
-rw-r--r-- | src/libproxychains.c | 78 | ||||
-rw-r--r-- | src/proxychains.conf | 18 |
3 files changed, 102 insertions, 0 deletions
@@ -20,6 +20,7 @@ #define __CORE_HEADER #define BUFF_SIZE 8*1024 // used to read responses from proxies. #define MAX_LOCALNET 64 +#define MAX_DNAT 64 typedef union { unsigned char octet[4]; @@ -94,6 +95,11 @@ typedef struct { } localaddr_arg; typedef struct { + struct in_addr orig_dst, new_dst; + unsigned short orig_port, new_port; +} dnat_arg; + +typedef struct { ip_type ip; unsigned short port; proxy_type pt; diff --git a/src/libproxychains.c b/src/libproxychains.c index 46d11c7..23eeb53 100644 --- a/src/libproxychains.c +++ b/src/libproxychains.c @@ -66,6 +66,8 @@ chain_type proxychains_ct; proxy_data proxychains_pd[MAX_CHAIN]; size_t num_localnet_addr = 0; +dnat_arg dnats[MAX_DNAT]; +size_t num_dnats = 0; #ifdef THREAD_SAFE pthread_once_t init_once = PTHREAD_ONCE_INIT; @@ -188,6 +190,8 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ char *env; 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]; FILE *file = NULL; if(proxychains_got_chain_data) @@ -297,6 +301,55 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ proxychains_quiet_mode = 1; } else if(strstr(buff, "proxy_dns")) { proxychains_resolver = 1; + } else if(strstr(buff, "dnat")) { + if(sscanf(buff, "%s %21[^ ] %21s\n", user, dnat_orig_addr_port, dnat_new_addr_port) < 3) { + fprintf(stderr, "dnat format error"); + exit(1); + } + /* clean previously used buffer */ + memset(dnat_orig_port, 0, sizeof(dnat_orig_port) / sizeof(dnat_orig_port[0])); + memset(dnat_new_port, 0, sizeof(dnat_new_port) / sizeof(dnat_new_port[0])); + + (void)sscanf(dnat_orig_addr_port, "%15[^:]:%5s", dnat_orig_addr, dnat_orig_port); + (void)sscanf(dnat_new_addr_port, "%15[^:]:%5s", dnat_new_addr, dnat_new_port); + + if(num_dnats < MAX_DNAT) { + int error; + error = + inet_pton(AF_INET, dnat_orig_addr, + &dnats[num_dnats].orig_dst); + if(error <= 0) { + fprintf(stderr, "dnat original destination address error\n"); + exit(1); + } + + error = + inet_pton(AF_INET, dnat_new_addr, + &dnats[num_dnats].new_dst); + if(error <= 0) { + fprintf(stderr, "dnat effective destination address error\n"); + exit(1); + } + + if(dnat_orig_port[0]) { + dnats[num_dnats].orig_port = + (short) atoi(dnat_orig_port); + } else { + dnats[num_dnats].orig_port = 0; + } + + if(dnat_new_port[0]) { + dnats[num_dnats].new_port = + (short) atoi(dnat_new_port); + } else { + dnats[num_dnats].new_port = 0; + } + + PDEBUG("added dnat: orig-dst=%s orig-port=%d new-dst=%s new-port=%d\n", dnat_orig_addr, dnats[num_dnats].orig_port, dnat_new_addr, dnats[num_dnats].new_port); + ++num_dnats; + } else { + fprintf(stderr, "# of dnat exceed %d.\n", MAX_DNAT); + } } } } @@ -350,6 +403,8 @@ int connect(int sock, const struct sockaddr *addr, socklen_t len) { char str[256]; #endif struct in_addr *p_addr_in; + struct sockaddr_in new_addr; + dnat_arg *dnat = NULL; unsigned short port; size_t i; int remote_dns_connect = 0; @@ -373,6 +428,29 @@ int connect(int sock, const struct sockaddr *addr, socklen_t len) { // check if connect called from proxydns remote_dns_connect = (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet); + // more specific first + for(i = 0; i < num_dnats && !remote_dns_connect && !dnat; i++) + if((dnats[i].orig_dst.s_addr == p_addr_in->s_addr)) + if(dnats[i].orig_port && (dnats[i].orig_port == port)) + dnat = &dnats[i]; + + for(i = 0; i < num_dnats && !remote_dns_connect && !dnat; i++) + if(dnats[i].orig_dst.s_addr == p_addr_in->s_addr) + if(!dnats[i].orig_port) + dnat = &dnats[i]; + + if (dnat) { + if (dnat->new_port) + new_addr.sin_port = htons(dnat->new_port); + else + new_addr.sin_port = htons(port); + new_addr.sin_addr = dnat->new_dst; + + addr = (struct sockaddr *)&new_addr; + p_addr_in = &((struct sockaddr_in *) addr)->sin_addr; + port = ntohs(((struct sockaddr_in *) addr)->sin_port); + } + 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)) { diff --git a/src/proxychains.conf b/src/proxychains.conf index 14a0e63..07f4a7e 100644 --- a/src/proxychains.conf +++ b/src/proxychains.conf @@ -73,6 +73,24 @@ localnet 127.0.0.0/255.0.0.0 ## Exclude connections to ANYwhere with port 80 # localnet 0.0.0.0:80/0.0.0.0 + +### Examples for dnat +## Trying to proxy connections to destinations which are dnatted, +## will result in proxying connections to the new given destinations. +## Whenever I connect to 1.1.1.1 on port 1234 actually connect to 1.1.1.2 on port 443 +# dnat 1.1.1.1:1234 1.1.1.2:443 + +## Whenever I connect to 1.1.1.1 on port 443 actually connect to 1.1.1.2 on port 443 +## (no need to write :443 again) +# dnat 1.1.1.2:443 1.1.1.2 + +## No matter what port I connect to on 1.1.1.1 port actually connect to 1.1.1.2 on port 443 +# dnat 1.1.1.1 1.1.1.2:443 + +## Always, instead of connecting to 1.1.1.1, connect to 1.1.1.2 +# dnat 1.1.1.1 1.1.1.2 + + # ProxyList format # type host port [user pass] # (values separated by 'tab' or 'blank') |