This is the Windows version of TCP Proxy.
/* * A simple TCP proxy for Windows * by Martin Broadhurst (www.martinbroadhurst.com) * Link with Ws2_32.lib * Usage: tcpproxy local_host local_port remote_host remote_port */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #define _WINSOCK_DEPRECATED_NO_WARNINGS /* inet_ntoa */ #include <stdio.h> #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #define BACKLOG 10 /* Passed to listen() */ #define BUF_SIZE 4096 /* Buffer for transfers */ unsigned int transfer(SOCKET from, SOCKET to) { char buf[BUF_SIZE]; unsigned int disconnected = 0; size_t bytes_read, bytes_written; bytes_read = recv(from, buf, BUF_SIZE, 0); if (bytes_read == 0) { disconnected = 1; } else { bytes_written = send(to, buf, bytes_read, 0); if (bytes_written == -1) { disconnected = 1; } } return disconnected; } void handle(SOCKET client, const char *remote_host, const char *remote_port) { struct addrinfo hints, *res; SOCKET server = -1; unsigned int disconnected = 0; fd_set set; unsigned int max_sock; /* Get the address info */ ZeroMemory(&hints, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(remote_host, remote_port, &hints, &res) != 0) { perror("getaddrinfo"); closesocket(client); return; } /* Create the socket */ server = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (server == INVALID_SOCKET) { perror("socket"); closesocket(client); return; } /* Connect to the host */ if (connect(server, res->ai_addr, res->ai_addrlen) == -1) { perror("connect"); closesocket(client); return; } if (client > server) { max_sock = client; } else { max_sock = server; } /* Main transfer loop */ while (!disconnected) { FD_ZERO(&set); FD_SET(client, &set); FD_SET(server, &set); if (select(max_sock + 1, &set, NULL, NULL, NULL) == SOCKET_ERROR) { perror("select"); break; } if (FD_ISSET(client, &set)) { disconnected = transfer(client, server); } if (FD_ISSET(server, &set)) { disconnected = transfer(server, client); } } if (server != -1) { closesocket(server); } closesocket(client); } int main(int argc, char **argv) { WORD wVersion = MAKEWORD(2, 2); WSADATA wsaData; int iResult; SOCKET sock; struct addrinfo hints, *res; int reuseaddr = 1; /* True */ const char *local_host, *local_port, *remote_host, *remote_port; /* Initialise Winsock */ if (iResult = (WSAStartup(wVersion, &wsaData)) != 0) { fprintf(stderr, "WSAStartup failed: %d\n", iResult); return 1; } /* Get the local and remote hosts and ports from the command line */ if (argc < 5) { fprintf(stderr, "Usage: tcpproxy local_host local_port remote_host remote_port\n"); return 1; } local_host = argv[1]; local_port = argv[2]; remote_host = argv[3]; remote_port = argv[4]; /* Get the address info */ ZeroMemory(&hints, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(local_host, local_port, &hints, &res) != 0) { perror("getaddrinfo"); WSACleanup(); return 1; } /* Create the socket */ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock == INVALID_SOCKET) { perror("socket"); WSACleanup(); return 1; } /* Enable the socket to reuse the address */ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, sizeof(int)) == SOCKET_ERROR) { perror("setsockopt"); WSACleanup(); return 1; } /* Bind to the address */ if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) { perror("bind"); WSACleanup(); return 1; } /* Listen */ if (listen(sock, BACKLOG) == SOCKET_ERROR) { perror("listen"); WSACleanup(); return 1; } freeaddrinfo(res); /* Main loop */ while (1) { size_t size = sizeof(struct sockaddr_in); struct sockaddr_in their_addr; int newsock = accept(sock, (struct sockaddr*)&their_addr, &size); if (newsock == INVALID_SOCKET) { perror("accept"); } else { printf("Got a connection from %s on port %d\n", inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port)); handle(newsock, remote_host, remote_port); } } closesocket(sock); WSACleanup(); return 0; }