Jump to content
Sign in to follow this  
Shanheavel

Local Proxy Server

Recommended Posts

Hi,

I'm trying all day to write a working proxy server, but it still doesn't work correctly. I'm not good at network functions, so maybe I've forgot about something.

It should receive, modify and send data between a browser and web server.

Here is a code. I just added a short comments. I hope it will make the script more readably.

#Region Tables
#include <Array.au3>

Global $sProxyIP = @IPAddress1, $iProxyPort = 8080, $iProxySocket = -1
Global $iNewSocket, $asLines[0], $sHost, $iLen
Global $aiBrowserSocket[0], $asBrowserRecv[0], $aiServerSocket[0], $asServerRecv[0], $aiServerContentLen[0]

#EndRegion Tables

#Region Initialization
If Not TCPStartup() Then Exit @ScriptLineNumber
$iProxySocket = TCPListen($sProxyIP, $iProxyPort)
If @error Then Exit @ScriptLineNumber
#EndRegion Initialization

While 1
    ;Accepting new sockets
    $iNewSocket = TCPAccept($iProxySocket)
    If $iNewSocket >= 0 Then ProxyAddArray($iNewSocket)

    ;Browser --> Proxy
    For $socket = 0 To UBound($asBrowserRecv) - 1
        $asBrowserRecv[$socket] = BinaryToString(TCPRecv($aiBrowserSocket[$socket], 1024 ^ 2))
        If @error Then
            ProxyDeleteArray($socket)
            $socket += 1
            ContinueLoop
        EndIf
    Next

    ;Browser data analyzing
    For $socket = 0 To UBound($asBrowserRecv) - 1
        $sHost = ''
        $asLines = StringSplit($asBrowserRecv[$socket], @CRLF, 1)
        For $line = 1 To $asLines[0]
            If StringLeft($asLines[$line], 4) = 'Host' Then
                $sHost = StringTrimLeft($asLines[$line], 6)
                ExitLoop
            EndIf
        Next
        $aiServerSocket[$socket] = TCPConnect(TCPNameToIP($sHost), 80)
        If @error Then
            ProxyDeleteArray($socket)
            $socket += 1
            ContinueLoop
        EndIf
    Next

    ;Proxy --> Web Page
    For $socket = 0 To UBound($aiServerSocket) - 1
        If $aiServerSocket[$socket] < 0 Then ContinueLoop
        $asServerRecv[$socket] = TCPSend($aiServerSocket[$socket], $asBrowserRecv[$socket])
        If @error Then $aiServerSocket[$socket] = -1
    Next

    ;Web Page --> Proxy
    For $socket = 0 To UBound($aiServerSocket) - 1
        If $aiServerSocket[$socket] < 0 Then ContinueLoop
        $iLen = 0
        $asServerRecv[$socket] = BinaryToString(TCPRecv($aiServerSocket[$socket], 1024 ^ 2 * 10))
        If StringLen($asServerRecv[$socket]) = 0 Then ContinueLoop
        $asLines = StringSplit($asServerRecv[$socket], @CRLF, 1)
        If @error Then $aiServerSocket[$socket] = -1
        For $line = 1 To $asLines[0]
            ;Data lenght
            If StringLeft($asLines[$line], 14) = 'Content-Length' Then
                $iLen = StringTrimLeft($asLines[$line], 16)
                $aiServerContentLen[$socket] = $iLen
                ExitLoop
            EndIf
        Next
    Next

    ;Proxy --> Browser
    For $socket = 0 To UBound($aiBrowserSocket) - 1
        If $aiServerContentLen[$socket] > StringLen($asBrowserRecv[$socket]) Then ContinueLoop
        TCPSend($aiBrowserSocket[$socket], $asServerRecv[$socket])
    Next
WEnd

#Region Proxy
Func ProxyAddArray($iSocket)
    _ArrayAdd($aiBrowserSocket, $iSocket)
    _ArrayAdd($asBrowserRecv, '')
    _ArrayAdd($aiServerSocket, -1)
    _ArrayAdd($asServerRecv, '')
    _ArrayAdd($aiServerContentLen, 0)
EndFunc   ;==>ProxyAddArray

