5 * License: LGPL 2.1+ with static linking exception
17 #include "../rocksock.h"
18 #include "../../lib/include/stringlist.h"
21 static char chk_host
[512];
22 static int chk_host_port
;
25 #define DPRINTF(fmt, args...) if(debug) do { dprintf(2,fmt, ## args); } while(0)
27 static int scanHost(stringlist
* chain
, char* scanproxy
, size_t max
, rs_errorInfo
*e_info
) {
32 rs_proxy proxies
[stringlist_getsize(chain
)+1];
34 rocksock_init(soc
, proxies
);
35 rocksock_set_timeout(soc
, timeout
);
37 DPRINTF("====== checking %s (timeout: %d)\n", scanproxy
, timeout
);
39 size_t i
, top
= max
== -1 ? stringlist_getsize(chain
) : max
;
41 for(i
= 0; i
< top
; i
++) {
42 // stringlist_foreach(chain, candidate) {
43 candidate
= stringlist_get(chain
, i
);
44 DPRINTF("> %s\n", candidate
);
45 if(rocksock_add_proxy_fromstring(soc
, candidate
))
49 if(rocksock_add_proxy_fromstring(soc
, scanproxy
))
52 if (!rocksock_connect(soc
, chk_host
, chk_host_port
, 0)){
54 ret
= 0; /* success */
57 DPRINTF("%s\n", rocksock_strerror_detailed(soc
, ebuf
, sizeof ebuf
));
58 *e_info
= soc
->lasterror
;
62 rocksock_disconnect(soc
);
68 static int usage(const char *argv0
) {
70 "proxy checker/chain generator.\n\n"
72 "%s [options] chain-length\n"
73 "[-c check_ip:port]\n"
74 "[-T global timeout_in_millisec]\n"
75 "[-t per-proxy additional timeout_in_millisec]\n"
76 "[-l fixedlist.txt]\n"
79 "generates a working proxychain.\n"
80 "every proxy that works will be added to the chain, and connects will only\n"
81 "be done through the existing chain.\n"
82 "if the desired chain length is reached, the chain will be printed to stdout.\n"
83 "the list of proxies is passed on stdin in type://ip:port format, where type\n"
84 "can be one of socks4|socks5|http\n"
85 "the optional list added with -l contains proxies that will be added w/o check\n"
88 "timeout defaults to 1500.\n"
89 "checkip:port defaults to cnn.com:80\n"
91 ,argv0
, argv0
, argv0
);
95 int main(int argc
, char** argv
) {
100 char *checkurl
= "cnn.com:80";
101 int base_timeout
= 1500;
102 int per_proxy_timeout
= 0;
104 while ((c
= getopt(argc
, argv
, "c:T:t:l:")) != -1) {
110 base_timeout
= atoi(optarg
);
113 per_proxy_timeout
= atoi(optarg
);
119 return usage(argv
[0]);
123 if (optind
>= argc
) {
124 dprintf(2, "error: chain length missing\n");
125 return usage(argv
[0]);
128 int n_proxies
= atoi(argv
[optind
]);
131 char *p
= strchr(checkurl
, ':');
132 if(!p
) return usage(argv
[0]);
134 size_t l
= p
-checkurl
;
135 strncpy(chk_host
, checkurl
, l
);
137 chk_host_port
= atoi(++p
);
141 stringlist
*chain
= stringlist_new(n_proxies
);
145 FILE *f
= fopen(load_list
, "r");
146 while(fgets(buf
, sizeof buf
, f
)) {
148 if((p
= strrchr(buf
, '\n'))) *p
= 0;
149 if(*buf
== 0 || *buf
== '#') continue;
150 stringlist_add_dup(chain
, buf
);
155 while(stringlist_getsize(chain
) < n_proxies
) {
156 if(!fgets(buf
, sizeof buf
, stdin
))
159 if((p
= strrchr(buf
, '\n'))) *p
= 0;
160 if(*buf
== 0 || *buf
== '#') continue;
163 for(i
=0; i
< stringlist_getsize(chain
); i
++) {
164 char *entry
= stringlist_get(chain
, i
);
165 if (!strcmp(entry
, buf
)) goto next
;
168 timeout
= base_timeout
+ (per_proxy_timeout
* stringlist_getsize(chain
));
169 rs_errorInfo last_err
;
170 if(0 == (ret
= scanHost(chain
, buf
, -1, &last_err
)))
171 stringlist_add_dup(chain
, buf
);
173 if(last_err
.errortype
== RS_ET_OWN
&&
174 (last_err
.error
== RS_E_REMOTE_DISCONNECTED
||
175 last_err
.error
== RS_E_TARGETPROXY_CONN_REFUSED
) &&
176 last_err
.failedProxy
!= -1 && stringlist_getsize(chain
) > 0
178 int fp
= last_err
.failedProxy
, fails
= 0;
180 ret
= scanHost(chain
, buf
, fp
, &last_err
);
181 if(!ret
|| last_err
.failedProxy
!= fp
) break;
185 dprintf(2, "proxy: %d stopped working, removing\n", fp
);
186 stringlist_delete(chain
, fp
);
193 stringlist_foreach(chain
, px
) {