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

How to specify server by DOMAIN PORT not IP PORT? #246

Closed
xieranmaya opened this issue Jun 28, 2018 · 31 comments
Closed

How to specify server by DOMAIN PORT not IP PORT? #246

xieranmaya opened this issue Jun 28, 2018 · 31 comments

Comments

@xieranmaya
Copy link

I'm having a server with a dynamic IP address(ADSL) and a DDNS configured for it, thus I need to use DOMAIN to specify the server, any way?

@rofl0r
Copy link
Owner

rofl0r commented Jun 28, 2018

yes, you write a script that resolves the host and then creates a proxychains.conf from a template like this:

#!/bin/sh
# proxychains wrapper
PROXY_DNS=foobar.com
PROXY_PORT=1080
PROXY_IP=$(host $PROXY_DNS | tail -n 1 | awk '{n=split($0, a, " "); print a[n];}')
conf=/tmp/pxc4.conf.$$
cat << EOF > $conf
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
EOF
echo "socks5 $PROXY_IP $PROXY_PORT" >> $conf
trap "rm -f $conf" INT TERM
proxychains4 -f "$conf" "$@"
ec="$?"
rm -f "$conf"
return "$ec"

@gemmax
Copy link

gemmax commented Jul 1, 2018

when i run the script, it occurs:
Usage: proxychains4 -q -f config_file program_name [arguments]
-q makes proxychains quiet - this overrides the config setting
-f allows one to manually specify a configfile to use
for example : proxychains telnet somehost.com
More help in README file

what should i do?

@rofl0r
Copy link
Owner

rofl0r commented Jul 1, 2018

did you pass parameters ? usage is like sh script.sh curl ifconfig.me

if it still doesn't work use sh -x instead of sh and paste the output here

@Justsoos
Copy link

to @rofl0r , but shell script is very unreliable, such like:

$ host g.www.ms.akadns.net
g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net.
lb1.www.ms.akadns.net has address 13.75.118.214

the alias will cause error of host command, and also to multi-line output of some domainname by cut command.
I will try to write a proxychains wrapper, upload later.

@rofl0r
Copy link
Owner

rofl0r commented Aug 27, 2018

@Justsoos see above, i fixed the host command, should work now (i wrote the above script "blind", without ever running it)

@Justsoos
Copy link

@rofl0r :D still the obviurs bug PROXY_DNS=foobar.com & host $PROXYDNS, too old to be programmer la ~ :p

@rofl0r
Copy link
Owner

rofl0r commented Aug 27, 2018

@Justsoos fixed. can you confirm it works now ?

@Justsoos
Copy link

Justsoos commented Aug 28, 2018

so, that is what I need:

  • three more profiles choosed by param -1, -2, -3, and so on
  • no param means default proxy profile
  • appointed manually by -n IP(hostname,Node‘s first letter):port -p Protocol
  • support IPv6
  • support hostname or IP input, use getent but host to resolve hostname (host will RDNS ip address)

suggest setting system alias like:
alias p='/home/your_path/p.sh'
and then you could run proxychains with ease like:
$p curl ipinfo.io
or
$p -1 curl ipinfo.io
or
$p -n 1.1.1.1:1080 -p socks5 curl ipinfo.io

thx @rofl0r, this script will be maintained at here https://gist.github.com/Justsoos/8c06f2df7b7c1b01749c19fe598e1e11

#!/bin/sh
# proxychains wrapper
# Choose pre-supposed profile with -1,-2,-3 OR appoint by -n proxy(Node)_ip(hostname):port and -p proxy_protocol and -q as quiet mode

# Default profile
proxy_hostname=127.0.0.1
proxy_port=1080
protocol=socks5
# profile 1
proxy_hostname_1=127.0.0.1
proxy_port_1=9999
protocol_1=socks5
# profile 2
proxy_hostname_2=SomeProxySite.com
proxy_port_2=443
protocol_2=https
# profile 3
proxy_hostname_3=SomeProxySite.com
proxy_port_3=8080
protocol_3=http

quiet=""