Func ProxyDeleteArray($iIndex)
    _ArrayAdd($aiBrowserSocket, $iIndex)
    _ArrayAdd($asBrowserRecv, $iIndex)
    _ArrayAdd($aiServerSocket, $iIndex)
    _ArrayAdd($asServerRecv, $iIndex)
    _ArrayAdd($aiServerContentLen, $iIndex)
EndFunc   ;==>ProxyDeleteArray
#EndRegion Proxy

Important:

Before you will check this, you should change connection setting in your web browser.

And please do not post links to other old proxy server from Autoit Forums. I've tried them all.

Share this post


Link to post
Share on other sites

I see that no one is able to help me. So I wrote a new version of my proxy server. It does not use arrays. I think it is much simpler. However it still has problem with loading most sites. 

#Region Tables
Global $sProxyIP = @IPAddress1, $iProxyPort = 8080, $iProxySocket = -1
Global $iBrowserSocket, $sBrowserRecv
Global $iServerSocket, $sServerRecv, $iContentLenght

#EndRegion Tables

#Region Initialization
If Not TCPStartup() Then Exit @ScriptLineNumber
$iProxySocket = TCPListen($sProxyIP, $iProxyPort)
If @error Then Exit @ScriptLineNumber
#EndRegion Initialization

While 1
    Do
        $iBrowserSocket = TCPAccept($iProxySocket)
        Sleep(10)
    Until $iBrowserSocket > -1

    For $i = 1 To 100
        $sBrowserRecv = TCPRecv($iBrowserSocket, 1024 ^ 2)
        If $sBrowserRecv Then ExitLoop
        Sleep(10)
    Next

    If $sBrowserRecv Then
        If HTTPRequest() Then TCPSend($iBrowserSocket, $sServerRecv)
    EndIf
    TCPCloseSocket($iBrowserSocket)
WEnd

Func HTTPRequest()
    Local $asLines = StringSplit($sBrowserRecv, @CRLF, 1), $asLineParts[0]
    $iContentLenght = 0
    For $line = 1 To $asLines[0]
        $asLineParts = StringSplit($asLines[$line], ': ', 1)
        If $asLineParts[0] < 2 Then ContinueLoop
        Assign('Browser ' & $asLineParts[1], $asLineParts[2])
    Next
    $iServerSocket = TCPConnect(TCPNameToIP(Eval('Browser Host')), 80)
    If $iServerSocket < 0 Then Return
    If TCPSend($iServerSocket, $sBrowserRecv) <> StringLen($sBrowserRecv) Then Exit 2
    $sServerRecv = TCPRecv($iServerSocket, 1024 ^ 2)
    If @error Then Return
    $sServerRecv = BinaryToString($sServerRecv, 1)
    $asLines = StringSplit($sServerRecv, @CRLF, 1)
    For $line = 1 To $asLines[0]
        $asLineParts = StringSplit($asLines[$line], ': ', 1)
        If $asLineParts[0] < 2 Then ContinueLoop
        Switch $asLineParts[1]
            Case 'Content-Length'
                $iContentLenght = $asLineParts[2]
        EndSwitch
    Next
    For $i = 1 To 100
        If StringLen($sServerRecv) >= $iContentLenght Then ExitLoop
        $sServerRecv &= BinaryToString(TCPRecv($iServerSocket, 1024 ^ 2), 1)
        Sleep(10)
    Next
    If StringLen($sServerRecv) < $iContentLenght Then
        MsgBox(32, StringLen($sServerRecv) & '/' & $iContentLenght, $sServerRecv)
    EndIf
    Return 1
EndFunc   ;==>HTTPRequest

For example, it loads wikipedia.org only partly. 

Have you any idea, how to fix this?

Share this post


Link to post
Share on other sites

Your script has an array error at this line:

Func HTTPRequest()
    Local $asLines = StringSplit($sBrowserRecv, @CRLF, 1), $asLineParts[0]; <======

I know you said:

And please do not post links to other old proxy server from Autoit Forums. I've tried them all.

 

I'm not sure what you tried -- It's not perfect, but, did you try this?

'?do=embed' frameborder='0' data-embedContent>>

At the very least, you could get some ideas from it.


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Your script has an array error at this line:

Func HTTPRequest()
    Local $asLines = StringSplit($sBrowserRecv, @CRLF, 1), $asLineParts[0]; <======

