socks5proxy.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 <sys/stat.h>
  14. #include <netinet/in.h>
  15. #include <netdb.h>
  16. #include <pthread.h>
  17. #include <fcntl.h>
  18. #include <openssl/bio.h>
  19. #include <openssl/evp.h>
  20. #include<openssl/buffer.h>
  21. int proxy_data(int sockfd, uint8_t stream_id, int32_t pipefd);
  22. void *demultiplex_data();
  23. struct __attribute__ ((__packed__)) slitheen_hdr{
  24. uint8_t stream_id;
  25. uint16_t len;
  26. uint16_t garbage_len;
  27. };
  28. struct __attribute__ ((__packed__)) slitheen_up_hdr{
  29. uint8_t stream_id;
  30. uint16_t len;
  31. };
  32. typedef struct connection_st{
  33. int32_t pipe_fd;
  34. uint8_t stream_id;
  35. struct connection_st *next;
  36. } connection;
  37. typedef struct connection_table_st{
  38. connection *first;
  39. } connection_table;
  40. static connection_table *connections;
  41. int main(void){
  42. int listen_socket;
  43. struct sockaddr_in address;
  44. struct sockaddr_in remote_addr;
  45. socklen_t addr_size;
  46. //mkfifo("OUS_in", 0666);
  47. mkfifo("OUS_out", 0666);
  48. /* Spawn process to listen for incoming data from OUS
  49. int32_t demux_pipe[2];
  50. if(pipe(demux_pipe) < 0){
  51. printf("Failed to create pipe for new thread\n");
  52. return 1;
  53. }*/
  54. connections = calloc(1, sizeof(connection_table));
  55. connections->first = NULL;
  56. pthread_t *demux_thread = calloc(1, sizeof(pthread_t));
  57. pthread_create(demux_thread, NULL, demultiplex_data, NULL);
  58. if (!(listen_socket = socket(AF_INET, SOCK_STREAM, 0))){
  59. printf("Error creating socket\n");
  60. fflush(stdout);
  61. return 1;
  62. }
  63. address.sin_family = AF_INET;
  64. address.sin_addr.s_addr = INADDR_ANY;
  65. address.sin_port = htons(1080);
  66. if(bind(listen_socket, (struct sockaddr *) &address, sizeof(address))){
  67. printf("Error binding socket\n");
  68. fflush(stdout);
  69. return 1;
  70. }
  71. if(listen(listen_socket, 10) < 0){
  72. printf("Error listening\n");
  73. fflush(stdout);
  74. close(listen_socket);
  75. exit(1);
  76. }
  77. uint8_t last_id = 0;
  78. printf("Ready for listening\n");
  79. for(;;){
  80. addr_size = sizeof(remote_addr);
  81. int new_socket;
  82. new_socket = accept(listen_socket, (struct sockaddr *) &remote_addr,
  83. &addr_size);
  84. if(new_socket < 0){
  85. perror("accept");
  86. exit(1);
  87. }
  88. printf("New connection\n");
  89. //assign a new stream_id and create a pipe for the session
  90. connection *new_conn = calloc(1, sizeof(connection));
  91. new_conn->stream_id = last_id++;
  92. int32_t pipefd[2];
  93. if(pipe(pipefd) < 0){
  94. printf("Failed to create pipe\n");
  95. continue;
  96. }
  97. new_conn->pipe_fd = pipefd[1];
  98. new_conn->next = NULL;
  99. if(connections->first == NULL){
  100. connections->first = new_conn;
  101. printf("Added first connection with id: %d\n", new_conn->stream_id);
  102. printf("Connection table (%p) has entry %p\n", connections, connections->first);
  103. fflush(stdout);
  104. } else {
  105. connection *last = connections->first;
  106. printf("New incoming connection\n");
  107. printf("First connection was at %p\n", last);
  108. fflush(stdout);
  109. while(last->next != NULL){
  110. last = last->next;
  111. printf("Next connection was at %p\n", last);
  112. }
  113. last->next = new_conn;
  114. printf("Added connection with id: %d at %p\n", new_conn->stream_id, last->next);
  115. fflush(stdout);
  116. }
  117. int pid = fork();
  118. if(pid == 0){ //child
  119. close(listen_socket);
  120. printf("demux reads from pipe fd %d", pipefd[1]);
  121. fflush(stdout);
  122. proxy_data(new_socket, new_conn->stream_id, pipefd[0]);
  123. exit(0);
  124. }
  125. close(new_socket);
  126. }
  127. return 0;
  128. }
  129. struct socks_method_req {
  130. uint8_t version;
  131. uint8_t num_methods;
  132. };
  133. struct socks_req {
  134. uint8_t version;
  135. uint8_t cmd;
  136. uint8_t rsvd;
  137. uint8_t addr_type;
  138. };
  139. //continuously read from the socket and look for a CONNECT message
  140. int proxy_data(int sockfd, uint8_t stream_id, int32_t ous_out){
  141. uint8_t *buffer = calloc(1, BUFSIZ);
  142. uint8_t *response = calloc(1, BUFSIZ);
  143. printf("ous out pipe fd: %d\n", ous_out);
  144. fflush(stdout);
  145. int bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
  146. if (bytes_read < 0){
  147. printf("Error reading from socket (fd = %d)\n", sockfd);
  148. fflush(stdout);
  149. goto err;
  150. }
  151. printf("Received %d bytes (id %d):\n", bytes_read, stream_id);
  152. for(int i=0; i< bytes_read; i++){
  153. printf("%02x ", buffer[i]);
  154. }
  155. printf("\n");
  156. fflush(stdout);
  157. //Respond to methods negotiation
  158. struct socks_method_req *clnt_meth = (struct socks_method_req *) buffer;
  159. uint8_t *p = buffer + 2;
  160. if(clnt_meth->version != 0x05){
  161. printf("Client supplied invalid version: %02x\n", clnt_meth->version);
  162. fflush(stdout);
  163. }
  164. int responded = 0;
  165. int bytes_sent;
  166. for(int i=0; i< clnt_meth->num_methods; i++){
  167. if(p[0] == 0x00){//send response with METH= 0x00
  168. response[0] = 0x05;
  169. response[1] = 0x00;
  170. send(sockfd, response, 2, 0);
  171. responded = 1;
  172. }
  173. p++;
  174. }
  175. if(!responded){//respond with METH= 0xFF
  176. response[0] = 0x05;
  177. response[1] = 0xFF;
  178. send(sockfd, response, 2, 0);
  179. goto err;
  180. }
  181. //Now wait for a connect request
  182. bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
  183. if (bytes_read < 0){
  184. printf("Error reading from socket\n");
  185. fflush(stdout);
  186. goto err;
  187. }
  188. printf("Received %d bytes (id %d):\n", bytes_read, stream_id);
  189. for(int i=0; i< bytes_read; i++){
  190. printf("%02x ", buffer[i]);
  191. }
  192. printf("\n");
  193. fflush(stdout);
  194. //pre-pend stream_id and length
  195. memmove(buffer+3, buffer, bytes_read+1);
  196. struct slitheen_up_hdr *up_hdr = (struct slitheen_up_hdr *) buffer;
  197. up_hdr->stream_id = stream_id;
  198. up_hdr->len = htons(bytes_read);
  199. bytes_read+= 3;
  200. //encode bytes for safe transport (b64)
  201. const char *encoded_bytes;
  202. BUF_MEM *buffer_ptr;
  203. BIO *bio, *b64;
  204. b64 = BIO_new(BIO_f_base64());
  205. bio = BIO_new(BIO_s_mem());
  206. bio = BIO_push(b64, bio);
  207. BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
  208. BIO_write(bio, buffer, bytes_read);
  209. BIO_flush(bio);
  210. BIO_get_mem_ptr(bio, &buffer_ptr);
  211. BIO_set_close(bio, BIO_NOCLOSE);
  212. BIO_free_all(bio);
  213. encoded_bytes = (*buffer_ptr).data;
  214. //send connect request to OUS
  215. int ous_in = open("OUS_in", O_CREAT | O_WRONLY, 0666);
  216. if(ous_in < 0){
  217. printf("Error opening file OUS_in\n");
  218. fflush(stdout);
  219. goto err;
  220. }
  221. lseek(ous_in, 0, SEEK_END);
  222. bytes_sent = write(ous_in, encoded_bytes, strlen(encoded_bytes));
  223. bytes_sent += write(ous_in, " ", 1);//space delimiter
  224. close(ous_in);
  225. if(bytes_sent < 0){
  226. printf("Error writing to named pipe\n");
  227. fflush(stdout);
  228. goto err;
  229. } else {
  230. printf("Wrote %d bytes to OUS_in:\n", bytes_sent);
  231. for(int i=0; i< bytes_read; i++){
  232. printf("%02x ",encoded_bytes[i]);
  233. }
  234. printf("\n");
  235. fflush(stdout);
  236. }
  237. p = buffer+sizeof(struct slitheen_up_hdr);
  238. for(int i=0; i< bytes_read; i++){
  239. printf("%02x ", p[i]);
  240. }
  241. printf("\n");
  242. fflush(stdout);
  243. struct socks_req *clnt_req = (struct socks_req *) p;
  244. p += 4;
  245. //see if it's a connect request
  246. if(clnt_req->cmd != 0x01){
  247. printf("Error: issued a non-connect command\n");
  248. fflush(stdout);
  249. goto err;
  250. }
  251. printf("Received a connect request from stream id %d\n", stream_id);
  252. fflush(stdout);
  253. //now select on pipe (for downstream data) and the socket (for upstream data)
  254. for(;;){
  255. fd_set readfds;
  256. fd_set writefds;
  257. int32_t nfds = (sockfd > ous_out) ? sockfd +1 : ous_out + 1;
  258. //if(sockfd > ous_out){
  259. // nfds = (sockfd > ous_in) ? sockfd +1 : ous_in + 1;
  260. //} else {
  261. // nfds = (ous_out > ous_in) ? ous_out +1 : ous_in + 1;
  262. //}
  263. FD_ZERO(&readfds);
  264. FD_ZERO(&writefds);
  265. FD_SET(sockfd, &readfds);
  266. FD_SET(ous_out, &readfds);
  267. FD_SET(sockfd, &writefds);
  268. //FD_SET(ous_in, &writefds);
  269. if(select(nfds, &readfds, &writefds, NULL, NULL) <0){
  270. printf("Select error\n");
  271. fflush(stdout);
  272. continue;
  273. }
  274. if(FD_ISSET(sockfd, &readfds)){// && FD_ISSET(ous_in, &writefds)){
  275. bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
  276. if (bytes_read < 0){
  277. printf("Error reading from socket (in for loop)\n");
  278. fflush(stdout);
  279. goto err;
  280. }
  281. if(bytes_read > 0){
  282. printf("Received %d data bytes from sockfd (id %d):\n", bytes_read, stream_id);
  283. for(int i=0; i< bytes_read; i++){
  284. printf("%02x ", buffer[i]);
  285. }
  286. printf("\n");
  287. fflush(stdout);
  288. memmove(buffer+sizeof(struct slitheen_up_hdr), buffer, bytes_read);
  289. up_hdr = (struct slitheen_up_hdr *) buffer;
  290. up_hdr->stream_id = stream_id;
  291. up_hdr->len = htons(bytes_read);
  292. bytes_read+= 3;
  293. bio = BIO_new(BIO_s_mem());
  294. b64 = BIO_new(BIO_f_base64());
  295. bio = BIO_push(b64, bio);
  296. printf("HERE\n");
  297. fflush(stdout);
  298. BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
  299. BIO_write(bio, buffer, bytes_read);
  300. BIO_flush(bio);
  301. BIO_get_mem_ptr(bio, &buffer_ptr);
  302. BIO_set_close(bio, BIO_NOCLOSE);
  303. BIO_free_all(bio);
  304. encoded_bytes = (*buffer_ptr).data;
  305. int ous_in = open("OUS_in", O_CREAT | O_WRONLY, 0666);
  306. if(ous_in < 0){
  307. printf("Error opening file OUS_in\n");
  308. fflush(stdout);
  309. goto err;
  310. }
  311. lseek(ous_in, 0, SEEK_END);
  312. bytes_sent = write(ous_in, encoded_bytes, strlen(encoded_bytes));
  313. bytes_sent += write(ous_in, " ", 1);//space delimiter
  314. close(ous_in);
  315. printf("Sent to OUS (%d bytes):%s\n",bytes_sent, encoded_bytes );
  316. fflush(stdout);
  317. }
  318. } else if(FD_ISSET(ous_out, &readfds) && FD_ISSET(sockfd, &writefds)){
  319. bytes_read = read(ous_out, buffer, BUFSIZ-1);
  320. if (bytes_read < 0){
  321. printf("Error reading from ous_out (in for loop)\n");
  322. fflush(stdout);
  323. goto err;
  324. }
  325. if(bytes_read > 0){
  326. printf("Stream id %d received %d bytes from ous_out:\n", stream_id, bytes_read);
  327. for(int i=0; i< bytes_read; i++){
  328. printf("%02x ", buffer[i]);
  329. }
  330. printf("\n");
  331. fflush(stdout);
  332. bytes_sent = send(sockfd, buffer, bytes_read, 0);
  333. printf("Sent to browser (%d bytes):\n", bytes_sent);
  334. for(int i=0; i< bytes_sent; i++){
  335. printf("%02x ", buffer[i]);
  336. }
  337. printf("\n");
  338. fflush(stdout);
  339. }
  340. }
  341. }
  342. err:
  343. close(sockfd);
  344. free(buffer);
  345. free(response);
  346. exit(0);
  347. }
  348. void *demultiplex_data(){
  349. int32_t buffer_len = BUFSIZ;
  350. uint8_t *buffer = calloc(1, buffer_len);
  351. uint8_t *p;
  352. printf("Opening OUS_out\n");
  353. int32_t ous_fd = open("OUS_out", O_RDONLY);
  354. printf("Opened.\n");
  355. uint8_t *overflow;
  356. uint32_t overflow_len = 0;
  357. for(;;){
  358. int32_t bytes_read = read(ous_fd, buffer, buffer_len-overflow_len);
  359. if(bytes_read > 0){
  360. int32_t bytes_remaining = bytes_read;
  361. if(overflow_len > 0){
  362. //process first part of slitheen info
  363. memmove(buffer+overflow_len, buffer, bytes_read);
  364. memcpy(buffer, overflow, overflow_len);
  365. bytes_remaining += overflow_len;
  366. free(overflow);
  367. overflow_len = 0;
  368. }
  369. p = buffer;
  370. while(bytes_remaining > 0){
  371. struct slitheen_hdr *sl_hdr = (struct slitheen_hdr *) p;
  372. if(ntohs(sl_hdr->len)+ sizeof(struct slitheen_hdr) > bytes_remaining){
  373. overflow = calloc(1, bytes_remaining);
  374. memcpy(overflow, p, bytes_remaining);
  375. overflow_len = bytes_remaining;
  376. bytes_remaining = 0;
  377. break;
  378. }
  379. p += sizeof(struct slitheen_hdr);
  380. if(sl_hdr->garbage_len == 0){
  381. printf("Received information for stream id: %d of length: %u\n", sl_hdr->stream_id, ntohs(sl_hdr->len));
  382. int32_t pipe_fd =-1;
  383. if(connections->first == NULL){
  384. printf("There are no connections\n");
  385. } else {
  386. printf("First connection was at %p\n", connections->first);
  387. connection *last = connections->first;
  388. if (last->stream_id == sl_hdr->stream_id){
  389. printf("Found stream id %d!\n", sl_hdr->stream_id);
  390. pipe_fd = last->pipe_fd;
  391. printf("Pipe fd: %d\n", pipe_fd);
  392. }
  393. while(last->next != NULL){
  394. last = last->next;
  395. printf("Next connection was at %p\n", last);
  396. if (last->stream_id == sl_hdr->stream_id){
  397. printf("Found stream id %d!\n", sl_hdr->stream_id);
  398. pipe_fd = last->pipe_fd;
  399. printf("Pipe fd: %d\n", pipe_fd);
  400. }
  401. }
  402. }
  403. if(pipe_fd == -1){
  404. printf("No stream id exists\n");
  405. } else {
  406. int32_t bytes_sent = write(pipe_fd, p, ntohs(sl_hdr->len));
  407. if(bytes_sent < 0){
  408. printf("Error reading to pipe for stream id %d\n", sl_hdr->stream_id);
  409. }
  410. }
  411. }
  412. p += ntohs(sl_hdr->len);
  413. bytes_remaining -= sizeof(struct slitheen_hdr) + ntohs(sl_hdr->len);
  414. }
  415. } else {
  416. printf("Error: read %d bytes from OUS_out\n", bytes_read);
  417. printf("Opening OUS_out\n");
  418. close(ous_fd);
  419. ous_fd = open("OUS_out", O_RDONLY);
  420. printf("Opened.\n");
  421. }
  422. }
  423. close(ous_fd);
  424. }