小型的http代理程序

關鍵詞: http代理程序    壓縮後不到3K                                          
http代理程序網上有很多,公佈源代碼的也有一些,但是很多我測試的都不是很滿意,
於是就借鑑了那些代碼,我自己動手打造了這個。
沒有很多註釋,其實每個函數名都可以顧名思義。

我自己測試沒什麼問題的,有心的可以幫忙測試下,附件中有源碼和已編譯壓縮的程序

其實協議的很多細節我沒去弄清楚,只是知道修改下請求包再轉發包,就寫了這個東西

glacier前輩有空可以看下嗎,http代理這樣實現還有什麼不足

// Author: LZX
// E-mail: [email protected]
// Version: V1.0 beta
// Purpose: A HTTP Proxy Supports GET && POST && CONNECT Methods
// Test PlatForm: WinXP SP2
// Compiled On: VC++ 6.0

#include <windows.h>
#include <stdio.h>
#include <wininet.h>
#include <errno.h>
#pragma comment(lib,"Ws2_32.lib")

#define MAX_HOSTNAME    256
#define DEFAULTPORT        80
#define LISTENPORT        8000
#define DEFLISNUM        500
#define HEADLEN            7

#define TIMEOUT            10000
#define MAXSIZE            20480

char ErrorMsg[]="Http/1.1 403 Forbidden/r/n/r/n<body><h1>403 Forbidden</h1></body>";
char ConnectionEstablished[]="HTTP/1.0 200 OK/r/n/r/n";

DWORD    WINAPI ZXHTTPProxyThread(SOCKET* CSsocket);
int        CheckRequest(char *ReceiveBuf,int *MethodLength);
char    *GetURLRootPoint(char * ReceiveBuf,int DataLen,int *HostNaneLen);
void    GetHostNameAndPort(char *ReceiveBuf,int datalen,char *HostName,UINT *RemotePort);
int        ModifyRequest(char *SenderBuf,char *ReceiveBuf,int DataLen,int MethodLength);
char    *DNS(char *HostName);
BOOL    ConnectToRemoteHost(SOCKET *ServerSocket,char *HostName,const UINT RemotePort);
BOOL    SendRequest(SOCKET* CSsocket, char *SenderBuf, char *ReceiveBuf, int DataLen);
void    TransferData(SOCKET* CSsocket);