It is hard to get an array error with StringSplit function, so I think  $asLineParts[0] is a problem for you. You probably have a older AutoIt version, where assigning empty arrays was not allowed. Just delete "[0]" at this point. 

And yes, I tried this. I have to admit that my code was inspired by yours. I want to write something like you, but much simpler.

Share this post


Link to post
Share on other sites

Yes, I used an older version of AutoIt -- It slipped my mind about that new feature.

You could strip my existing code to bare minimum. It wouldn't have any features though.

In any case, I try not to add any more code than what is necessary to make it work with

acceptable accuracy. It was a very slow process to make it that way. A lot of "trial and error".

Also at this time, it's not a good idea to check for an error after TCPRecv, if you're using a

newer version of AutoIt. A bug exist where it will exit the loop before you have received data.

I assume it will get fixed in some future update.

Ticket link: http://www.autoitscript.com/trac/autoit/ticket/2596

You'll find a work-around for it in my code, where I used several time-out schemes.

The For Loop, 1 to 100 is one of them.


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

I ran some test with this arrangement today...

; Example Section Only
;
;===============================================
For $i = 1 To 100
    $recv = TCPRecv($socket, 10240, 1)
    If @error And _WSA_GetLastError() Then; <- both conditions must exist to exitloop
        ExitLoop
    EndIf
    ;
    If StringLeft($recv, 2) = '0x' Then
        $string &= BinaryToString($recv)
    EndIf
    ;
    Sleep(10)
Next
;===============================================
;
Func _WSA_GetLastError()
    Local $array = DllCall('ws2_32.dll', 'int', 'WSAGetLastError')
    If @error Then Return -1
    Return $array[0]
EndFunc
;

If $recv is blank with an @error of -1 (meaning, it has not received data yet)
and _WSA_GetLastError() is 0, then it will continue to loop. Otherwise, when
both @error and _WSA_GetLastError() exist, it will then exit the loop.

So far, This seems to work well.

