() () #include #include #include #include #include #include #include #include #include #include #include #include extern int forward(int, int); static void signal_handler(int sig) { if(sig != SIGCHLD) return; while(waitpid(-1, NULL, WNOHANG) < 0) { if(errno == EINTR) continue; perror("waitpid"); return; } } static void start_mirror_port(const struct iphdr *iph, struct tcphdr *tcph) { static struct in_addr last_source_in_addr; static uint16_t last_dest_port; static unsigned int repeat_count; struct in_addr source_in_addr = { iph->saddr }; struct in_addr dest_in_addr = { iph->daddr }; char source_address[16], dest_address[16]; fprintf(stderr, "TCP SYN & AckSeq=0 received from %s:%hu to %s:%hu0, inet_ntop(AF_INET, &source_in_addr, source_address, sizeof source_address), ntohs(tcph->source), inet_ntop(AF_INET, &dest_in_addr, dest_address, sizeof dest_address), ntohs(tcph->dest)); if(memcmp(&last_source_in_addr, &source_in_addr, sizeof source_in_addr) == 0 && last_dest_port == tcph->dest) { if(repeat_count > 8) { fprintf(stderr, "Too many request from host %s to port %d0, inet_ntop(AF_INET, &source_in_addr, source_address, sizeof source_address), ntohs(tcph->dest)); return; } repeat_count++; } else { last_source_in_addr = source_in_addr; last_dest_port = tcph->dest; repeat_count = 0; } pid_t pid = fork(); if(pid < 0) { perror("fork"); return; } if(pid) return; // child int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(fd == -1) { perror("socket: AF_INET,SOCK_STREAM,IPPROTO_TCP"); _exit(1); } struct sockaddr_in connect_addr = { .sin_family = AF_INET, .sin_addr = source_in_addr, .sin_port = tcph->dest }; while(connect(fd, (struct sockaddr *)&connect_addr, sizeof connect_addr) < 0) { if(errno == EINTR) continue; perror("connect"); close(fd); _exit(1); } int listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(listen_fd == -1) { perror("socket: AF_INET,SOCK_STREAM,IPPROTO_TCP"); close(fd); _exit(1); } int reuseaddr = 1; if(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof reuseaddr) < 0) perror("setsockopt"); struct sockaddr_in listen_addr = { .sin_family = AF_INET, //.sin_addr.s_addr = htonl(INADDR_ANY), .sin_addr = dest_in_addr, .sin_port = tcph->dest }; while(bind(listen_fd, (struct sockaddr *)&listen_addr, sizeof listen_addr) < 0) { if(errno == EINTR) continue; perror("bind"); goto fail; } if(listen(listen_fd, 1) < 0) { perror("listen"); goto fail; } fd_set fdset; FD_ZERO(&fdset); FD_SET(listen_fd, &fdset); struct timeval timeout = { .tv_sec = 10 }; switch(select(listen_fd + 1, &fdset, NULL, NULL, &timeout)) { case -1: perror("select"); goto fail; case 0: close(fd); close(listen_fd); _exit(1); } int afd; struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof client_addr; do { afd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_addr_len); } while(afd == -1 && errno == EINTR); if(afd == -1) { perror("accept"); goto fail; } fprintf(stderr, "Accepted connection from %s port %hu to port %hu0, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), ntohs(listen_addr.sin_port)); _exit(forward(fd, afd) < 0 ? 1 : 0); fail: close(fd); close(listen_fd); _exit(1); } int main(int argc, char **argv) { int begin_port = -1, end_port = -1; // host endian uint16_t *exclude_ports = NULL; // network endian size_t exclude_ports_count = 0, exclude_ports_allocated_size = 0; if(argc < 2) { fprintf(stderr, "Usage: %s [] [...]0, argv[0]); return -1; } char *dash = strchr(argv[1], '-'); if(dash) { *dash = 0; begin_port = atoi(argv[1]); end_port = atoi(dash + 1); } else { begin_port = end_port = atoi(argv[1]); } if(begin_port < 1 || end_port < 1) { fprintf(stderr, "%s: Port number must be greater than 00, argv[0]); return -1; } char **v = argv + 2; while(*v) { if(exclude_ports_count * sizeof(uint16_t) >= exclude_ports_allocated_size) { exclude_ports = realloc(exclude_ports, exclude_ports_allocated_size += 2 * sizeof(uint16_t)); if(!exclude_ports) { perror("realloc"); return 1; } } int port = atoi(*v++); if(port < 1) { fprintf(stderr, "%s: Port number must be greater than 00, argv[0]); return -1; } //exclude_ports[exclude_ports_count++] = atoi(*v++); exclude_ports[exclude_ports_count++] = htons(port); } //unsigned char *buffer = (unsigned char *)malloc(65536); //Its Big! unsigned char buffer[16384]; //struct sigaction act = { .sa_handler = singal_hander }; struct sigaction act = { .sa_handler = SIG_IGN }; if(sigaction(SIGPIPE, &act, NULL) < 0) { perror("sigaction"); return 1; } act.sa_handler = signal_handler; sigaction(SIGCHLD, &act, NULL); setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IONBF, 0); int fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); if(fd == -1) { perror("socket: AF_INET,SOCK_RAW,IPPROTO_TCP"); return 1; } struct sockaddr source_addr; socklen_t source_addr_len; int s, i; while(1) { first_loop: source_addr_len = sizeof source_addr; s = recvfrom(fd, buffer, sizeof buffer, 0 , &source_addr, &source_addr_len); if(s < 0) { if(errno == EINTR) continue; perror("recvfrom"); return 1; } struct iphdr *iph = (struct iphdr*)buffer; if(iph->protocol != 6) continue; unsigned short int iphdr_len = iph->ihl * 4; struct tcphdr *tcph = (struct tcphdr*)(buffer + iphdr_len); if((iph->saddr & 0xffffff) == 0x7f || (iph->daddr & 0xffffff) == 0x7f) continue; if(ntohs(tcph->dest) < begin_port || ntohs(tcph->dest) > end_port) continue; for(i=0; idest == exclude_ports[i]) goto first_loop; if(!tcph->syn || tcph->ack_seq) continue; start_mirror_port(iph, tcph); usleep(100000); } } August 31, 2025 ()