char *DNS(char *HostName)
{
    HOSTENT *hostent = NULL;
    IN_ADDR iaddr;
    hostent = gethostbyname(HostName);
    if (hostent == NULL)
    {
        return NULL;
    }
    iaddr = *((LPIN_ADDR)*hostent->h_addr_list);
    return inet_ntoa(iaddr);
}
BOOL ConnectToRemoteHost(SOCKET *ServerSocket,char *HostName,const UINT RemotePort)
{
    struct sockaddr_in Server;
    memset(&Server, 0, sizeof(Server));

    Server.sin_family = AF_INET;
    Server.sin_port = htons(RemotePort);

    if (inet_addr(HostName) != INADDR_NONE)
    {
        Server.sin_addr.s_addr = inet_addr(HostName);
    }
    else
    {
        if (DNS(HostName) != NULL)
        {
            Server.sin_addr.s_addr = inet_addr(DNS(HostName));
        }
        else
        {
            //printf("Invalid Host Name/n");
            return FALSE;
        }
    }
    // Create Socket
    *ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if (*ServerSocket == INVALID_SOCKET)
    {
        //printf("Fail To Create Server Socket/n");
        return FALSE;
    }
    // Set Socket Time To 10 Seconds
    UINT TimeOut = TIMEOUT;
    setsockopt(*ServerSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut));

    // Connect To The Remote Host
    if (connect(*ServerSocket, (const SOCKADDR *)&Server,sizeof(Server)) == SOCKET_ERROR)
    {
        //printf("Fail To Connect To Remote Host/n");
        closesocket(*ServerSocket);
        return FALSE;
    }

    return TRUE;
}// End Of ConnectToRemoteHost()
//---------------------------------------------------------------------------
void GetHostNameAndPort(char *ReceiveBuf,int datalen,char *HostName,UINT *RemotePort)
{
    char *fp = ReceiveBuf;
    for(int i = 0;i < datalen && *fp != ':' && *fp != '/0' && *fp != '/r' && *fp != '/';i++)
    {   
        HostName[i]=*fp++;
        if(*fp == ':')
            *RemotePort=atoi(fp+1);
        else *RemotePort=DEFAULTPORT;
    }
}
//---------------------------------------------------------------------------
char * GetURLRootPoint(char * ReceiveBuf,int DataLen,int *HostNaneLen)
{
    for(int i = 0;i < DataLen; i++)
    {
        if(ReceiveBuf[i] == '/')
        {
            *HostNaneLen = i;
            return &ReceiveBuf[i];
        }
    }
    return NULL;
}
//---------------------------------------------------------------------------
int CheckRequest(char *ReceiveBuf,int *MethodLength)
{
    if(!strnicmp(ReceiveBuf,"GET ",4))
    {
        *MethodLength = 4;
        return 1;
    }
    else if(!strnicmp(ReceiveBuf,"HEAD ",5)) //Looks like the same with GET
    {
        *MethodLength = 5;
        return 2;
    }
    else if(!strnicmp(ReceiveBuf,"POST ",5))
    {
        *MethodLength = 5;
        return 3;
    }
    else if(!strnicmp(ReceiveBuf,"CONNECT ",8))
    {
        *MethodLength = 8;
        return 4;
    }
    else
    {
        return 0;
    }
}
int ModifyRequest(char *SenderBuf,char *ReceiveBuf,int DataLen,int MethodLength)
{
    strncpy(SenderBuf,ReceiveBuf,MethodLength);
    int HedLen = 0;
    if(strncmp(ReceiveBuf+MethodLength,"http://",HEADLEN))
        return 0;

    char * Getrootfp = GetURLRootPoint(ReceiveBuf+MethodLength+HEADLEN,DataLen-MethodLength-HEADLEN,&HedLen);
    if(Getrootfp == NULL)
        return 0;

    memcpy(SenderBuf+MethodLength,Getrootfp,DataLen-MethodLength-HEADLEN-HedLen);

    return DataLen-HEADLEN-HedLen;
}
////////////////////////////////////////////////////////
void TransferData(SOCKET* CSsocket)
{
    SOCKET ClientSocket = CSsocket[0];
    SOCKET ServerSocket = CSsocket[1];
    struct timeval timeset;
    fd_set readfd,writefd;
    int result,i=0;
    char read_in1[MAXSIZE],send_out1[MAXSIZE];
    char read_in2[MAXSIZE],send_out2[MAXSIZE],SenderBuf[MAXSIZE];
    int read1=0,totalread1=0,send1=0;
    int read2=0,totalread2=0,send2=0;
    int sendcount1,sendcount2;
    int maxfd;

    maxfd=max(ClientSocket,ServerSocket)+1;
    memset(read_in1,0,MAXSIZE);
    memset(read_in2,0,MAXSIZE);
    memset(send_out1,0,MAXSIZE);
    memset(send_out2,0,MAXSIZE);

    timeset.tv_sec=TIMEOUT;
    timeset.tv_usec=0;
    while(1)
    {
        FD_ZERO(&readfd);
        FD_ZERO(&writefd);

        FD_SET((UINT)ClientSocket, &readfd);
        FD_SET((UINT)ClientSocket, &writefd);
        FD_SET((UINT)ServerSocket, &writefd);
        FD_SET((UINT)ServerSocket, &readfd);

        result=select(maxfd,&readfd,&writefd,NULL,×et);
        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, &readfd))
        {
            if(totalread2<MAXSIZE)
            {
                read2=recv(ServerSocket,read_in2,MAXSIZE-totalread2, 0);
                if(read2==0)break;
                if((read2<0) && (errno!=EINTR))
                {
                    //printf("[-] Read ServerSocket data error,maybe close?/r/n/r/n");
                    break;
                }

                memcpy(send_out2+totalread2,read_in2,read2);

                  totalread2+=read2;
                  memset(read_in2,0,MAXSIZE);

            }
            //printf("Read from WebServer:/n%s/n",send_out2);
        }

        if(FD_ISSET(ClientSocket, &writefd))
         {
            int err2=0;
                sendcount2=0;
                while(totalread2>0)
                {
                     send2=send(ClientSocket, send_out2+sendcount2, totalread2, 0);
                    if(send2==0)break;
                    if((send2<0) && (errno!=EINTR))
                    {
                        //printf("[-] Send to ClientSocket unknow error./r/n");
                    err2=1;
                        break;
                    }
                    if((send2<0) && (errno==ENOSPC)) break;
                    sendcount2+=send2;
                    totalread2-=send2;

                }
            if(err2==1) break;
               if((totalread2>0) && (sendcount2 > 0))
            {
                /* move not sended data to start addr */
                memcpy(send_out2, send_out2+sendcount2, totalread2);
                memset(send_out2+totalread2, 0, MAXSIZE-totalread2);
            }
            else
                memset(send_out2,0,MAXSIZE);
        }


        if(FD_ISSET(ClientSocket, &readfd))
        {
            /* must < MAXSIZE-totalread1, otherwise send_out1 will flow */
            if(totalread1<MAXSIZE)
               {
                read1=recv(ClientSocket, read_in1, MAXSIZE-totalread1, 0);
                if((read1==SOCKET_ERROR) || (read1==0))
                  {
                      //printf("[-] Read ClientSocket data error,maybe close?/r/n");
                      break;
                  }

                memcpy(send_out1+totalread1,read_in1,read1);

                totalread1+=read1;
                memset(read_in1,0,MAXSIZE);
            }
            if(SendRequest(CSsocket,SenderBuf,send_out1,totalread1))
                totalread1=0;
        }

        if(FD_ISSET(ServerSocket, &writefd))
        {
            int err=0;
            sendcount1=0;
            while(totalread1>0)
            {
                send1=send(ServerSocket, send_out1+sendcount1, totalread1, 0);
                if(send1==0)break;
                if((send1<0) && (errno!=EINTR))
                {
                    //printf("[-] Send to ServerSocket unknow error./r/n");
                    err=1;
                    break;
                }

                if((send1<0) && (errno==ENOSPC)) break;
                sendcount1+=send1;
                totalread1-=send1;

            }

            if(err==1) break;
            if((totalread1>0) && (sendcount1>0))
            {
                memcpy(send_out1,send_out1+sendcount1,totalread1);
                memset(send_out1+totalread1,0,MAXSIZE-totalread1);
            }
            else
            memset(send_out1,0,MAXSIZE);
        }
        Sleep(5);
    }

    closesocket(ClientSocket);
    closesocket(ServerSocket);
    //printf("/r/nClosed The Two Socket./r/n");
}
BOOL SendRequest(SOCKET* CSsocket, char *SenderBuf, char *ReceiveBuf, int DataLen)
{
    //CSsocket[0] ClientSocket
    //CSsocket[1] ServerSocket
    DWORD  dwThreadID;
    char   HostName[MAX_HOSTNAME] = {0};
    UINT   RemotePort = 0;

    int Flag=0, MethodLength=0, SendLength=0;
    Flag = CheckRequest(ReceiveBuf,&MethodLength);
    if(Flag==0) return 0;

    if(Flag==1 || Flag==2 || Flag==3)
    {
        SendLength=ModifyRequest(SenderBuf,ReceiveBuf,DataLen,MethodLength);
        if(!SendLength)
            return 0;
        GetHostNameAndPort(ReceiveBuf+MethodLength+HEADLEN,DataLen-MethodLength-HEADLEN,HostName,&RemotePort);
        //printf("%s:%d/n",HostName,RemotePort);
        if(!ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort))
            return 0;
        //printf("%s/n",SenderBuf);
        if(send(CSsocket[1],SenderBuf,SendLength,0) == SOCKET_ERROR)
            return 0;
    }else if(Flag==4)
    {
        GetHostNameAndPort(ReceiveBuf+MethodLength,DataLen-MethodLength,HostName,&RemotePort);
        //printf("%s:%d/n",HostName,RemotePort);
        if(!ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort))
            return 0;
        send(CSsocket[0], ConnectionEstablished, strlen(ConnectionEstablished),0);
    }
    if(CSsocket[0] && CSsocket[1])
    {
        HANDLE ThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)TransferData,(LPVOID)CSsocket,0,&dwThreadID);
        if (ThreadHandle != NULL)
        {
            WaitForSingleObject(ThreadHandle, INFINITE);
        }
    }else
        return 0;
    return 1;

}
DWORD WINAPI ZXHTTPProxyThread(SOCKET* CSsocket)
{

    char *ReceiveBuf = (char*)malloc(sizeof(char)*MAXSIZE);
    char *SenderBuf  = (char*)malloc(sizeof(char)*MAXSIZE);

    memset(ReceiveBuf,0,MAXSIZE);
    memset( SenderBuf,0,MAXSIZE);

    int DataLen = 0;

    DataLen = recv(CSsocket[0],ReceiveBuf,MAXSIZE,0);

    if(DataLen == SOCKET_ERROR || DataLen == 0)
    {
        goto error;
    }
    if(!SendRequest(CSsocket, SenderBuf, ReceiveBuf, DataLen))
        goto error;

error:
    send(CSsocket[0],ErrorMsg,strlen(ErrorMsg),0);
    closesocket(CSsocket[0]);
    closesocket(CSsocket[1]);
    free(CSsocket);
    free(ReceiveBuf);
    free(SenderBuf);
    return 0;
}


