• XSS.stack #1 – первый литературный журнал от юзеров форума

Переадресация трафа

at0m

RAID-массив
Пользователь
Регистрация
16.05.2010
Сообщения
93
Реакции
2
Картина такая
Есть 3 приложения A/B/C

Приложения А конечное оно имеет доступ в сеть
Приложение В промежуточное оно переадресует траф с приложения А на С и наоборот
Приложения С - клиент.

Проблема видимо в синхронизации. вот примеры кода

Для приложения А
Код:
       // tunneling socket to socket :))
       WSAEVENT MyStructEvents[1];
       MyStructEvents[0] = hDestSockEvent;
       MyStructEvents[1] = hSourceSocketEvent;
       char*szBuf = (char*)GlobalAlloc(GMEM_ZEROINIT,TRANSFERS_BUFF);
       if (szBuf != NULL)
       {
       DWORD dwRet;
       int _recvBytes;
       BOOL bIsExit = TRUE;
       while  (bIsExit)
       {
           WSANETWORKEVENTS WSANetworkEvents;
           dwRet = WSAWaitForMultipleEvents(2,MyStructEvents,FALSE,TIME_WAIT_REPLY,FALSE);
           switch (dwRet)
           {
               case WSA_WAIT_EVENT_0 + 0:     
               if (WSAEnumNetworkEvents(DestSock,hDestSockEvent,&WSANetworkEvents) == 0)
               {
                     if(WSANetworkEvents.lNetworkEvents & FD_READ)
                     {
                                if (WSANetworkEvents.iErrorCode[FD_READ_BIT] == 0)
                                { 
                                   //do {
                                              // receive data from remote server
                                              _recvBytes = ReceiveData(DestSock,szBuf,TRANSFERS_BUFF); 
                                             if (_recvBytes > 0)
                                             {
                                                 //send data to daemon 
                                                  SendData(SourceSocket,szBuf,_recvBytes);
                                             }
                                  //} while (_recvBytes != 0);
                               }
                      }
                      if(WSANetworkEvents.lNetworkEvents & FD_CLOSE)
                      {
                                 if ( (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] == 0) || (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0))
                                 {
                                      bIsExit = FALSE;
                                 }
                      }	
              }
              break;

              case WSA_WAIT_EVENT_0 + 1:
              if (WSAEnumNetworkEvents(SourceSocket,hSourceSocketEvent,&WSANetworkEvents) == 0)
              {
                    if(WSANetworkEvents.lNetworkEvents & FD_READ)
                    {
                          if (WSANetworkEvents.iErrorCode[FD_READ_BIT] == 0)
                          { 
                              //do {
                              // receive data from daemon
                              _recvBytes = ReceiveData(SourceSocket,szBuf,TRANSFERS_BUFF);
                              if (_recvBytes > 0)
                              {
                                   // send data to server
                                   SendData(DestSock,szBuf,_recvBytes);
                              }
                              //} while (_recvBytes != 0);
                          }
                     }
                     if(WSANetworkEvents.lNetworkEvents & FD_CLOSE)
                     {
                          if ( (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] == 0) || (WSANetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0))
                          {
                               bIsExit = FALSE;
                          }
                     }	
               }
               break;

               case WSA_WAIT_FAILED :
               bIsExit = FALSE;
               break;
           } 
       }
       GlobalFree(szBuf);  
   }    

для Приложения В
Код:
                      hWsaEvents[0] := hClientRemoteEvent;
                      hWsaEvents[1] := hPeerBackConnectRemoteEvent;
                      GetMem(pTransferData,PACKET_BUFFER);
                      FillChar(pTransferData^,PACKET_BUFFER,0);
                      repeat

                          dwRet:=WSAWaitForMultipleEvents(2,@hWsaEvents,FALSE,WSA_TIMEOUT_DELAY,FALSE);
                          case dwRet of

                          WSA_WAIT_EVENT_0 + 0:
                              begin
                                if  WSAEnumNetworkEvents(MySocketsInfo.sClientRemoteSocket,hClientRemoteEvent,MyWSANetworkEvents) = 0 then
                                begin
                                  if ( MyWSANetworkEvents.lNetworkEvents and FD_READ) > 0 then
                                  begin
                                    if MyWSANetworkEvents.iErrorCode[FD_READ_BIT] = 0 then
                                    begin
                                      //repeat
                                         // receive from client
                                         dwReceiveBytes := ReceiveData(MySocketsInfo.sClientRemoteSocket,PAnsiChar(pTransferData),PACKET_BUFFER);
                                         if (dwReceiveBytes > 0) then
                                         begin
                                           // send to bot
                                           SendData(sPeerBackConnectRemoteSocket,PAnsiChar(pTransferData),dwReceiveBytes);
                                         end;
                                      //until (dwReceiveBytes = 0);
                                    end;
                                  end;
                                  if ( MyWSANetworkEvents.lNetworkEvents and FD_CLOSE) > 0 then
                                  begin
                                    if (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] = 0) or (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] <> 0) then
                                    begin
                                      // close subsession session
                                      //bIsExitOrNext := True;
                                    end;
                                  end;
                                end;
                              end;

                          WSA_WAIT_EVENT_0 + 1:
                              begin
                                if WSAEnumNetworkEvents(sPeerBackConnectRemoteSocket,hPeerBackConnectRemoteEvent,MyWSANetworkEvents) = 0 then
                                begin
                                  if ( MyWSANetworkEvents.lNetworkEvents and FD_READ) > 0 then
                                  begin
                                    if MyWSANetworkEvents.iErrorCode[FD_READ_BIT] = 0 then
                                    begin
                                      //repeat
                                        // receive from bot
                                        dwReceiveBytes := ReceiveData(sPeerBackConnectRemoteSocket,PAnsiChar(pTransferData),PACKET_BUFFER);
                                        // send to client
                                        if dwReceiveBytes > 0 then
                                        begin
                                          SendData(MySocketsInfo.sClientRemoteSocket,PAnsiChar(pTransferData),dwReceiveBytes);
                                        end;
                                      //until ( dwReceiveBytes = 0);
                                    end;
                                  end;
                                  if ( MyWSANetworkEvents.lNetworkEvents and FD_CLOSE) > 0 then
                                  begin
                                    if (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] = 0) or (MyWSANetworkEvents.iErrorCode[FD_CLOSE_BIT] <> 0) then
                                    begin
                                      // close subsession session
                                      //bIsExitOrNext := True;
                                    end;
                                  end;
                                end;
                              end;

                          WSA_WAIT_FAILED :
                              begin
                                bIsExitOrNext := True;
                              end;


                          end;
                      until (Self.Terminated or bIsExitOrNext);
                      FreeMem(pTransferData);


