首页
社区
课程
招聘
[原创]远程桌面代理
发表于: 2014-12-2 18:07 7677

[原创]远程桌面代理

2014-12-2 18:07
7677
远程桌面代理
lilicao2000@tom.com
最近公司突然把很多局域网的网段屏蔽了,也就是说生产线上的电脑不能访问办公室的电脑,反之亦然,这给我造成了很多不便,但是部门服务器网段是没有被屏蔽的(如下图所示A是连不到C的),最简单的办法就是在部门服务器B上弄个代理之类的程序然后我就可以在生产线上的网段上用远程桌面连接办公室的电脑了,ok,开始撸。



#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   
#include <winsock2.h>   
#include <windows.h>   
#include <errno.h>
#include "proxymstsc.h"


		
#define MAX_HOSTNAME    1 
#define DEFAULTPORT     3389   
#define LISTENPORT      9595   
#define DEFLISNUM       50   
#define MAXBUFSIZE      20480   
#define TIMEOUT         10000   

//SOCKET *cs_socket;
/*void close_proxy(){

	if(cs_socket){
		closesocket(cs_socket[0]);
		closesocket(cs_socket[1]);
		closesocket(cs_socket[2]);
		free(cs_socket);
		WSACleanup();
	}
}*/

void TCP_Transfer(SOCKET *cs_socket){

	SOCKET ClientSocket = cs_socket[0];   
	SOCKET ServerSocket = cs_socket[1];   
	struct timeval cli_time_set,ser_time_set;   
	fd_set cli_rcv_fd,cli_send_fd; 
	fd_set	ser_rcv_fd,ser_send_fd;
	int result;   
	char cli_rcv_buf[MAXBUFSIZE],ser_send_buf[MAXBUFSIZE];   
	char ser_rcv_buf[MAXBUFSIZE],cli_send_buf[MAXBUFSIZE];   
	int cli_rcv_byte=0,totalcli_rcv_byte=0,ser_send_byte=0;   
	int ser_rcv_byte=0,totalser_rcv_byte=0,cli_send_byte=0;   
	int seri_total_send_byte,cli_total_send_byte;   
	
	memset(cli_rcv_buf,0,MAXBUFSIZE);   
	memset(ser_rcv_buf,0,MAXBUFSIZE);   
	memset(ser_send_buf,0,MAXBUFSIZE);   
	memset(cli_send_buf,0,MAXBUFSIZE);   

	while(1)   
	{   
		cli_time_set.tv_sec=TIMEOUT/2;   
		cli_time_set.tv_usec=0; 
		ser_time_set.tv_sec=TIMEOUT/2;
		ser_time_set.tv_usec=0;

		FD_ZERO(&cli_rcv_fd);   
		FD_ZERO(&cli_send_fd);   
		FD_ZERO(&ser_rcv_fd);
		FD_ZERO(&ser_send_fd);

		FD_SET((UINT)ClientSocket, &cli_rcv_fd);   
		FD_SET((UINT)ClientSocket, &cli_send_fd);   
		
		
		FD_SET((UINT)ServerSocket, &ser_send_fd);   
		FD_SET((UINT)ServerSocket, &ser_rcv_fd); 

		result=select(ClientSocket+1,&cli_rcv_fd,&cli_send_fd,NULL,&cli_time_set);   
		if((result<0) && (errno!=EINTR))   
		{   
			//printf("Select error.\r\n");   
			break;   
		}   
		else if(result==0)   
		{   
			//printf("Socket time out.\r\n");   
			break;   
		}   
		if(FD_ISSET(ClientSocket, &cli_send_fd))
		{
			int err2=0;
			cli_total_send_byte=0;
			while(totalser_rcv_byte>0)   
			{   
				cli_send_byte=send(ClientSocket, cli_send_buf+cli_total_send_byte, totalser_rcv_byte, 0);   
				if(cli_send_byte==0)break;   
				if((cli_send_byte<0) && (errno!=EINTR))   
				{   
					//printf("Send to ClientSocket unknow error.\r\n");   
					err2=1;   
					break;   
				}   
				if((cli_send_byte<0) && (errno==ENOSPC)) break;   
				cli_total_send_byte+=cli_send_byte;   
				totalser_rcv_byte-=cli_send_byte;   
				//printf("send to client: %d byte\n",cli_send_byte);
			}   
			if(err2==1) break;   
			if((totalser_rcv_byte>0) && (cli_total_send_byte > 0))   
			{   
				/* move not sended data to start addr */   
				memcpy(cli_send_buf, cli_send_buf+cli_total_send_byte, totalser_rcv_byte);   
				memset(cli_send_buf+totalser_rcv_byte, 0, MAXBUFSIZE-totalser_rcv_byte);   
			}   
			else   
				memset(cli_send_buf,0,MAXBUFSIZE);   
		}   


		if(FD_ISSET(ClientSocket, &cli_rcv_fd))   
		{   
			if(totalcli_rcv_byte<MAXBUFSIZE) 
			{
				cli_rcv_byte=recv(ClientSocket, cli_rcv_buf, MAXBUFSIZE-totalcli_rcv_byte, 0);
				if((cli_rcv_byte==SOCKET_ERROR) || (cli_rcv_byte==0)){ 
					break; 
					}
				memcpy(ser_send_buf+totalcli_rcv_byte,cli_rcv_buf,cli_rcv_byte);
				totalcli_rcv_byte+=cli_rcv_byte;
				memset(cli_rcv_buf,0,MAXBUFSIZE); 
				//printf("read form client: %d byte\n",cli_rcv_byte);
			} 
			//if(SendRequest(CSsocket,SenderBuf,ser_send_buf,totalcli_rcv_byte))
			//	totalcli_rcv_byte=0;
		}
		//////////////////////////////
		result=select(ServerSocket+1,&ser_rcv_fd,&ser_send_fd,NULL,&ser_time_set);  
		if((result<0) && (errno!=EINTR))   
		{   
			//printf("Select error.\r\n");   
			break;   
		}   
		else if(result==0)   
		{   
			//printf("Socket time out.\r\n");   
			break;   
		}   
		
		if(FD_ISSET(ServerSocket, &ser_rcv_fd))
		{ 
			if(totalser_rcv_byte<MAXBUFSIZE) 
			{
				
				ser_rcv_byte=recv(ServerSocket,ser_rcv_buf,MAXBUFSIZE-totalser_rcv_byte,0);
				if(ser_rcv_byte==0)break;
				if((ser_rcv_byte<0) && (errno!=EINTR))
				{
					//printf("Read ServerSocket data error,server maybe closed\r\n\r\n");
					break;
				}
				memcpy(cli_send_buf+totalser_rcv_byte,ser_rcv_buf,ser_rcv_byte);
				totalser_rcv_byte+=ser_rcv_byte;
				memset(ser_rcv_buf,0,MAXBUFSIZE);
				//printf("read from server: %d byte\n",ser_rcv_byte);
			}
		}
		
		if(FD_ISSET(ServerSocket,&ser_send_fd))
		{
			int err=0;
			seri_total_send_byte=0;
			while(totalcli_rcv_byte>0)   
			{   
				   
				ser_send_byte=send(ServerSocket, ser_send_buf+seri_total_send_byte, totalcli_rcv_byte, 0);   
				if(ser_send_byte==0)break;   
				if((ser_send_byte<0) && (errno!=EINTR))   
				{   
					err=1;   
					break;   
				}   

				if((ser_send_byte<0) && (errno==ENOSPC)) break;   
				seri_total_send_byte+=ser_send_byte;   
				totalcli_rcv_byte-=ser_send_byte;   
				//printf("send to server: %d byte\n",ser_send_byte);
			}   

			if(err==1) break;   
			if((totalcli_rcv_byte>0) && (seri_total_send_byte>0))   
			{   
				memcpy(ser_send_buf,ser_send_buf+seri_total_send_byte,totalcli_rcv_byte);   
				memset(ser_send_buf+totalcli_rcv_byte,0,MAXBUFSIZE-totalcli_rcv_byte);   
			}   
			else   
				memset(ser_send_buf,0,MAXBUFSIZE);   
		}   
		Sleep(5);   
	}//while   

	closesocket(ClientSocket);   
	closesocket(ServerSocket);
	

}