int main(int argc, char* argv[])
{
    int LisPort=LISTENPORT;
    if(argc>1)
        LisPort=atoi(argv[1]);

    printf("Http Proxy V1.0 By LZX./r/nUsage: %s ProxyPort/r/n",argv[0]);

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

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

    struct sockaddr_in Server={0};

    Server.sin_family = AF_INET;
    Server.sin_port = htons(LisPort);
    Server.sin_addr.S_un.S_addr = INADDR_ANY;

    if(bind(ProxyServer, (LPSOCKADDR)&Server, sizeof(Server)) == SOCKET_ERROR)
        return 1;

    if(listen(ProxyServer, DEFLISNUM) == SOCKET_ERROR)
        return 1;

    SOCKET AcceptSocket = INVALID_SOCKET;
    SOCKET *CSsocket;
    DWORD  dwThreadID;

    printf("Now listening on port: %d/r/n",LisPort);
    while(1)
    {
        AcceptSocket = accept(ProxyServer, NULL, NULL);
        //printf("Accepting New Requests/n");
        CSsocket = (SOCKET*)malloc(sizeof(SOCKET)*2);
        if (CSsocket == NULL)
        {
            //printf("Fail To Allocate Ram/n");
            continue;
        }
        CSsocket[0] = AcceptSocket;
        HANDLE hThread = CreateThread (NULL,0, (LPTHREAD_START_ROUTINE)ZXHTTPProxyThread,CSsocket,0, &dwThreadID);        // Create Thread To Handle Request
        if (hThread == NULL)        // Fail To Create Socket
        {
            //printf("Fail To Create Thread.Probably Too Many Threads Have Been Created/n");
            Sleep(1000);
        }
        else
        {
            CloseHandle(hThread);
        }

    }
}

 

 

出處:http://beiyu.bokee.com/4495940.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章