socks5proxy.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /** SOCKSv5 proxy that listens on port 1080.
  2. *
  3. *
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <stdint.h>
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <sys/socket.h>
  12. #include <sys/types.h>
  13. #include <netinet/in.h>
  14. #include <netdb.h>
  15. int proxy_data(int sockfd);
  16. int main(void){
  17. int listen_socket;
  18. struct sockaddr_in address;
  19. struct sockaddr_in remote_addr;
  20. socklen_t addr_size;
  21. if (!(listen_socket = socket(AF_INET, SOCK_STREAM, 0))){
  22. printf("Error creating socket\n");
  23. return 1;
  24. }
  25. address.sin_family = AF_INET;
  26. address.sin_addr.s_addr = INADDR_ANY;
  27. address.sin_port = htons(1080);
  28. if(bind(listen_socket, (struct sockaddr *) &address, sizeof(address))){
  29. printf("Error binding socket\n");
  30. return 1;
  31. }
  32. if(listen(listen_socket, 10) < 0){
  33. printf("Error listening\n");
  34. close(listen_socket);
  35. exit(1);
  36. }
  37. for(;;){
  38. addr_size = sizeof(remote_addr);
  39. int new_socket;
  40. new_socket = accept(listen_socket, (struct sockaddr *) &remote_addr,
  41. &addr_size);
  42. if(new_socket < 0){
  43. perror("accept");
  44. exit(1);
  45. }
  46. int pid = fork();
  47. if(pid > 0){ //child
  48. close(listen_socket);
  49. proxy_data(new_socket);
  50. exit(0);
  51. }
  52. close(new_socket);
  53. }
  54. return 0;
  55. }
  56. struct socks_method_req {
  57. uint8_t version;
  58. uint8_t num_methods;
  59. };
  60. struct socks_req {
  61. uint8_t version;
  62. uint8_t cmd;
  63. uint8_t rsvd;
  64. uint8_t addr_type;
  65. };
  66. //continuously read from the socket and look for a CONNECT message
  67. int proxy_data(int sockfd){
  68. uint8_t *buffer = calloc(1, BUFSIZ);
  69. uint8_t *response = calloc(1, BUFSIZ);
  70. int bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
  71. if (bytes_read < 0){
  72. printf("Error reading from socket\n");
  73. goto err;
  74. }
  75. printf("Received %d bytes:\n", bytes_read);
  76. for(int i=0; i< bytes_read; i++){
  77. printf("%02x ", buffer[i]);
  78. }
  79. printf("\n");
  80. //Respond to methods negotiation
  81. struct socks_method_req *clnt_meth = (struct socks_method_req *) buffer;
  82. uint8_t *p = buffer + 2;
  83. if(clnt_meth->version != 0x05){
  84. printf("Client supplied invalid version: %02x\n", clnt_meth->version);
  85. }
  86. int responded = 0;
  87. int bytes_sent;
  88. for(int i=0; i< clnt_meth->num_methods; i++){
  89. if(p[0] == 0x00){//send response with METH= 0x00
  90. response[0] = 0x05;
  91. response[1] = 0x00;
  92. send(sockfd, response, 2, 0);
  93. responded = 1;
  94. }
  95. p++;
  96. }
  97. if(!responded){//respond with METH= 0xFF
  98. response[0] = 0x05;
  99. response[1] = 0xFF;
  100. send(sockfd, response, 2, 0);
  101. goto err;
  102. }
  103. //Now wait for a connect request
  104. bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
  105. if (bytes_read < 0){
  106. printf("Error reading from socket\n");
  107. goto err;
  108. }
  109. printf("Received %d bytes:\n", bytes_read);
  110. for(int i=0; i< bytes_read; i++){
  111. printf("%02x ", buffer[i]);
  112. }
  113. printf("\n");
  114. struct socks_req *clnt_req = (struct socks_req *) buffer;
  115. p = buffer+4;
  116. //see if it's a connect request
  117. if(clnt_req->cmd != 0x01){
  118. printf("Error: issued a non-connect command\n");
  119. goto err;
  120. }
  121. //from this point on, this code will live on slitheen relay
  122. struct sockaddr_in dest;
  123. dest.sin_family = AF_INET;
  124. uint8_t domain_len;
  125. switch(clnt_req->addr_type){
  126. case 0x01:
  127. //IPv4
  128. dest.sin_addr.s_addr = *((uint32_t*) p);
  129. printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
  130. p += 4;
  131. break;
  132. case 0x03:
  133. //domain name
  134. domain_len = p[0];
  135. p++;
  136. uint8_t *domain_name = calloc(1, domain_len+1);
  137. memcpy(domain_name, p, domain_len);
  138. domain_name[domain_len] = '\0';
  139. struct hostent *host;
  140. host = gethostbyname((const char *) domain_name);
  141. dest.sin_addr = *((struct in_addr *) host->h_addr);
  142. printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
  143. p += domain_len;
  144. free(domain_name);
  145. break;
  146. case 0x04:
  147. //IPv6
  148. goto err;//TODO: fix this
  149. break;
  150. }
  151. //now set the port
  152. dest.sin_port = *((uint16_t *) p);
  153. printf("destination port: %d\n", ntohs(dest.sin_port));
  154. int32_t handle = socket(AF_INET, SOCK_STREAM, 0);
  155. if(handle < 0){
  156. printf("error: constructing socket failed\n");
  157. goto err;
  158. }
  159. struct sockaddr_in my_addr;
  160. socklen_t my_addr_len = sizeof(my_addr);
  161. int32_t error = connect (handle, (struct sockaddr *) &dest, sizeof (struct sockaddr));
  162. if(error <0){
  163. printf("error connecting\n");
  164. goto err;
  165. }
  166. getsockname(handle, (struct sockaddr *) &my_addr, &my_addr_len);
  167. //now send the reply to the client
  168. response[0] = 0x05;
  169. response[1] = 0x00;//TODO: make this accurate
  170. response[2] = 0x00;
  171. response[3] = 0x01;
  172. *((uint32_t *) (response + 4)) = my_addr.sin_addr.s_addr;
  173. *((uint16_t *) (response + 8)) = my_addr.sin_port;
  174. printf("Bound to %x:%d\n", my_addr.sin_addr.s_addr, ntohs(my_addr.sin_port));
  175. bytes_sent = send(sockfd, response, 10,0);
  176. printf("Sent response (%d bytes):\n", bytes_sent);
  177. for(int i=0; i< bytes_sent; i++){
  178. printf("%02x ", response[i]);
  179. }
  180. printf("\n");
  181. //now shuffle data
  182. for(;;){
  183. fd_set readfds;
  184. fd_set writefds;
  185. int32_t nfds = (sockfd > handle) ? sockfd +1 : handle + 1;
  186. FD_ZERO(&readfds);
  187. FD_ZERO(&writefds);
  188. FD_SET(sockfd, &readfds);
  189. FD_SET(handle, &readfds);
  190. FD_SET(sockfd, &writefds);
  191. FD_SET(handle, &writefds);
  192. if(select(nfds, &readfds, &writefds, NULL, NULL) <0){
  193. printf("Select error\n");
  194. continue;
  195. }
  196. if(FD_ISSET(sockfd, &readfds) && FD_ISSET(handle, &writefds)){
  197. bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
  198. if (bytes_read < 0){
  199. printf("Error reading from socket\n");
  200. goto err;
  201. }
  202. if(bytes_read > 0){
  203. printf("Received %d bytes:\n", bytes_read);
  204. for(int i=0; i< bytes_read; i++){
  205. printf("%02x ", buffer[i]);
  206. }
  207. printf("\n");
  208. bytes_sent = send(handle, buffer, bytes_read, 0);
  209. printf("Sent to website (%d bytes):\n", bytes_sent);
  210. for(int i=0; i< bytes_sent; i++){
  211. printf("%02x ", buffer[i]);
  212. }
  213. printf("\n");
  214. }
  215. } else if(FD_ISSET(handle, &readfds) && FD_ISSET(sockfd, &writefds)){
  216. bytes_read = recv(handle, buffer, BUFSIZ-1, 0);
  217. if (bytes_read < 0){
  218. printf("Error reading from socket\n");
  219. goto err;
  220. }
  221. if(bytes_read > 0){
  222. printf("Received %d bytes:\n", bytes_read);
  223. for(int i=0; i< bytes_read; i++){
  224. printf("%02x ", buffer[i]);
  225. }
  226. printf("\n");
  227. bytes_sent = send(sockfd, buffer, bytes_read, 0);
  228. printf("Sent to website (%d bytes):\n", bytes_sent);
  229. for(int i=0; i< bytes_sent; i++){
  230. printf("%02x ", buffer[i]);
  231. }
  232. printf("\n");
  233. }
  234. }
  235. }
  236. err:
  237. close(sockfd);
  238. free(buffer);
  239. free(response);
  240. exit(0);
  241. }