while getopts :n:p:q123 opt
do
    case $opt in
        1)
            # profile 1
            proxy_hostname=$proxy_hostname_1
            proxy_port=$proxy_port_1
            protocol=$protocol_1
            ;;
        2)
            # profile 2
            proxy_hostname=$proxy_hostname_2
            proxy_port=$proxy_port_2
            protocol=$protocol_2
            ;;
        3)
            # profile 3
            proxy_hostname=$proxy_hostname_3
            proxy_port=$proxy_port_3
            protocol=$protocol_3
            ;;
        n)
            # appointed proxy hostname & port
            proxy_port=$(echo $OPTARG | awk -F ':' '{print $(NF)}')
            # remove [] of IPv6
            proxy_hostname=$(echo $OPTARG | sed "s/:$proxy_port//g" | sed "s/\[//g" | sed "s/\]//g")
            ;;
        p)
            # appointed proxy protocol
            protocol=$OPTARG
            ;;
        q)
            # quiet
            quiet=" -q "
            ;;
        :)
            ;;
    esac
done
shift "$((OPTIND-1))"
# echo "$proxy_hostname $proxy_port $protocol"
proxy_ip=$(getent hosts $proxy_hostname | head -n1 | cut -d " " -f1)
[ -z $proxy_ip ] && proxy_ip=$proxy_hostname
# echo "$proxy_ip"
# echo "$@"
# echo "$OPTIND"
# echo "$quiet"
# echo $$
conf=/tmp/proxychains4.conf.$UID.$$
cat << EOF > $conf
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
EOF
echo "$protocol $proxy_ip $proxy_port" >> $conf
trap "rm -f $conf" INT TERM
para=${quiet}" -f "${conf}" "${@}
# echo $para
proxychains4 $para
ec="$?"
rm -f "$conf"
exit "$ec"

@philurlaub
Copy link

philurlaub commented Feb 28, 2019

Hi,
I have kind of similar problem but in my case I have a squid proxy in front of me which has a whitelist. The whitelist already contains the dns name of the second proxy but does not allow HTTP CONNECT to non whitelisted IPs or DNS names.

So

nc -v internal.first.proxy.somewhere 8888
CONNECT external.second.proxy.somewhere:8888 HTTP/1.1
Host: external.second.proxy.somewhere:22225

works fine, whereas:

nc -v internal.first.proxy.somewhere 8888
CONNECT  1.1.1.1:8888 HTTP/1.1

does not (Permission denied). Unfortunately your workaround does not solve this problem.
Do you have an idea how to fix this besides rewriting the tool?

Regards

rofl0r added a commit that referenced this issue Feb 28, 2019
conditions that need to be met are:
1) chaintype strict
2) proxy_dns on
3) not the first proxy in the list

if these conditions are met, the dns name can be passed to be
receiving proxy and be resolved there.

addressing #246 (comment)
@rofl0r
Copy link
Owner

rofl0r commented Feb 28, 2019

@philurlaub see latest commit ^

@philurlaub
Copy link

philurlaub commented Feb 28, 2019

@rofl0r thanks a lot! Really appreciate your fast response.

@philurlaub
Copy link

Okay, one more thing, if you could confirm, that basic auth works for the second proxy with dns name, that would help alot :) I currently get always denied.

http 1.1.1.1 8888
http external.second.proxy.somewhere 22225 user password

@rofl0r
Copy link
Owner

rofl0r commented Feb 28, 2019

it worked for my socks5 test server with password auth. can you provide me a pcap recording of the transaction (recorded with tcpdump or wireshark)? (you could change user/pass to something non-sensitive for testing)

@philurlaub
Copy link

tcpdumping something is not a trivial task in my case as I'm in a big company setup surrounded with lots of restrictions. Basic auth seems to work though, it just behaviors not the way I suspected. Some URLs work some doesn't but that's probably because of one of the proxys having more restrictions. Nevertheless thanks again for testing!

@onichandame
Copy link

Why is domain name not directly supported by the proxychains.conf?

@rofl0r
Copy link
Owner

rofl0r commented Jul 12, 2020

Why is domain name not directly supported by the proxychains.conf?

it's explained in great detail in one of the issues here. please post a link when you find it.

@krackers
Copy link

krackers commented Nov 30, 2020

Why is domain name not directly supported by the proxychains.conf?

I'm curious about this as well. While I agree that adding code to support this is unnecessary since it can be handled via the wrapper script, at first glance it doesn't seem like there's any major hurdles implementation-wise.

The only reference I found was in #184 where you mention that "it's not possible due to the way DNS resolution is internally done." However, in strict-chain mode proxychains already supports hostnames in the config for all except the first server. It seems like one should be able to modify get_chain_data to add a case for count == 1 where we call true_gethostbyname to resolve it using the libc resolver. What am I missing?

@rofl0r
Copy link
Owner

