#include #include #include #include #include #include #include #include #ifndef IP_TRANSPARENT #define IP_TRANSPARENT 19 #endif #ifndef SO_ORIGINAL_DST #define SO_ORIGINAL_DST 80 #endif #define USE_TRANSPARENT_TO_SERVER int sfd; struct timeval cur_microtime; #define GET_MICROTIME(str) gettimeofday(&cur_microtime,NULL);printf("%s %d.%d\n",str,cur_microtime.tv_sec,cur_microtime.tv_usec); int create_listen_socket(){ struct sockaddr_in in_addr; int flags=1; if((sfd = socket(AF_INET, SOCK_STREAM, 0))==-1){ perror("AF_INET socket()- failed"); return -1; } setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags)); if(setsockopt(sfd, SOL_IP, IP_TRANSPARENT, &flags, sizeof(int)) == -1){ perror("Server-setsockopt() IP_TRANSPARENT error!"); return -1; }else{ printf("Server-setsockopt IP_TRANSPARENT is OK...\n"); } memset(&in_addr, 0, sizeof(struct sockaddr_in)); in_addr.sin_family = AF_INET; in_addr.sin_port = htons(3200); in_addr.sin_addr.s_addr = inet_addr("0.0.0.0"); if(bind(sfd, (struct sockaddr *) &in_addr, sizeof(in_addr)) == -1) { perror("Bind AF_INET socket failed\n"); close(sfd); return -1; } if(listen(sfd, 8192) == -1) { perror("Listen AF_INET socket failed\n"); close(sfd); return -1; } } int proxy_loop(){ struct sockaddr_in client_addr,server_addr; socklen_t sinlen; int client_fd,server_fd,yes=1,pos; char buffer[10000]; while(1){ bzero(&client_addr, sizeof(struct sockaddr_in)); GET_MICROTIME("before accept"); client_fd=accept(sfd,(struct sockaddr *)&client_addr,&sinlen); GET_MICROTIME("after accept"); if((server_fd=socket(AF_INET, SOCK_STREAM, 0)) == -1){ perror("server fd-socket() error!"); return -1; } setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); #ifdef USE_TRANSPARENT_TO_SERVER if(setsockopt(server_fd, SOL_IP, IP_TRANSPARENT, &yes, sizeof(int)) == -1){ perror("Server-setsockopt() IP_TRANSPARENT error!"); return -1; } #else bzero(&client_addr, sizeof(struct sockaddr_in)); client_addr.sin_family=AF_INET; client_addr.sin_addr.s_addr=inet_addr("212.76.127.11"); client_addr.sin_port=32760; #endif GET_MICROTIME("before the bind for the socket to the server"); if(bind(server_fd, (struct sockaddr *) &client_addr, sizeof(client_addr)) == -1){ perror("server fd - bind"); return -1; } bzero(&server_addr, sizeof(struct sockaddr_in)); getsockopt(client_fd, SOL_IP, SO_ORIGINAL_DST, &server_addr, &sinlen); GET_MICROTIME("after the bind, before the connect to the server"); if(connect(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1){ perror("connect server failed"); return -1; } GET_MICROTIME("after the connect, before the recv"); if((pos=recv(client_fd,buffer,10000,0))<0){ perror("recv problem"); return -1; } GET_MICROTIME("before send"); if((pos=send(server_fd,buffer,pos,0))<0){ perror("send problem"); return -1; } GET_MICROTIME("after send"); close(client_fd); close(server_fd); } } int main(){ if(create_listen_socket()<0 || proxy_loop()<0) exit(EXIT_FAILURE); }