版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明。
https://windtear.net/archives/2004/03/23/000344.html
datapipe.sh 其实是iptables 只不过模仿 datapipe.c 的样子占山为王自称 datapipe.sh
-----> datapipe.sh #!/bin/bash # # Setup a DataPipe # By Zhang Xiuling (windtear@ipcn.org) #
LOCALIP=166.111.154.35 LOCALPORT=8080 REMOTEIP=10.35.0.1 REMOTEPORT=8080 IPTABLES=/sbin/iptables
usage() { FILENAME=`basename $0` echo echo "Setup a DataPipe" echo " By Zhang Xiuling (windtear@ipcn.org)" echo echo "usage: $FILENAME [LOCALIP] [LOCALPORT] [REMOTEIP] [REMOTEPORT]" echo echo "Example:" echo " $FILENAME 166.111.154.35 8080 10.35.0.1 8080" echo exit }
if [ "$1" == "-h" -o "$1" == "-?" -o "$1" == "--help" ]; then usage else LOCALIP=${1:-$LOCALIP} LOCALPORT=${2:-$LOCALPORT} REMOTEIP=${3:-$REMOTEIP} REMOTEPORT=${4:-$REMOTEPORT} fi
$IPTABLES -t nat -I PREROUTING -d $LOCALIP -p tcp --dport $LOCALPORT -j DNAT --to $REMOTEIP:$REMOTEPORT $IPTABLES -t nat -I POSTROUTING -d $REMOTEIP -p tcp --dport $REMOTEPORT -j SNAT --to $LOCALIP
-----> datapipe.c
/* * Datapipe - Create a listen socket to pipe connections to another * machine/port. 'localport' accepts connections on the machine running * datapipe, which will connect to 'remoteport' on 'remotehost'. * It will fork itself into the background on non-Windows machines. * * This implementation of the traditional "datapipe" does not depend on * forking to handle multiple simultaneous clients, and instead is able * to do all processing from within a single process, making it ideal * for low-memory environments. The elimination of the fork also * allows it to be used in environments without fork, such as Win32. * * This implementation also differs from most others in that it allows * the specific IP address of the interface to listen on to be specified. * This is useful for machines that have multiple IP addresses. The * specified listening address will also be used for making the outgoing * connections on. * * Note that select() is not used to perform writability testing on the * outgoing sockets, so conceivably other connections might have delayed * responses if any of the connected clients or the connection to the * target machine is slow enough to allow its outgoing buffer to fill * to capacity. * * Compile with: * cc -O -o datapipe datapipe.c * On Solaris/SunOS, compile with: * gcc -Wall datapipe.c -lsocket -lnsl -o datapipe * On Windows compile with: * bcc32 /w datapipe.c (Borland C++) * cl /W3 datapipe.c wsock32.lib (Microsoft Visual C++) * * Run as: * datapipe localhost localport remoteport remotehost * * * written by Jeff Lawson <jlawson@bovine.net> * inspired by code originally by Todd Vierling, 1995. */
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <time.h> #if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include <winsock.h> #define bzero(p, l) memset(p, 0, l) #define bcopy(s, t, l) memmove(t, s, l) #else #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <netdb.h> #include <strings.h> #define recv(x,y,z,a) read(x,y,z) #define send(x,y,z,a) write(x,y,z) #define closesocket(s) close(s) typedef int SOCKET; #endif
#ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif
struct client_t { int inuse; SOCKET csock, osock; time_t activity; };
#define MAXCLIENTS 60 #define IDLETIMEOUT 900
const char ident[] = "$Id: datapipe.c,v 1.8 1999/01/29 01:21:54 jlawson Exp $";
int main(int argc, char *argv[]) { SOCKET lsock; char buf[4096]; struct sockaddr_in laddr, oaddr; int i; struct client_t clients[MAXCLIENTS];
#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) /* Winsock needs additional startup activities */ WSADATA wsadata; WSAStartup(MAKEWORD(1,1), &wsadata); #endif
/* check number of command line arguments */ if (argc != 5) { fprintf(stderr,"Usage: %s localhost localport remotehost remoteport\n",argv[0]); return 30; }
/* reset all of the client structures */ for (i = 0; i < MAXCLIENTS; i++) clients[i].inuse = 0;
/* determine the listener address and port */ bzero(&laddr, sizeof(struct sockaddr_in)); laddr.sin_family = AF_INET; laddr.sin_port = htons((unsigned short) atol(argv[2])); laddr.sin_addr.s_addr = inet_addr(argv[1]); if (!laddr.sin_port) { fprintf(stderr, "invalid listener port\n"); return 20; } if (laddr.sin_addr.s_addr == INADDR_NONE) { struct hostent *n; if ((n = gethostbyname(argv[1])) == NULL) { perror("gethostbyname"); return 20; } bcopy(n->h_addr, (char *) &laddr.sin_addr, n->h_length); }
/* determine the outgoing address and port */ bzero(&oaddr, sizeof(struct sockaddr_in)); oaddr.sin_family = AF_INET; oaddr.sin_port = htons((unsigned short) atol(argv[4])); if (!oaddr.sin_port) { fprintf(stderr, "invalid target port\n"); return 25; } oaddr.sin_addr.s_addr = inet_addr(argv[3]); if (oaddr.sin_addr.s_addr == INADDR_NONE) { struct hostent *n; if ((n = gethostbyname(argv[3])) == NULL) { perror("gethostbyname"); return 25; } bcopy(n->h_addr, (char *) &oaddr.sin_addr, n->h_length); }
/* create the listener socket */ if ((lsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); return 20; } if (bind(lsock, (struct sockaddr *)&laddr, sizeof(laddr))) { perror("bind"); return 20; } if (listen(lsock, 5)) { perror("listen"); return 20; }
/* change the port in the listener struct to zero, since we will * use it for binding to outgoing local sockets in the future. */ laddr.sin_port = htons(0);
/* fork off into the background. */ #if !defined(__WIN32__) && !defined(WIN32) && !defined(_WIN32) if ((i = fork()) == -1) { perror("fork"); return 20; } if (i > 0) return 0; setsid(); #endif
/* main polling loop. */ while (1) { fd_set fdsr; int maxsock; struct timeval tv = {1,0}; time_t now = time(NULL);
/* build the list of sockets to check. */ FD_ZERO(&fdsr); FD_SET(lsock, &fdsr); maxsock = (int) lsock; for (i = 0; i < MAXCLIENTS; i++) if (clients[i].inuse) { FD_SET(clients[i].csock, &fdsr); if ((int) clients[i].csock > maxsock) maxsock = (int) clients[i].csock; FD_SET(clients[i].osock, &fdsr); if ((int) clients[i].osock > maxsock) maxsock = (int) clients[i].osock; } if (select(maxsock + 1, &fdsr, NULL, NULL, &tv) < 0) { return 30; }
/* check if there are new connections to accept. */ if (FD_ISSET(lsock, &fdsr)) { SOCKET csock = accept(lsock, NULL, 0); for (i = 0; i < MAXCLIENTS; i++) if (!clients[i].inuse) break; if (i < MAXCLIENTS) { /* connect a socket to the outgoing host/port */ SOCKET osock; if ((osock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); closesocket(csock); } else if (bind(osock, (struct sockaddr *)&laddr, sizeof(laddr))) { perror("bind"); closesocket(csock); closesocket(osock); } else if (connect(osock, (struct sockaddr *)&oaddr, sizeof(oaddr))) { perror("connect"); closesocket(csock); closesocket(osock); } else { clients[i].osock = osock; clients[i].csock = csock; clients[i].activity = now; clients[i].inuse = 1; } } else { fprintf(stderr, "too many clients\n"); closesocket(csock); } }
/* service any client connections that have waiting data. */ for (i = 0; i < MAXCLIENTS; i++) { int nbyt, closeneeded = 0; if (!clients[i].inuse) { continue; } else if (FD_ISSET(clients[i].csock, &fdsr)) { if ((nbyt = recv(clients[i].csock, buf, sizeof(buf), 0)) <= 0 || send(clients[i].osock, buf, nbyt, 0) <= 0) closeneeded = 1; else clients[i].activity = now; } else if (FD_ISSET(clients[i].osock, &fdsr)) { if ((nbyt = recv(clients[i].osock, buf, sizeof(buf), 0)) <= 0 || send(clients[i].csock, buf, nbyt, 0) <= 0) closeneeded = 1; else clients[i].activity = now; } else if (now - clients[i].activity > IDLETIMEOUT) { closeneeded = 1; } if (closeneeded) { closesocket(clients[i].csock); closesocket(clients[i].osock); clients[i].inuse = 0; } } } return 0; }
|
|