rofl0r commented Nov 30, 2020

It seems like one should be able to modify get_chain_data to add a case for count == 1 where we call true_gethostbyname to resolve it using the libc resolver.

ok, try it out and file a PR if it works.

@krackers
Copy link

krackers commented Dec 1, 2020

@rofl0r Ah you're right, since gethostbyname ends up calling connect it's not really so straightforward. We end up needing to guard it so we don't call init again if the call stack originates from get_chain_data. This is a really hacky patch that works on linux at least, but I'm not confident it's bulletproof. Either way this was just curiosity on my part to see whether it was possible.

diff --git a/src/libproxychains.c b/src/libproxychains.c
index fc6880f..437cbae 100644
--- a/src/libproxychains.c
+++ b/src/libproxychains.c
@@ -82,6 +82,7 @@ unsigned int remote_dns_subnet = 224;
 pthread_once_t init_once = PTHREAD_ONCE_INIT;
 
 static int init_l = 0;
+static int getting_chain_data = 0;
 
 static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
 
@@ -131,13 +132,16 @@ static void do_init(void) {
        srand(time(NULL));
        core_initialize();
 
+       setup_hooks();
+
        /* read the config file */
+       getting_chain_data = 1;
        get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
        DUMP_PROXY_CHAIN(proxychains_pd, proxychains_proxy_count);
+       getting_chain_data = 0;
 
        proxychains_write_log(LOG_PREFIX "DLL init: proxychains-ng %s\n", proxychains_get_version());
 
-       setup_hooks();
 
        while(close_fds_cnt) true_close(close_fds[--close_fds_cnt]);
        init_l = 1;
@@ -341,13 +345,32 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ
                                                ip_type4 internal_ip = at_get_ip_for_host(host, strlen(host));
                                                pd[count].ip.is_v6 = 0;
                                                host_ip->addr.v4 = internal_ip;
-                                               if(internal_ip.as_int == IPT4_INVALID.as_int)
-                                                       goto inv_host;
                                        } else {
+                                               struct addrinfo* addr;
+                                               int result = true_getaddrinfo(host, NULL, NULL, &addr);
+                                               if (result != 0) {
+                                                       goto inv_host;
+                                               }
+                                               for (struct addrinfo* res = addr; res != NULL; res = res->ai_next) {
+                                                       int af = res->ai_family;
+                                                       struct sockaddr *addr = res->ai_addr;
+                                                       switch (af)
+                                                       {
+                                                               case AF_INET:
+                                                                       pd[count].ip.is_v6 = 0;
+                                                                       host_ip->addr.v4 = IPT4_INT(((struct sockaddr_in*) addr)->sin_addr.s_addr);
+                                                                       goto got_host;
+                                                               case AF_INET6:
+                                                                       pd[count].ip.is_v6 = 1;
+                                                                       memcpy(host_ip->addr.v6, ((struct sockaddr_in6*) addr)->sin6_addr.s6_addr, 16);
+                                                                       goto got_host;
+                                                       }
+                                               }
+                                       }
+got_host:
+                                       if (!host_ip->is_v6 && host_ip->addr.v4.as_int == IPT4_INVALID.as_int) {
 inv_host:
-                                               fprintf(stderr, "proxy %s has invalid value or is not numeric\n", host);
-                                               fprintf(stderr, "non-numeric ips are only allowed under the following circumstances:\n");
-                                               fprintf(stderr, "chaintype == strict (%s), proxy is not first in list (%s), proxy_dns active (%s)\n\n", bool_str(*ct == STRICT_TYPE), bool_str(count > 0), rdns_resolver_string(proxychains_resolver));
+                                               fprintf(stderr, "proxy %s has invalid value\n", host);
                                                exit(1);
                                        }
                                }
