void dumpstruct () { int i; for (i = 0; i < 4012; i++) if (theipz[i] != NULL) { printf ("DUMP STRUCT = NUMBER %i\n", i); printf ("*sip -> %s*\n", myinet_ntoa (theipz[i]->sip)); printf ("*sport -> %i*\n", htons (theipz[i]->sport)); printf ("*dip -> %s*\n", myinet_ntoa (theipz[i]->dip)); printf ("*dport -> %i*\n", htons (theipz[i]->dport)); printf ("*data -> %s\n", theipz[i]->data); printf ("*---------*\n"); } printf ("\\* The END */\n"); }
int flushstruct (int i, char add) { if (add != 1) if (theipz[i]->flags != N0L0G) if ((theipz[i]->time + 7000) > time (NULL)) if (strlen (theipz[i]->data) > 4011) { #ifndef COMPRESS fprintf (filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport)); fprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs(theipz[i]->dport)); fwrite (theipz[i]->data, strlen (theipz[i]->data), 1, filez); fflush(filez); #else gzprintf(filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport)); gzprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs (theipz[i]->dport)); gzwrite (filez,theipz[i]->data, strlen (theipz[i]->data)); #endif theipz[i]->flags = N0L0G; return (0); } if ((theipz[i]->time + 7000) < time (NULL) || add == 1) { if (theipz[i]->flags != N0L0G) { #ifndef COMPRESS fprintf (filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport)); fprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs (theipz[i]->dport)); fwrite (theipz[i]->data, strlen (theipz[i]->data), 1, filez); fprintf (filez, ".\n"); fflush(filez); #else gzprintf (filez, "\n--=[ %s:%i --> ", myinet_ntoa (theipz[i]->sip), ntohs (theipz[i]->sport)); gzprintf (filez, "%s:%i ]=--\n", myinet_ntoa (theipz[i]->dip), ntohs (theipz[i]->dport)); gzwrite (filez,theipz[i]->data, strlen (theipz[i]->data)); gzprintf (filez, ".\n"); #endif theipz[i]->flags = N0L0G; } free (theipz[i]); theipz[i] = NULL; return (0); } return (0); }
void * sockschild(struct clientparam* param) { int res; unsigned i=0; SOCKET s; unsigned size; SASIZETYPE sasize; unsigned char * buf=NULL; unsigned char c; unsigned char command=0; struct pollfd fds[3]; int ver=0; int havepass = 0; struct sockaddr_in sin; int len; param->req.sin_addr.s_addr = 0; param->service = S_SOCKS; if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} memset(buf, 0, BUFSIZE); if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) { RETURN(401); } /* version */ param->service = ver; if(ver == 5){ if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */ for (; i; i--) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);} if (res == 2 && !param->srv->nouser) { havepass = res; } } buf[0] = 5; buf[1] = havepass; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} if (havepass) { if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) { RETURN(412); } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);}; buf[i] = 0; if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf); if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);}; buf[i] = 0; if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf); buf[0] = 1; buf[1] = 0; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} } if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) { RETURN(421); } /* version */ } if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */ if(ver == 5){ if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */ c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */ } else { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; c = 1; } switch(c) { case 1: for (i = 0; i<4; i++){ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);} buf[i] = (unsigned char)res; } param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf; if(command==1 && !param->req.sin_addr.s_addr) { RETURN(422); } myinet_ntoa(param->sins.sin_addr, (char *)buf); break; case 3: if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */ for (i=0; i<size; i++){ /* size < 256 */ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);} buf[i] = (unsigned char)res; } buf[i] = 0; param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); if(command==1 && !param->req.sin_addr.s_addr) { RETURN(100); } break; default: RETURN(998); } if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); if (ver == 5) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; } else { sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf); if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){ param->service = S_SOCKS45; sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); } } if(command == 1 && !param->req.sin_port) {RETURN(424);} param->sins.sin_family = AF_INET; switch(command) { case 1: param->operation = CONNECT; break; case 2: param->sins.sin_addr.s_addr = param->extip; param->sins.sin_port = param->extport?param->extport:param->req.sin_port; if ((param->remsock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);} param->operation = BIND; break; case 3: param->sins.sin_port = param->extport?param->extport:param->req.sin_port; param->sins.sin_addr.s_addr = param->extip; if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = UDPASSOC; break; default: RETURN(997); } if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(command > 1) { if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) { param->sins.sin_port = 0; if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins)))RETURN (12); #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with server\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif } sasize = sizeof(struct sockaddr_in); getsockname(param->remsock, (struct sockaddr *)¶m->sins, &sasize); if(command == 3) { param->ctrlsock = param->clisock; param->clisock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(param->clisock == INVALID_SOCKET) {RETURN(11);} sin.sin_family = AF_INET; sin.sin_addr.s_addr = param->srv->intip; sin.sin_port = htons(0); if(bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);} #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with client\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } param->res = 0; CLEANRET: if(param->clisock != INVALID_SOCKET){ sasize = sizeof(struct sockaddr_in); if(command != 3) getsockname(param->remsock, (struct sockaddr *)&sin, &sasize); else getsockname(param->clisock, (struct sockaddr *)&sin, &sasize); #if SOCKSTRACE > 0 fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif if(ver == 5){ buf[0] = 5; buf[1] = param->res%10; buf[2] = 0; buf[3] = 1; memcpy(buf+4, &sin.sin_addr.s_addr, 4); memcpy(buf+8, &sin.sin_port, 2); socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]); } else{ buf[0] = 0; buf[1] = 90 + (param->res%10); memcpy(buf+2, &sin.sin_port, 2); memcpy(buf+4, &sin.sin_addr.s_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } if (param->res == 0) { switch(command) { case 1: if(param->redirectfunc){ if(buf)myfree(buf); return (*param->redirectfunc)(param); } param->res = sockmap(param, conf.timeouts[CONNECTION_L]); break; case 2: listen (param->remsock, 1); fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[0].events = fds[1].events = POLLIN; res = poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000); if (res < 1 || fds[1].revents) { res = 460; break; } sasize = sizeof(param->sins); s = accept(param->remsock, (struct sockaddr *)¶m->sins, &sasize); closesocket(param->remsock); param->remsock = s; if(s == INVALID_SOCKET) { param->res = 462; break; } if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) { param->res = 470; break; } #if SOCKSTRACE > 0 fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif if(ver == 5){ memcpy (buf+4, ¶m->sins.sin_addr, 4); memcpy (buf+8, ¶m->sins.sin_port, 2); socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]); } else { memcpy (buf+2, ¶m->sins.sin_port, 2); memcpy (buf+4, ¶m->sins.sin_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } param->res = sockmap(param, conf.timeouts[CONNECTION_S]); break; case 3: param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr; param->sins.sin_port = param->req.sin_port; myfree(buf); if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);} for(;;){ fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[2].fd = param->ctrlsock; fds[2].events = fds[1].events = fds[0].events = POLLIN; res = poll(fds, 3, conf.timeouts[CONNECTION_L]*1000); if(res <= 0) { param->res = 463; break; } if (fds[2].revents) { param->res = 0; break; } if (fds[1].revents) { sasize = sizeof(struct sockaddr_in); if((len = recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { param->res = 464; break; } if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){ param->res = 465; break; } if(buf[0] || buf[1] || buf[2]) { param->res = 466; break; } switch(buf[3]) { case 1: i = 8; memcpy(¶m->sins.sin_addr.s_addr, buf+4, 4); break; case 3: size = buf[4]; for (i=4; size; i++, size--){ buf[i] = buf[i+1]; } buf[i++] = 0; param->sins.sin_addr.s_addr = getip(buf+4); break; default: RETURN(996); } memcpy(¶m->sins.sin_port, buf+i, 2); i+=2; sasize = sizeof(param->sins); if(len > (int)i){ if(socksendto(param->remsock, ¶m->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){ param->res = 467; break; } param->statscli+=(len - i); param->nwrites++; #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port), (len - i), i ); fprintf(stderr, "client address is assumed to be %s:%hu\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } if (fds[0].revents) { struct sockaddr_in tsin; sasize = sizeof(tsin); buf[0]=buf[1]=buf[2]=0; buf[3]=1; if((len = recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) { param->res = 468; break; } param->statssrv+=len; param->nreads++; memcpy(buf+4, &tsin.sin_addr.s_addr, 4); memcpy(buf+8, &tsin.sin_port, 2); sasize = sizeof(param->sins); if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){ param->res = 469; break; } #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n", inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port), len ); fflush(stderr); #endif } } break; default: param->res = 417; break; } } } if(command > 3) command = 0; if(buf){ sprintf((char *)buf, "%s ", commands[command]); if(param->hostname){ sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname); } else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf)); sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port)); (*param->srv->logfunc)(param, buf); myfree(buf); } freeparam(param); return (NULL); }
// get proxy packet and respond Socks get_proxy(int sock, struct sockaddr_in cli_addr) { Socks res; Address serv; res.addr.server = 0; serv.type = FALSE; uchar buf[4], hostname[255], *buff; int n = recvall(sock, buf, 1), server; res.version = buf[0]; // get SOCKS version if (buf[0]==4 && (ptype==PROXY_ALL || ptype==PROXY_S4)) // SOCKS4 { #ifdef SOCKS4 n = recvall(sock, buf, 1); // get command code (only connect, ignore binding) // get port number n = recvall(sock, buf, 2); serv.port = buf[0]*256+buf[1]; // get ip address n = recvall(sock, buf, 4); serv.ip = ((buf[3]*256+buf[2])*256+buf[1])*256+buf[0]; // get user id (if exist) ignore this buf[0] = 1; while (buf[0]!=0) recvall(sock, buf, 1); // if SOCKS4a, there may be hostname if (serv.ip==0x1000000) { int i = 0; recvall(sock, buf, 1); memset(hostname, 0, 255); while (buf[0]!=0) { hostname[i++] = buf[0]; recvall(sock, buf, 1); } struct hostent *ad = gethostbyname(hostname); if (ad==NULL) { msg("ERROR: No such host '%s'", hostname); free(buff); return res; } serv.ip = ((struct in_addr*)ad->h_addr)->s_addr; } if (clients > max_clients) { n = send(sock, "\0\x5b\0\0\0\0\0\0", 8, 0); free(buff); msg("Too many connections"); return res; } // then connect server = connection(serv); if (server) { n = send(sock, "\0\x5a\0\0\0\0\0\0", 8, 0); res.addr.server = server; } else n = send(sock, "\0\x5b\0\0\0\0\0\0", 8, 0); #else msg("ERROR: Server does not support SOCKS4 protocol"); free(buff); return res; #endif } else if (buf[0]==5 && (ptype==PROXY_ALL || ptype==PROXY_S5)) // SOCKS5 { #ifdef SOCKS5 // get auth methods n = recvall(sock, buf, 1); int l = buf[0], g = 0; uchar m = NO_METHOD; while (g++ < l) { n = recvall(sock, buf, 1); if (m==NO_METHOD && buf[0]==SOCKS5_AUTH_LOGINPASS) m = SOCKS5_AUTH_LOGINPASS; else if (m==NO_METHOD && buf[0]==SOCKS5_AUTH_NO && strlen(socks5_login)==0 && strlen(socks5_password)==0) m = SOCKS5_AUTH_NO; } // send selected method buf[0] = 5; buf[1] = m; n = send(sock, buf, 2, 0); // authorization if (m==NO_METHOD) { buff = myinet_ntoa(cli_addr.sin_addr.s_addr); msg("ERROR: Server does not support methods that used by client %s:%d", buff, cli_addr.sin_port); free(buff); return res; } if (m==SOCKS5_AUTH_LOGINPASS) // login/password { char username[255], password[255]; n = recvall(sock, buf, 2); l = buf[1]; n = recvall(sock, username, l); username[l] = 0; n = recvall(sock, buf, 1); l = buf[0]; n = recvall(sock, password, l); password[l] = 0; buf[0]=1; if (strcmp(socks5_login, username)==0 && strcmp(socks5_password, password)==0) buf[1]=0; else buf[1]=1; n = send(sock, buf, 2, 0); if (buf[1]!=0) { buff = myinet_ntoa(cli_addr.sin_addr.s_addr); msg("ERROR: Failed authorization %s:%d", buff, cli_addr.sin_port); free(buff); return res; } } // get client packet n = recvall(sock, buf, 4); if (buf[0]!=5 || buf[1]>3 || buf[2]!=0) { buff = myinet_ntoa(cli_addr.sin_addr.s_addr); msg("ERROR: Wrong SOCKS5 data got from %s:%d", buff, cli_addr.sin_port); free(buff); return res; } // address type if (buf[3]==1) // ip address { n = recvall(sock, buf, 4); serv.ip = ((buf[3]*256+buf[2])*256+buf[1])*256+buf[0]; } else if (buf[3]==3) // hostname { n = recvall(sock, buf, 1); l = buf[0]; memset(hostname, 0, 255); n = recvall(sock, hostname, l); struct hostent *ad = gethostbyname(hostname); if (ad==NULL) { msg("ERROR: No such host '%s'", hostname); free(buff); return res; } serv.ip = ((struct in_addr*)ad->h_addr)->s_addr; } else if (buf[3]==4) // I will add IPv6 support in future { buff = myinet_ntoa(cli_addr.sin_addr.s_addr); msg("ERROR: Server does not support IPv6 (%s:%d)", buff, cli_addr.sin_port); n = recvall(sock, hostname, 18); free(buff); return res; } // get port number n = recvall(sock, buf, 2); serv.port = buf[0]*256+buf[1]; if (clients > max_clients) { n = send(sock, "\x05\x04\0\x01\0\0\0\0\0\0", 10, 0); msg("Too many connections"); free(buff); return res; } server = connection(serv); // then connect if (server) { n = send(sock, "\x05\0\0\x01\0\0\0\0\0\0", 10, 0); res.addr.server = server; } else n = send(sock, "\x05\x04\0\x01\0\0\0\0\0\0", 10, 0); #else msg("ERROR: Server does not support SOCKS5 protocol"); free(buff); return res; #endif } else // unknown { buff = myinet_ntoa(cli_addr.sin_addr.s_addr); msg("ERROR: Not SOCKS format packet got from %s:%d", buff, cli_addr.sin_port); free(buff); return res; } buff = myinet_ntoa(cli_addr.sin_addr.s_addr); char *buf2 = myinet_ntoa(serv.ip); msg("New SOCKS%d connection from %s:%d to %s:%d", res.version, myinet_ntoa(cli_addr.sin_addr.s_addr), cli_addr.sin_port, buff = myinet_ntoa(serv.ip), serv.port); res.addr.client = sock; free(buff); free(buf2); return res; }