If it does okay over the next week, I'll update my code.


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • By AoRaToS
      I started working on this program in the summer of 2008 then I stopped cause I faced some problems I couldn't overcome back then. Now that I've practiced more and have become a better scripter/programmer I'm releasing the program to the public to get some opinions. I know it's not a new concept but it's the first program I started besides some small stuff I did just for practice! I won't post the source code yet because it's still under construction, although I'm sure I've posted early stages of the code with bugs in the past in some topic...
      What I wanted was a simple, small, serverless program that would work without installation cause I wanted it for where I work, so I ended up with this!
       
      I have attached some images of various versions, also visit the forum thread.
       
      The package includes s!mpL3 LAN Messenger, the License Agreement and the change log.
       
      Current version 2.9.9.0! [13/06/2019]
       
      Check the Change Log below!
       
       
      http://www.autoitscript.com/forum/index.php?showtopic=88782
       
       
       
      Read the license before using this software.
       
    • By Colduction
      Hello Guys and AutoIt Scriptwriters!🎉❤️
      I've created a script to notify to me if RDP main IP changed then send a message via Telegram bot to me
      But some of my RDP's Main IP are @IPAddress1 or @IPAddress3 or Public IP Address...
      I want to detect automatically the IP that windows client can run RDP to remotely control
      This image can help you that what i say, there are three RDP with specified IP, i want to run script in these RDP's then capture those IP's changes then notify me via Telegram bot

    • By rudi
      Hello,
      When new versions e.g. of your compiled script cannot be replaced on the server, as they are in use, you can use this script to manage to close the open handles and to replace the old file with your new version.

      ; Autoit v3.3.14.5 #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Res_Description=Close OpenFileHandlles, replace file on Server with a new version #AutoIt3Wrapper_Res_Fileversion=1 #AutoIt3Wrapper_Res_LegalCopyright=(c) 2019 by Rudolf Thilo, IT-Beratung Rudolf Thilo #AutoIt3Wrapper_Res_SaveSource=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <GUIConstantsEx.au3> #include <NetShare.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <EditConstants.au3> ; Enumerate open files on the server $DragDropOpenFile = "<drag-drop file locked on Server to be closed and replaced>" $DragDropNewFile = "<drag-drop file to replace the one on the server>" $NewFile = "" $Gui_h = 250 $Gui_w = 800 $vDist = 7 ; GUICreate($GuiTitle, $w, $h, @DesktopWidth - $w - 100, @DesktopHeight - $h - 60, -1, $WS_EX_ACCEPTFILES) ; generally enable drag-drop for files into other GUI controls $myGui = GUICreate("force close of all NETWORK opened file handles", $Gui_w, $Gui_h, 100, 100, -1, $WS_EX_ACCEPTFILES) $InputFileToClose = GUICtrlCreateInput($DragDropOpenFile, 20, $vDist, $Gui_w - 40, 20) GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; allow drag-droping files for this control, $InputFile Opt("Guicoordmode", 2) $InputFileNew = GUICtrlCreateInput($DragDropNewFile, -1, $vDist) GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; allow drag-droping files for this control, $InputFile GUICtrlSetState(-1, $GUI_DISABLE) $lServer = GUICtrlCreateLabel("<server>", -1, $vDist) $lShare = GUICtrlCreateLabel("<share>", -1, $vDist) $lPath = GUICtrlCreateLabel("<path>", -1, $vDist) $lFile = GUICtrlCreateLabel("<file>", -1, $vDist) $doit = GUICtrlCreateButton("search for and close open file handles", -1, $vDist) GUICtrlSetState(-1, $GUI_DISABLE) $exit = GUICtrlCreateButton("cancel", -1, $vDist) GUISetState() $FN = False $FNnew = "" $FNmatch = False $ToolTitle = "" $ToolTxt = "" While 1 $input = GUICtrlRead($InputFileToClose) If $input <> $DragDropOpenFile Then ; da wurde was reingezogen $DragDropOpenFile = $input If StringLeft($input, 2) = "\\" Then $Type = "UNC" $ServerShareUNC = StringLeft($input, StringInStr($input, "\", 0, 4) - 1) $fRelPathFN = StringReplace($input, $ServerShareUNC, "") $fPath = StringLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) $FN = StringTrimLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) ElseIf StringMid($input, 2, 1) = ":" Then ; Pfad mit Laufwerksbuchstabe, evtl. Netzwerk Mapping (erforderlich) $drive = StringLeft($input, 2) $Type = DriveGetType($drive) If $Type = "Network" Then $ServerShareUNC = DriveMapGet($drive) $foo = StringReplace($input, $drive, $ServerShareUNC) ; Laufwerkspfad in UNC Pfad umwandeln $fRelPathFN = StringReplace($foo, $ServerShareUNC, "") $fPath = StringLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) $FN = StringTrimLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) Else MsgBox(0, @ScriptLineNumber, "This script can *ONLY* close open file handles on NETWORK SHARES!" & @CRLF & _ $input & @CRLF & _ $drive & " = " & $Type) ContinueLoop 2 EndIf EndIf $Server = StringLeft($ServerShareUNC, StringInStr($ServerShareUNC, "\", 0, 3) - 1) $Share = StringTrimLeft($ServerShareUNC, StringInStr($ServerShareUNC, "\", 0, 3) - 1) GUICtrlSetData($lServer, $Server) GUICtrlSetData($lShare, $Share) GUICtrlSetData($lPath, $fPath) GUICtrlSetData($lFile, $FN) GUICtrlSetState($doit, $GUI_ENABLE) GUICtrlSetState($InputFileNew, $GUI_ENABLE) EndIf If $NewFile <> GUICtrlRead($InputFileNew) Then $NewFile = GUICtrlRead($InputFileNew) If $NewFile <> $DragDropNewFile Then If StringInStr($NewFile, $DragDropNewFile) Then $NewFile = StringReplace($NewFile, $DragDropNewFile, "") GUICtrlSetData($InputFileNew, $NewFile) EndIf $FNnew = StringTrimLeft($NewFile, StringInStr($NewFile, "\", 0, -1)) If $FN = $FNnew Then If $FNmatch = False Then $FNmatch = True GUICtrlSetData($doit, "Search for open file handles, close them, overwrite old file.") EndIf Else If $FNmatch Then $FNmatch = False GUICtrlSetData($doit, "Search for open file handles and close them.") GUICtrlSetData($InputFileNew,$DragDropNewFile) EndIf EndIf EndIf EndIf Switch GUIGetMsg() Case $exit, $GUI_EVENT_CLOSE GUIDelete($myGui) Exit Case $doit AbArbeiten($Server, $Share, $fPath, $FN) EndSwitch WEnd Func AbArbeiten($_Srv, $_Shr, $_fPth, $_fNme) Local $iID = 0 Local $iRights = 1 Local $iLckCount = 2 Local $iFPFN = 3 Local $iUser = 4 ConsoleWrite($_fPth & $_fNme & @CRLF) Local $aFile = _Net_Share_FileEnum($_Srv) If IsArray($aFile) Then ; _ArrayDisplay($aFile) Local $x $ToolTxt = "Open Handles:" $ToolTitle = $aFile[0][0] & " handles still waiting to be checkt..." UpdateToolTip() AdlibRegister(UpdateToolTip, 1000) For $x = $aFile[0][0] To 1 Step -1 $ToolTitle = $x & " handles waiting to be checked..." If Not StringInStr($aFile[$x][$iFPFN], $_fPth & $_fNme) Then ; ConsoleWrite("Nix Enthalten in: " & $aFile[$x][$iFPFN] & @CRLF) _ArrayDelete($aFile, $x) Else $ToolTxt &= @CRLF & $aFile[$x][$iFPFN] & ", User = " & $aFile[$x][$iUser] ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ToolTxt = ' & $ToolTxt & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console EndIf Next $aFile[0][0] = UBound($aFile) - 1 _ArraySort($aFile, 0, 1, 0, $iUser) ; _ArrayDisplay($aFile, $aFile[0][0] & " FileLocks found.") If $aFile[0][0] = 0 Then $ToolTitle = "Done. No open handles coud be found." $ToolTxt &= @CRLF & "Nothing to be closed!" Sleep(2000) $ToolTxt = "" Else $ToolTitle = $aFile[0][0] & " Handles found to be closed..." $CloseErr = 0 For $x = 1 To $aFile[0][0] If _Net_Share_FileClose($Server, $aFile[$x][$iID]) Then $ToolTxt &= @CRLF & @TAB & "Handle closed: " & $aFile[$x][$iID] Else $ToolTxt &= @CRLF & "ERROR: Handle Close Failed! --> " & $aFile[$x][$iFPFN] & ", User = " & $aFile[$x][$iUser] $CloseErr += 1 EndIf Next ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $CloseErr = ' & $CloseErr & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If $CloseErr = 0 Then $ToolTitle = "Alle open handles were closed successfully." If FileExists($NewFile) Then If FileCopy($NewFile, $input, 1 + 8) Then $ToolTitle = "File could be replaced." $ToolTxt = "done" Else $ToolTitle = "File could *NOT* be replaced" $ToolTxt = "Most propably a newly open file handle was created while this script was running." & @CRLF & _ "Just start over again." EndIf EndIf Else $ToolTitle = $CloseErr & " handles could *NOT* be closed!" Sleep(2000) EndIf Sleep(1000) $ToolTxt = "" $ToolTitle = "" EndIf Else MsgBox(0, "not an array", $aFile & @CRLF & @error & @CRLF & @extended) EndIf EndFunc ;==>AbArbeiten Func UpdateToolTip() ToolTip($ToolTxt, MouseGetPos(0) + 20, MouseGetPos(1) + 20, $ToolTitle) ; ConsoleWrite( $ToolTxt & @CRLF & $ToolTitle & @CRLF & "-------------------" & @CRLF) EndFunc ;==>UpdateToolTip Rudi.
    • By Raywando
      Hello,
      This is my first post. So I’ve worked on a script for a while and I’m planning to publish it but the problem is that it connects to an FTP server at some point, and as you probably know FTP credentials are easily captured by a MITM attack or Wireshark (not sure if Wireshark does). So I thought if i can detect data capturing in the user’s network the script would stop. Any idea?.
      If there’s another workaround I’m happy to hear it. 
    • By HansHenrik
      ----------
      edit: this is probably in the wrong place, can a moderator move it to wherever it belongs?
      ----------

      is there any way to completely disable TCPTimeout and make TCPRecv() wait indefinitely? maybe setting it to 0 or -1 or something? 
      the docs doesn't seem to mention any way to disable it

      - the underlying C code would set SO_RCVTIMEO to 0 , aka

      DWORD timeout=0;
      setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
×
×
  • Create New...