@@ -547,6 +570,9 @@ 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);
 }
 int connect(int sock, const struct sockaddr *addr, unsigned int len) {
+       if (getting_chain_data) {
+               return true_connect(sock, addr, len);
+       }
        INIT();
        PFUNC();

@rofl0r
Copy link
Owner

rofl0r commented Dec 1, 2020

This is a really hacky patch that works on linux at least, but I'm not confident it's bulletproof.

congrats. yes, to know whether it's bulletproof one would have to test it with all different proxy_dns/remote_dns backends. which reminds me that in case the proxyresolv script is installed, one could eventually just call proxy_gethostbyname_old(), which i recently re-added, without any hacks.

@krackers
Copy link

krackers commented Dec 1, 2020

whether it's bulletproof one would have to test it with all different backends

I also wonder if there could be some thread related race condition where we after we set getting_chain_data = 1 but before we finish calling get_chain_data, some other application thread calls connect which will be erroneously redirected to true_connect and thus bypass the proxy. I guess you would need to make getting_chain_data a thread-local variable to avoid this.

one could eventually just call proxy_gethostbyname_old

That script injects the libproxychains dylib before calling dig, which would seem to cause an issue since that newly forked process will again try to call get_chain_data in the setup, resulting in endless recursion.
I think what you'd want to do is unset LD_PRELOAD, fork/exec host, and then restore the LD_PRELOAD.

That seems even more hacky than the above though. I'll leave it to someone else who cares enough about this to rigorously test and polish the implementation.

@DUOLabs333
Copy link

Is is possible to specify hostname if it can be resolvable by the local DNS or Bonjour? I have a proxy server on system.local, and can resolve it on my Mac. Since it does not need an external DNS server, it should be possible to resolve it.

@xlucn
Copy link

xlucn commented Jun 2, 2022

Or could proxychains at least parse hostnames in config file from /etc/hosts?

@rofl0r
Copy link
Owner

rofl0r commented Jun 2, 2022

Or could proxychains at least parse hostnames in config file from /etc/hosts?

it does already

@xlucn
Copy link

xlucn commented Jun 2, 2022

But proxychains-ng gives an error message:

$ proxychains curl www.google.com
proxy proxy-host has invalid value or is not numeric
non-numeric ips are only allowed under the following circumstances:
chaintype == strict (true), proxy is not first in list (false), proxy_dns active (thread)

Using the config file:

strict_chain
quiet_mode
proxy_dns
[ProxyList]
socks5 proxy-host 1081

and /etc/hosts file:

192.168.1.100   proxy-host

Is this not the use case?

@rofl0r
Copy link
Owner

rofl0r commented Jun 2, 2022

there's hostsreader code in proxychains-ng, but apparently it's only used for getaddrinfo-style lookups for the proxified program, but not for config processing. eventually this could be added without big effort.

@ocervell
Copy link

Any updates on this ? Seems like DNS resolution would come a long way to e.g automate proxychains conf deployment in Kubernetes for instance, where you might have a proxy like:

# proxychains.conf  VER 4.x
#
#        HTTP, SOCKS4a, SOCKS5 tunneling proxifier with DNS.

proxy_dns
strict_chain
# dynamic_chain
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000

[ProxyList]
socks5 tor-privoxy.default.svc.cluster.local 9050

That links to an egress proxy service deployed in k8s to control outgoing traffic.

@rofl0r
Copy link
Owner

rofl0r commented Sep 25, 2023

Any updates on this ?

no. use the wrapper script from my first post.

@rofl0r rofl0r closed this as not planned Won't fix, can't repro, duplicate, stale Sep 25, 2023
@ocervell
Copy link

ocervell commented Sep 25, 2023

Sorry but your wrapper script is not very good, goes against all rules of automation ... Not too mention IPs can change in time and make deployments drift ... Seems trivial to add DNS resolution to proxychains, too bad you don't want to open a discussion, I could even have helped write it.

@goooogs
Copy link

goooogs commented Dec 12, 2023

yes, you write a script that resolves the host and then creates a proxychains.conf from a template like this:

#!/bin/sh
# proxychains wrapper
PROXY_DNS=foobar.com
PROXY_PORT=1080
PROXY_IP=$(host $PROXY_DNS | tail -n 1 | awk '{n=split($0, a, " "); print a[n];}')
conf=/tmp/pxc4.conf.$$
cat << EOF > $conf
strict_chain
proxy_dns
remote_dns_subnet 224
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
EOF
echo "socks5 $PROXY_IP $PROXY_PORT" >> $conf
trap "rm -f $conf" INT TERM
proxychains4 -f "$conf" "$@"
ec="$?"
rm -f "$conf"
return "$ec"

Our proxy IP address may change. If the proxy IP address changes after the program is started, how can it automatically use the new address without restarting?

@rofl0r
Copy link
Owner

rofl0r commented Dec 15, 2023

If the proxy IP address changes after the program is started, how can it automatically use the new address without restarting?

it can't. you'd need some kind of background task which contiously polls what the hostname resolves to, and then restart proxychains tasks. much simpler solution: don't change the proxy ip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests