socks5proxy.c 6.5 KB

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