socks.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /*
  2. 3APA3A simpliest proxy server
  3. (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
  4. please read License Agreement
  5. */
  6. #include "proxy.h"
  7. #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
  8. char * commands[] = {"UNKNOWN", "CONNECT", "BIND", "UDPMAP"};
  9. #define BUFSIZE 1024
  10. #define LARGEBUFSIZE 67000
  11. void * sockschild(struct clientparam* param) {
  12. int res;
  13. unsigned i=0;
  14. SOCKET s;
  15. unsigned size;
  16. SASIZETYPE sasize;
  17. unsigned short port = 0;
  18. char * buf=NULL;
  19. char c;
  20. char command=0;
  21. struct pollfd fds[3];
  22. int ver=0;
  23. int havepass = 0;
  24. #ifndef NOIPV6
  25. struct sockaddr_in6 sin = {AF_INET6};
  26. #else
  27. struct sockaddr_in sin = {AF_INET};
  28. #endif
  29. int len;
  30. int heur = 0;
  31. param->service = S_SOCKS;
  32. if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
  33. memset(buf, 0, BUFSIZE);
  34. if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) {
  35. RETURN(401);
  36. } /* version */
  37. param->service = ver;
  38. if(ver == 5){
  39. if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
  40. for (; i; i--) {
  41. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
  42. if (res == 2 && param->srv->needuser) {
  43. havepass = res;
  44. }
  45. }
  46. buf[0] = 5;
  47. buf[1] = (param->srv->needuser > 1 && !havepass)? 255 : havepass;
  48. if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(401);}
  49. if (param->srv->needuser > 1 && !havepass) RETURN(4);
  50. if (havepass) {
  51. if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
  52. RETURN(412);
  53. }
  54. if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
  55. if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
  56. buf[i] = 0;
  57. if(!param->username)param->username = mystrdup(buf);
  58. if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
  59. if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
  60. buf[i] = 0;
  61. if(!param->password)param->password = mystrdup(buf);
  62. buf[0] = 1;
  63. buf[1] = 0;
  64. if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(481);}
  65. }
  66. if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
  67. RETURN(421);
  68. } /* version */
  69. }
  70. if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */
  71. if(ver == 5){
  72. if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */
  73. c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
  74. }
  75. else {
  76. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
  77. buf[0] = (unsigned char) res;
  78. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
  79. buf[1] = (unsigned char) res;
  80. port = *(unsigned short*)buf;
  81. c = 1;
  82. }
  83. size = 4;
  84. *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET;
  85. switch(c) {
  86. #ifndef NOIPV6
  87. case 4:
  88. if(param->srv->family == 4) RETURN(997);
  89. size = 16;
  90. *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
  91. #endif
  92. case 1:
  93. for (i = 0; i<size; i++){
  94. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
  95. buf[i] = (unsigned char)res;
  96. }
  97. #ifndef NOIPV6
  98. if (c == 1 && param->srv->family==6){
  99. char prefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
  100. *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
  101. memcpy(SAADDR(&param->sinsr), prefix, 12);
  102. memcpy(12 + (char *)SAADDR(&param->sinsr), buf, 4);
  103. memcpy(SAADDR(&param->req), prefix, 12);
  104. memcpy(12 + (char *)SAADDR(&param->req), buf, 4);
  105. }
  106. else {
  107. #endif
  108. memcpy(SAADDR(&param->sinsr), buf, size);
  109. memcpy(SAADDR(&param->req), buf, size);
  110. #ifndef NOIPV6
  111. }
  112. #endif
  113. if(command == 1 && SAISNULL(&param->req)) {
  114. RETURN(431);
  115. }
  116. myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), buf, 64);
  117. if(command == 3){
  118. if(*SAFAMILY(&param->req) == *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&param->req),SAADDR(&param->sincr), SAADDRLEN(&param->req))){
  119. heur = 1;
  120. }
  121. else if (!SAISNULL(&param->req)){
  122. heur = 2;
  123. }
  124. }
  125. break;
  126. case 3:
  127. if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
  128. for (i=0; i<size; i++){ /* size < 256 */
  129. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
  130. buf[i] = (unsigned char)res;
  131. }
  132. buf[i] = 0;
  133. if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
  134. param->sinsr = param->req;
  135. break;
  136. default:
  137. RETURN(997);
  138. }
  139. if(param->hostname)myfree(param->hostname);
  140. param->hostname = mystrdup(buf);
  141. if (ver == 5) {
  142. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
  143. buf[0] = (unsigned char) res;
  144. if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
  145. buf[1] = (unsigned char) res;
  146. port = *(unsigned short*)buf;
  147. }
  148. else {
  149. sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
  150. buf[127] = 0;
  151. if(param->srv->needuser && *buf && !param->username)param->username = mystrdup(buf);
  152. if(!memcmp(SAADDR(&param->req), "\0\0\0", 3)){
  153. param->service = S_SOCKS45;
  154. sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
  155. buf[127] = 0;
  156. if(param->hostname)myfree(param->hostname);
  157. param->hostname = mystrdup(buf);
  158. if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
  159. param->sinsr = param->req;
  160. }
  161. }
  162. *SAPORT(&param->sinsr) = *SAPORT(&param->req) = port;
  163. if(command == 1 && !*SAPORT(&param->sinsr)) {RETURN(461);}
  164. switch(command) {
  165. case 1:
  166. param->operation = CONNECT;
  167. break;
  168. case 2:
  169. case 3:
  170. #ifndef NOIPV6
  171. param->sinsl = *SAFAMILY(&param->req)==AF_INET6? param->srv->extsa6 : (SAISNULL(&param->srv->extNat)?param->srv->extsa:param->srv->extNat);
  172. #else
  173. param->sinsl = SAISNULL(&param->srv->extNat)?param->srv->extsa:param->srv->extNat;
  174. #endif
  175. if ((param->remsock=so._socket(SASOCK(&param->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
  176. param->operation = command == 2?BIND:UDPASSOC;
  177. #ifdef REUSE
  178. if (command == 2){
  179. int opt;
  180. #ifdef SO_REUSEADDR
  181. opt = 1;
  182. so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
  183. #endif
  184. #ifdef SO_REUSEPORT
  185. opt = 1;
  186. so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(int));
  187. #endif
  188. }
  189. #endif
  190. break;
  191. default:
  192. RETURN(997);
  193. }
  194. if((res = (*param->srv->authfunc)(param))) {
  195. RETURN(res);
  196. }
  197. if(command > 1) {
  198. if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl))) {
  199. *SAPORT(&param->sinsl) = 0;
  200. if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl)))RETURN (12);
  201. #if SOCKSTRACE > 0
  202. fprintf(stderr, "%hu bound to communicate with server\n", *SAPORT(&param->sins));
  203. fflush(stderr);
  204. #endif
  205. }
  206. sasize = SASIZE(&param->sinsl);
  207. so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl, &sasize);
  208. if(command == 3) {
  209. param->ctrlsock = param->clisock;
  210. param->clisock = so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP);
  211. if(param->clisock == INVALID_SOCKET) {RETURN(11);}
  212. sin = param->sincl;
  213. *SAPORT(&sin) = 0;
  214. if(so._bind(param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
  215. #if SOCKSTRACE > 0
  216. fprintf(stderr, "%hu binded to communicate with client\n",
  217. ntohs(*SAPORT(&sin))
  218. );
  219. fflush(stderr);
  220. #endif
  221. }
  222. }
  223. param->res = 0;
  224. CLEANRET:
  225. if(param->clisock != INVALID_SOCKET){
  226. int repcode;
  227. sasize = sizeof(sin);
  228. if(command != 3 && param->remsock != INVALID_SOCKET) so._getsockname(param->remsock, (struct sockaddr *)&sin, &sasize);
  229. else so._getsockname(param->clisock, (struct sockaddr *)&sin, &sasize);
  230. #if SOCKSTRACE > 0
  231. fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n",
  232. param->res,
  233. commands[command],
  234. inet_ntoa(sin.sin_addr),
  235. ntohs(sin.sin_port)
  236. );
  237. fflush(stderr);
  238. #endif
  239. if(!param->res) repcode = 0;
  240. else if(param->res <= 10) repcode = 2;
  241. else if (param->res < 20) repcode = 5;
  242. else if (param->res < 30) repcode = 1;
  243. else if (param->res < 100) repcode = 4;
  244. else repcode = param->res%10;
  245. if(ver == 5){
  246. buf[0] = 5;
  247. buf[1] = repcode;
  248. buf[2] = 0;
  249. buf[3] = (*SAFAMILY(&sin) == AF_INET)?1:4;
  250. memcpy(buf+4, SAADDR(&sin), SAADDRLEN(&sin));
  251. memcpy(buf+4+SAADDRLEN(&sin), SAPORT(&sin), 2);
  252. socksend((command == 3)?param->ctrlsock:param->clisock, buf, 6+SAADDRLEN(&sin), conf.timeouts[STRING_S]);
  253. }
  254. else{
  255. buf[0] = 0;
  256. buf[1] = 90 + !!(repcode);
  257. memcpy(buf+2, SAPORT(&sin), 2);
  258. memcpy(buf+4, SAADDR(&sin), 4);
  259. socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
  260. }
  261. if (param->res == 0) {
  262. switch(command) {
  263. case 1:
  264. if(param->redirectfunc){
  265. if(buf)myfree(buf);
  266. return (*param->redirectfunc)(param);
  267. }
  268. param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
  269. break;
  270. case 2:
  271. so._listen (param->remsock, 1);
  272. fds[0].fd = param->remsock;
  273. fds[1].fd = param->clisock;
  274. fds[0].events = fds[1].events = POLLIN;
  275. res = so._poll(fds, 2, conf.timeouts[CONNECTION_L] * 1000);
  276. if (res < 1 || fds[1].revents) {
  277. res = 460;
  278. break;
  279. }
  280. sasize = sizeof(param->sinsr);
  281. s = so._accept(param->remsock, (struct sockaddr *)&param->sinsr, &sasize);
  282. so._closesocket(param->remsock);
  283. param->remsock = s;
  284. if(s == INVALID_SOCKET) {
  285. param->res = 462;
  286. break;
  287. }
  288. if(SAISNULL(&param->req) &&
  289. memcmp(SAADDR(&param->req),SAADDR(&param->sinsr),SAADDRLEN(&param->req))) {
  290. param->res = 470;
  291. break;
  292. }
  293. #if SOCKSTRACE > 0
  294. fprintf(stderr, "Sending incoming connection to client with code %d for %s with %hu\n",
  295. param->res,
  296. commands[command],
  297. *SAPORT(param->sins);
  298. );
  299. fflush(stderr);
  300. #endif
  301. if(ver == 5){
  302. buf[3] = (*SAFAMILY(&param->sinsr) == AF_INET)?1:4;
  303. memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
  304. memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
  305. socksend(param->clisock, buf, 6+SAADDRLEN(&param->sinsr), conf.timeouts[STRING_S]);
  306. }
  307. else {
  308. memcpy (buf+2, SAPORT(&param->sinsr), 2);
  309. memcpy (buf+4, SAADDR(&param->sinsr), 4);
  310. socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
  311. }
  312. param->res = mapsocket(param, conf.timeouts[CONNECTION_S]);
  313. break;
  314. case 3:
  315. param->sinsr = param->req;
  316. myfree(buf);
  317. if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}
  318. sin = (heur == 1)?param->req:param->sincr;
  319. fds[2].events = fds[1].events = fds[0].events = 0;
  320. fds[0].fd = param->remsock;
  321. fds[1].fd = param->clisock;
  322. fds[2].fd = param->ctrlsock;
  323. for(;;){
  324. if(!fds[1].events || fds[1].revents){
  325. sasize = sizeof(sin);
  326. len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize);
  327. if(len >= 0) {
  328. fds[1].events = fds[1].revents = 0;
  329. if(len < 10) continue;
  330. sasize = sizeof(sin);
  331. if(len <= 10) {
  332. param->res = 464;
  333. break;
  334. }
  335. if(SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin)) || (heur == 1 && *SAPORT(&param->sincr)!=*SAPORT(&sin))){
  336. if(heur == 1){
  337. #if SOCKSTRACE > 0
  338. fprintf(stderr, "internal UDP packet ignored\n");
  339. fflush(stderr);
  340. #endif
  341. sin = param->req;
  342. continue;
  343. }
  344. param->res = 465;
  345. break;
  346. }
  347. if(buf[0] || buf[1] || buf[2]) {
  348. param->res = 466;
  349. break;
  350. }
  351. size = 4;
  352. switch(buf[3]) {
  353. case 4:
  354. size = 16;
  355. case 1:
  356. i = 4+size;
  357. memcpy(SAADDR(&param->sinsr), buf+4, size);
  358. *SAFAMILY(&param->sinsr) = (size == 4)?AF_INET:AF_INET6;
  359. break;
  360. case 3:
  361. size = buf[4];
  362. for (i=4; size; i++, size--){
  363. buf[i] = buf[i+1];
  364. }
  365. buf[i++] = 0;
  366. if(!getip46(param->srv->family, buf+4, (struct sockaddr *) &param->sinsr)) RETURN(100);
  367. break;
  368. default:
  369. RETURN(997);
  370. }
  371. memcpy(SAPORT(&param->sinsr), buf+i, 2);
  372. i+=2;
  373. sasize = sizeof(param->sinsr);
  374. if(len > (int)i){
  375. socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000);
  376. param->statscli64+=(len - i);
  377. param->nwrites++;
  378. #if SOCKSTRACE > 1
  379. fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
  380. inet_ntoa(param->sins.sin_addr),
  381. ntohs(param->sins.sin_port),
  382. (len - i),
  383. i
  384. );
  385. fprintf(stderr, "client address is assumed to be %s:%hu\n",
  386. inet_ntoa(sin.sin_addr),
  387. ntohs(sin.sin_port)
  388. );
  389. fflush(stderr);
  390. #endif
  391. }
  392. continue;
  393. }
  394. else if(len ==0 || (len <0 && errno != EINTR && errno != EAGAIN)){
  395. param->res = 464;
  396. break;
  397. }
  398. fds[1].events = POLLIN;
  399. }
  400. if (!fds[0].events || fds[0].revents) {
  401. sasize = sizeof(param->sinsr);
  402. buf[0]=buf[1]=buf[2]=0;
  403. buf[3]=(*SAFAMILY(&param->sinsl) == AF_INET)?1:4;
  404. len = so._recvfrom(param->remsock, (char *)buf+6+SAADDRLEN(&param->sinsl), 65535 - (6+SAADDRLEN(&param->sinsl)), 0, (struct sockaddr *)&param->sinsr, &sasize);
  405. if(len == 0 || (len < 0 && errno != EAGAIN && errno !=EINTR)) {
  406. param->res = 468;
  407. break;
  408. }
  409. else if(len > 0){
  410. fds[0].events = fds[0].revents = 0;
  411. param->statssrv64+=len;
  412. param->nreads++;
  413. if(!*SAPORT(&sin) || (heur == 2 && (*SAFAMILY(&param->sinsr) != *SAFAMILY(&param->req) || memcmp(SAADDR(&param->sinsr),SAADDR(&param->req), SAADDRLEN(&param->req))))){
  414. #if SOCKSTRACE > 0
  415. fprintf(stderr, "external UDP packet ignored\n");
  416. fflush(stderr);
  417. #endif
  418. continue;
  419. }
  420. memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
  421. memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
  422. sasize = sizeof(sin);
  423. socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(&param->sinsr), conf.timeouts[SINGLEBYTE_L]*1000);
  424. #if SOCKSTRACE > 1
  425. fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",
  426. ntohs(*SAPORT(&param->sinsr)),
  427. len
  428. );
  429. fflush(stderr);
  430. #endif
  431. continue;
  432. }
  433. fds[0].events = POLLIN;
  434. }
  435. if (fds[2].revents) {
  436. param->res = 0;
  437. break;
  438. }
  439. fds[0].revents = fds[1].revents = fds[2].revents = 0;
  440. fds[2].events = POLLIN;
  441. res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000);
  442. if(res == 0 || (res < 0 && errno != EAGAIN && errno != EINTR)) {
  443. param->res = 463;
  444. break;
  445. }
  446. }
  447. break;
  448. default:
  449. param->res = 417;
  450. break;
  451. }
  452. }
  453. }
  454. if(command > 3) command = 0;
  455. if(buf){
  456. sprintf((char *)buf, "%s ", commands[command]);
  457. if(param->hostname){
  458. sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname);
  459. }
  460. else
  461. myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + strlen((char *)buf), 64);
  462. sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(*SAPORT(&param->req)));
  463. dolog(param, buf);
  464. myfree(buf);
  465. }
  466. freeparam(param);
  467. return (NULL);
  468. }
  469. #ifdef WITHMAIN
  470. struct proxydef childdef = {
  471. sockschild,
  472. 1080,
  473. 0,
  474. S_SOCKS,
  475. "-N(EXTERNAL_IP) External NAT address to report to client for BIND\n"
  476. };
  477. #include "proxymain.c"
  478. #include "log.c"
  479. #endif