int connect_remot_host(SOCKET *serversocket,char *hostname,const int remotport){

	struct sockaddr_in server;
	memset(&server,0,sizeof(server));

	struct hostent *temp_server=gethostbyname(hostname);

	server.sin_family=AF_INET;
	server.sin_port=htons(remotport);
	server.sin_addr=*((struct in_addr*)temp_server->h_addr);

	*serversocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(*serversocket == INVALID_SOCKET)
		return 0;
	UINT timeout=TIMEOUT;
	setsockopt(*serversocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
	unsigned int i=40960;
	setsockopt(*serversocket,SOL_SOCKET,SO_RCVBUF,(void*)&i,sizeof(i));
	i=40960;
	setsockopt(*serversocket,SOL_SOCKET,SO_SNDBUF,(void*)&i,sizeof(i));

	if(connect(*serversocket,(const SOCKADDR *)&server,sizeof(server))==SOCKET_ERROR){
		//printf("Fail to connect to remot host:%d serversocket:%d server:%s\n",WSAGetLastError(),serversocket,inet_ntoa(server.sin_addr));
		closesocket(*serversocket);
		return 0;
	}	
	
	return 1;
}

void mstsc_proxy(SOCKET *cs_socket){
	char hostname[]={""};//please type your remote compute name
	
	
	connect_remot_host(&cs_socket[1],hostname,DEFAULTPORT);
	if(cs_socket[0] && cs_socket[1]){
		//printf("Transfering TCP session :%d\t-->%d\n",cs_socket[1],cs_socket[0]);
		TCP_Transfer(cs_socket);
		
	}
	closesocket(cs_socket[0]);
	closesocket(cs_socket[1]);
	free(cs_socket);

}




void start_proxy(){

	WSADATA WSAData;   
	if(WSAStartup(MAKEWORD(2,2), &WSAData))   
		return;   

	SOCKET proxyserver=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(proxyserver == SOCKET_ERROR)
		return;

	struct sockaddr_in server={0};
	
	server.sin_family=AF_INET;
	server.sin_port=htons(LISTENPORT);
	server.sin_addr.S_un.S_addr=INADDR_ANY;

	if(bind(proxyserver,(LPSOCKADDR)&server,sizeof(server))==SOCKET_ERROR)
		return;
	if(listen(proxyserver,DEFLISNUM)==SOCKET_ERROR)
		return;

	SOCKET accept_socket=INVALID_SOCKET;
	

	//printf("proxy listening on port:%d\r\n",LISTENPORT);

	while(1){
		accept_socket=accept(proxyserver,NULL,NULL);
		SOCKET *cs_socket;
		cs_socket=(SOCKET*)malloc(sizeof(SOCKET)*2);
		cs_socket[0]=accept_socket;
		
		mstsc_proxy(cs_socket);

	}//while

	WSACleanup();
}

int main(void){

	


	start_proxy();

	
}


在撸的过程中发现代理程序要怎么知道mstsc要连那台机的ip地址?
我就直接把这个地址硬编码了,如下图:


还有就是刚开始没用select和线程,发现代理程序最多接收和发送一次dada就停着不动了,调试了一下之后用select改了下发现代理程序运行正常。开始还是想简单了,当然你也可以用线程来代替,但线程太难调试了。

这个代理程序功能很单一,只是把mstsc进行简单的TCPIP端口转发,其它的像HTTP FTP 等等是不支持的,当然到了这里已经很容易扩展了,这个程序不支持多人连接,如果要支持多人连接你得在代理程序中知道mstsc要连接的ip地址,这里我没想到更好的办法,因为mstsc没有IE的代理设置(如下图:)



当然你可以在mstsc加个这样的设置,然后再在代理程序里面解析出远程IP就行了,就像sock5代理里面一样,坛子里有很多人都可以做到。
希望好心的Geek给个简洁优雅的方法。
还有就是你得在mstsc中填写代理程序所在的ip地址(也就是上面图中B的地址)。

这只是一个图样图森破的版本(Too young Too Simple),但是已经能用了!
写这个玩意的时候参考了坛子里面几位大侠的代码,在这里表示感谢!
感谢我的同事CC Liu 让这个程序运行在服务器上。
如有疑问请在下面回帖。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 1585
活跃值: (182)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
吊爆了-----
2014-12-2 19:08
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
收藏,谢谢分享
2014-12-2 19:58
0
雪    币: 1136
活跃值: (683)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个不就是端口转向吗?
2014-12-2 21:04
0
游客
登录 | 注册 方可回帖
返回
//