BitTheByte

desock.c

Jan 25th, 2021
335
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.76 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <netinet/in.h>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <pthread.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <signal.h>
  11. #include <dlfcn.h>
  12. #include <errno.h>
  13. #include <stdio.h>
  14. #include <poll.h>
  15.  
  16.  
  17. #define PREENY_MAX_FD 8192
  18. #define PREENY_SOCKET_OFFSET 500
  19. #define READ_BUF_SIZE 65536
  20.  
  21. #define PREENY_SIN_PORT 9000
  22.  
  23. #define PREENY_SOCKET(x) (x+PREENY_SOCKET_OFFSET)
  24.  
  25.  
  26. //********************************************************************************************//
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31.  
  32. int preeny_debug_on =0;
  33. int preeny_info_on  =0;
  34. int preeny_error_on =0;
  35.  
  36. void preeny_debug(char *fmt, ...)
  37. {
  38.     if (!preeny_debug_on) return;
  39.  
  40.     printf("+++ ");
  41.     va_list args;
  42.     va_start(args,fmt);
  43.     vprintf(fmt,args);
  44.     va_end(args);
  45.  
  46.     fflush(stdout);
  47. }
  48.  
  49. void preeny_info(char *fmt, ...)
  50. {
  51.     if (!preeny_info_on) return;
  52.  
  53.     printf("--- ");
  54.     va_list args;
  55.     va_start(args,fmt);
  56.     vprintf(fmt,args);
  57.     va_end(args);
  58.  
  59.     fflush(stdout);
  60. }
  61.  
  62. void preeny_error(char *fmt, ...)
  63. {
  64.     if (!preeny_error_on) return;
  65.  
  66.     fprintf(stderr, "!!! ERROR: ");
  67.     va_list args;
  68.     va_start(args,fmt);
  69.     vfprintf(stderr, fmt,args);
  70.     va_end(args);
  71.  
  72.     fflush(stderr);
  73. }
  74. //********************************************************************************************//
  75.  
  76. int preeny_desock_shutdown_flag = 0;
  77. int preeny_desock_accepted_sock = -1;
  78.  
  79. pthread_t *preeny_socket_threads_to_front[PREENY_MAX_FD] = { 0 };
  80. pthread_t *preeny_socket_threads_to_back[PREENY_MAX_FD] = { 0 };
  81.  
  82. int preeny_socket_sync(int from, int to, int timeout)
  83. {
  84.     struct pollfd poll_in = { from, POLLIN, 0 };
  85.     char read_buf[READ_BUF_SIZE];
  86.     int total_n;
  87.     char error_buf[1024];
  88.     int n;
  89.     int r;
  90.  
  91.     r = poll(&poll_in, 1, timeout);
  92.     if (r < 0)
  93.     {
  94.         strerror_r(errno, error_buf, 1024);
  95.         preeny_debug("read poll() received error '%s' on fd %d\n", error_buf, from);
  96.         return 0;
  97.     }
  98.     else if (poll_in.revents == 0)
  99.     {
  100.         preeny_debug("read poll() timed out on fd %d\n", from);
  101.         return 0;
  102.     }
  103.  
  104.     total_n = read(from, read_buf, READ_BUF_SIZE);
  105.     if (total_n < 0)
  106.     {
  107.         strerror_r(errno, error_buf, 1024);
  108.         preeny_info("synchronization of fd %d to %d shutting down due to read error '%s'\n", from, to, error_buf);
  109.         return -1;
  110.     }
  111.     else if (total_n == 0 && from == 0)
  112.     {
  113.         preeny_info("synchronization of fd %d to %d shutting down due to EOF\n", from, to);
  114.         return -1;
  115.     }
  116.     preeny_debug("read %d bytes from %d (will write to %d)\n", total_n, from, to);
  117.  
  118.     n = 0;
  119.     while (n != total_n)
  120.     {
  121.         r = write(to, read_buf, total_n - n);
  122.         if (r < 0)
  123.         {
  124.             strerror_r(errno, error_buf, 1024);
  125.             preeny_info("synchronization of fd %d to %d shutting down due to read error '%s'\n", from, to, error_buf);
  126.             return -1;
  127.         }
  128.         n += r;
  129.     }
  130.  
  131.     preeny_debug("wrote %d bytes to %d (had read from %d)\n", total_n, to, from);
  132.     return total_n;
  133. }
  134.  
  135. __attribute__((destructor)) void preeny_desock_shutdown()
  136. {
  137.     int i;
  138.     int to_sync[PREENY_MAX_FD] = { };
  139.  
  140.     preeny_debug("shutting down desock...\n");
  141.     preeny_desock_shutdown_flag = 1;
  142.  
  143.  
  144.     for (i = 0; i < PREENY_MAX_FD; i++)
  145.     {
  146.         if (preeny_socket_threads_to_front[i])
  147.         {
  148.             preeny_debug("sending SIGINT to thread %d...\n", i);
  149.             pthread_join(*preeny_socket_threads_to_front[i], NULL);
  150.             pthread_join(*preeny_socket_threads_to_back[i], NULL);
  151.             preeny_debug("... sent!\n");
  152.             to_sync[i] = 1;
  153.         }
  154.     }
  155.  
  156.     for (i = 0; i < PREENY_MAX_FD; i++)
  157.     {
  158.         if (to_sync[i])
  159.         {
  160.             //while (preeny_socket_sync(0, PREENY_SOCKET(i), 10) > 0);
  161.             while (preeny_socket_sync(PREENY_SOCKET(i), 1, 0) > 0);
  162.         }
  163.     }
  164.  
  165.     preeny_debug("... shutdown complete!\n");
  166. }
  167.  
  168. void preeny_socket_sync_loop(int from, int to)
  169. {
  170.     int r;
  171.  
  172.     preeny_debug("starting forwarding from %d to %d!\n", from, to);
  173.  
  174.     while (!preeny_desock_shutdown_flag)
  175.     {
  176.         r = preeny_socket_sync(from, to, 15);
  177.         if (r < 0) return;
  178.     }
  179. }
  180.  
  181. #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
  182. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  183.  
  184. void *preeny_socket_sync_to_back(void *fd)
  185. {
  186.     int front_fd = (int)fd;
  187.     int back_fd = PREENY_SOCKET(front_fd);
  188.     preeny_socket_sync_loop(back_fd, 1);
  189.     return NULL;
  190. }
  191.  
  192. void *preeny_socket_sync_to_front(void *fd)
  193. {
  194.     int front_fd = (int)fd;
  195.     int back_fd = PREENY_SOCKET(front_fd);
  196.     preeny_socket_sync_loop(0, back_fd);
  197.     shutdown(back_fd, SHUT_WR);
  198.     return NULL;
  199. }
  200.  
  201. //
  202. // originals
  203. //
  204. int (*original_socket)(int, int, int);
  205. int (*original_bind)(int, const struct sockaddr *, socklen_t);
  206. int (*original_listen)(int, int);
  207. int (*original_accept)(int, struct sockaddr *, socklen_t *);
  208. int (*original_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  209. int (*original_close)(int fd);
  210. int (*original_shutdown)(int sockfd, int how);
  211. int (*original_getsockname)(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  212. __attribute__((constructor)) void preeny_desock_orig()
  213. {
  214.     original_socket = dlsym(RTLD_NEXT, "socket");
  215.     original_listen = dlsym(RTLD_NEXT, "listen");
  216.     original_accept = dlsym(RTLD_NEXT, "accept");
  217.     original_bind = dlsym(RTLD_NEXT, "bind");
  218.     original_connect = dlsym(RTLD_NEXT, "connect");
  219.     original_close = dlsym(RTLD_NEXT, "close");
  220.     original_shutdown = dlsym(RTLD_NEXT, "shutdown");
  221.     original_getsockname = dlsym(RTLD_NEXT, "getsockname");
  222.    
  223. }
  224.  
  225. int fcntl(int fd, int cmd, ... /* arg */ ){
  226.     return 0;
  227. }
  228. int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen){
  229.     return 0;
  230. }
  231.  
  232. ssize_t recv(int sockfd, void *buf, size_t len, int flags){
  233.     FILE *fp = fopen("/tmp/input", "r");
  234.     int data_size = 0;
  235.     if(fp != NULL)
  236.     {
  237.         int symbol = 0;
  238.         while((symbol = getc(fp)) != EOF)
  239.         {
  240.             if (data_size == len){
  241.                 break;
  242.             }
  243.             strcat(buf, &symbol);
  244.             data_size+= 1;
  245.         }
  246.         fclose(fp);
  247.     }
  248.     return strlen(buf);
  249. }
  250.  
  251.  
  252. int socket(int domain, int type, int protocol)
  253. {
  254.     int fds[2];
  255.     int front_socket;
  256.     int back_socket;
  257.  
  258.     if (domain != AF_INET && domain != AF_INET6)
  259.     {
  260.         preeny_info("Ignoring non-internet socket.");
  261.         return original_socket(domain, type, protocol);
  262.     }
  263.    
  264.     int r = socketpair(AF_UNIX, type, 0, fds);
  265.     preeny_debug("Intercepted socket()!\n");
  266.  
  267.     if (r != 0)
  268.     {
  269.         perror("preeny socket emulation failed:");
  270.         return -1;
  271.     }
  272.  
  273.     preeny_debug("... created socket pair (%d, %d)\n", fds[0], fds[1]);
  274.  
  275.     front_socket = fds[0];
  276.     back_socket = dup2(fds[1], PREENY_SOCKET(front_socket));
  277.     close(fds[1]);
  278.  
  279.     preeny_debug("... dup into socketpair (%d, %d)\n", fds[0], back_socket);
  280.  
  281.     preeny_socket_threads_to_front[fds[0]] = malloc(sizeof(pthread_t));
  282.     preeny_socket_threads_to_back[fds[0]] = malloc(sizeof(pthread_t));
  283.  
  284.     r = pthread_create(preeny_socket_threads_to_front[fds[0]], NULL, (void*(*)(void*))preeny_socket_sync_to_front, (void *)front_socket);
  285.     if (r)
  286.     {
  287.         perror("failed creating front-sync thread");
  288.         return -1;
  289.     }
  290.  
  291.     r = pthread_create(preeny_socket_threads_to_back[fds[0]], NULL, (void*(*)(void*))preeny_socket_sync_to_back, (void *)front_socket);
  292.     if (r)
  293.     {
  294.         perror("failed creating back-sync thread");
  295.         return -1;
  296.     }
  297.  
  298.     return fds[0];
  299. }
  300.  
  301. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
  302. {
  303.     if (preeny_desock_accepted_sock >= 0)
  304.     {
  305.                 errno = ECONNRESET;
  306.         return -1;
  307.     }
  308.  
  309.     //initialize a sockaddr_in for the peer
  310.      struct sockaddr_in peer_addr;
  311.      memset(&peer_addr, '0', sizeof(struct sockaddr_in));
  312.  
  313.     //Set the contents in the peer's sock_addr.
  314.     //Make sure the contents will simulate a real client that connects with the intercepted server, as the server may depend on the contents to make further decisions.
  315.     //The followings set-up should be fine with Nginx.
  316.      peer_addr.sin_family = AF_INET;
  317.      peer_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  318.          peer_addr.sin_port = htons(PREENY_SIN_PORT);
  319.  
  320.     //copy the initialized peer_addr back to the original sockaddr. Note the space for the original sockaddr, namely addr, has already been allocated
  321.     if (addr) memcpy(addr, &peer_addr, sizeof(struct sockaddr_in));
  322.  
  323.     if (preeny_socket_threads_to_front[sockfd])
  324.     {
  325.         preeny_desock_accepted_sock = dup(sockfd);
  326.         return preeny_desock_accepted_sock;
  327.     }
  328.     else return original_accept(sockfd, addr, addrlen);
  329. }
  330.  
  331. int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
  332. {
  333.        return accept(sockfd, addr, addrlen);
  334. }
  335.  
  336. int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
  337. {
  338.     if (preeny_socket_threads_to_front[sockfd])
  339.     {
  340.         preeny_info("Emulating bind on port %d\n", ntohs(((struct sockaddr_in*)addr)->sin_port));
  341.         return 0;
  342.     }
  343.     else
  344.     {
  345.         return original_bind(sockfd, addr, addrlen);
  346.     }
  347. }
  348.  
  349. int listen(int sockfd, int backlog)
  350. {
  351.     if (preeny_socket_threads_to_front[sockfd]) return 0;
  352.     else return original_listen(sockfd, backlog);
  353. }
  354.  
  355. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
  356. {
  357.     if (preeny_socket_threads_to_front[sockfd]) return 0;
  358.     else return original_connect(sockfd, addr, addrlen);
  359. }
  360.  
  361. int close(int fd) {
  362.     if (preeny_desock_accepted_sock != -1 && preeny_desock_accepted_sock == fd)
  363.         exit(0);
  364.  
  365.     return original_close(fd);
  366. }
  367.  
  368. int shutdown(int sockfd, int how) {
  369.     if (preeny_desock_accepted_sock != -1 && preeny_desock_accepted_sock == sockfd)
  370.         exit(0);
  371.  
  372.     return original_shutdown(sockfd, how);
  373. }
  374.  
  375. int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
  376.     struct sockaddr_in target;
  377.     socklen_t copylen = sizeof(target);
  378.  
  379.     if (!preeny_socket_threads_to_front[sockfd])
  380.         return original_getsockname(sockfd, addr, addrlen);
  381.  
  382.     if (!addr || !addrlen)
  383.         return -1;
  384.  
  385.     if (*addrlen < sizeof(target))
  386.         copylen = *addrlen;
  387.  
  388.     target.sin_family = AF_INET;
  389.     target.sin_addr.s_addr = htonl(INADDR_ANY);
  390.     target.sin_port = htons(PREENY_SIN_PORT);
  391.  
  392.     memcpy(addr, &target, copylen);
  393.     *addrlen = copylen;
  394.  
  395.     return 0;
  396. }
  397.  
Advertisement
Add Comment
Please, Sign In to add comment