суть в следующем ограничения буфера 8191 байт припустим нужно что то принят более чем этот буфер получается следущая ситуация приложения С принимает даные через прилож. В (в цикле по событиях перебрасывает буфер ) с прилож. А на прилож. С. Тут А начинает принимать даные и передавать на промежутоное приложение В но данные не все доходят с А на В, Тоесть смотрел в отладке А принимает все даные и сразу по событию отсылает на В. Прилож. B теряет даные так как идет следующая ситуация А принимает даные и отсылает и неизвестно как там В с ними работает принял или нет но в В не все даные что А принял. Какие методы синхронизации существуют в моем случае ??? или может есть у кого то исходники тунеля на винсок под винду ... я думал что бы все сразу принял а потом передавать но если у меня будет поток )) и т.д и т.п.
 
может есть у кого то исходники тунеля на винсок под винду

Socat? Не совсем под винду конечно, но собирается под нее. Netcat?
 
Вот кусок кода из моего socks5 сервера (http://zona-chat.narod.ru/src/mini_socks5_0.01_src.rar), который реализует туннель
Код:
// теперь надо обмен между клиентом и сервером организовать
  while(1)
  {
  	fds_read.fd_count=2;
  	fds_read.fd_array[0] = client;
  	fds_read.fd_array[1] = dst_socket;

  	// запросим инфу о состоянии
  	k = select(0, &fds_read, 0, 0, &tv);
  	if (k > 0) // если чтото изменилось
  	{
    if (__WSAFDIsSet(client, &fds_read)) // если первый сокет очухался
    {
    	len=recv(client,buf,4096,MSG_PEEK);
    	if(!len) break;
    	else { 
      if(tcp_rs(RECV,client,buf,len,0)>0) { 

      	if(tcp_rs(SEND,dst_socket,buf,len,0)<=0) break;

      } else break; }
    }
    if (__WSAFDIsSet(dst_socket, &fds_read)) // если первый сокет очухался
    {
    	len=recv(dst_socket,buf,4096,MSG_PEEK);
    	if(!len) break;
    	else { if(tcp_rs(RECV,dst_socket,buf,len,0)>0) { 

      if(tcp_rs(SEND,client,buf,len,0)<=0) break;

    	} else break; }
    }
  	} 
  Sleep(50); // не отнимаем у проца ресурсы
  }

Вот пример для UNIX

Код:
 while (!done) {  
        FD_ZERO(&rdset);  
        FD_SET(tty_in, &rdset);  
        FD_SET(rfcomm, &rdset);  
  
        if (select(n, &rdset, NULL, NULL, NULL) < 0) {  
            if (errno == EINTR)  
                continue;  
  
            //syslog(LOG_ERR, "select error: %m");  
            exit(EXIT_FAILURE);  
        }  
  
        if (FD_ISSET(tty_in, &rdset))  
            copy_data(tty_in, rfcomm);  
  
        if (FD_ISSET(rfcomm, &rdset))  
            copy_data(rfcomm, tty_out);  
    }  

void copy_data(int src, int dst) {  
    static char buf[BUFSIZ];  
    ssize_t nr, nw, off;  
  
    while ((nr = read(src, buf, sizeof (buf))) == -1) {  
        if (errno != EINTR) {  
            //syslog(LOG_ERR, "read failed: %m");  
            exit(EXIT_FAILURE);  
        }  
    }  
  
    if (nr == 0) /* reached EOF */  
        done++;  
  
    for (off = 0; nr; nr -= nw, off += nw) {  
        if ((nw = write(dst, buf + off, (size_t) nr)) == -1) {  
            //syslog(LOG_ERR, "write failed: %m");  
            exit(EXIT_FAILURE);  
        }  
    }  
}

Конечно это для блокирующих сокетов, но тебе ничто не мешает сделать поток для клиента.
 
вопрос решен
причина была в том что системная очередь на сокете была заполнена и при отсылке буфера был сокет_еррор и ошибка (WSAEWOULDBLOCK) надо было еще раз WSAWaitForMultipleEvents подождать и дождатся события FD_WRITE после чего этот же буфер отправить все )
всем спасибо топ можно закрыть
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх