Code: Select all
;+-------------------------+
;|                         |
;|      Proxy-Server       |
;|                         |
;|   only http supported   |
;|     in this example     |
;|  (for SOCKs use brain)  |
;|                         |
;|      (c)HeX0R 2005      |
;|                         |
;+-------------------------+
Structure _clients_
  Mode.l
  ClientID.l
  OUT_Port.l
  OUT_IP.s
  OUT_ID.l
  IN_Rest_String.s
  OUT_Rest_String.s
EndStructure
Global IN_Username.s ;<-possible Username for proxy
Global IN_Password.s ;<-possible Password for proxy
Global *buffer
NewList Clients._clients_()
*buffer = AllocateMemory(20000)
If InitNetwork() = 0
  End
EndIf
NetID.l = CreateNetworkServer(8080)
If NetID = 0
  Debug "Can't Create Listen-Server!"
  End
EndIf
Procedure.l SelectClient(Client.l)
  found.l = #False
  ForEach Clients()
    If Clients()\ClientID = Client
      found = #True
      Break
    EndIf
  Next
  ProcedureReturn found
EndProcedure
Procedure CheckInput(From_ID.l, To_ID.l, mode.b)
  ;mode Bit0 = 1  -> Data from Client (OUT)
  ;mode Bit0 = 0  -> Data from Server (IN)
  If mode & 1
    Rest.s = Clients()\OUT_Rest_String
    What.s = "OUT"
  Else
    Rest.s = Clients()\IN_Rest_String
    What.s = "IN"
  EndIf
  
  length.l = ReceiveNetworkData(From_ID, *buffer, 10000)
  
  ;Normal
  text$ = Rest + PeekS(*buffer, length)
  count.l = CountString(text$, Chr(10))
  For i = 1 To count
    line$ = StringField(text$, i, Chr(10)) + Chr(10)
    line$ = ReplaceString(ReplaceString(line$, Chr(10), "[lf]"), Chr(13), "[cr]")
    PrintN(What + "->" + line$)    
  Next i
  If mode & 1
    Clients()\OUT_Rest_String = StringField(text$, i, Chr(10))
  Else
    Clients()\IN_Rest_String = StringField(text$, i, Chr(10))
  EndIf
  If To_ID
    SendNetworkData(To_ID, *buffer, length)
  EndIf
EndProcedure
Procedure.l ProxyCheckConnect()
  If Clients()\Mode = -1
    ProcedureReturn 0
  EndIf
  ;====================
  ;-HTTP - Proxy
  ;====================
  length.l = ReceiveNetworkData(Clients()\ClientID, *buffer, 5000)
  If length = 0
    ProcedureReturn 0
  EndIf
  PokeB(*buffer + length, 0)
  text$ = PeekS(*buffer)
  accept$ = "200"
  If LCase(Left(text$, 8)) = "connect "
    ;Application-Tunneling!
    text$ = Right(text$, Len(text$) - 8)
    ip_port.s = StringField(text$, 1, " ")
    Clients()\OUT_IP = StringField(text$, 1, ":")
    Clients()\OUT_Port = Val(StringField(text$, 2, ":"))
    l.l = FindString(text$, #CRLF$, 1)
    If l
      text$ = Right(text$, Len(text$) - l - 1)
    EndIf
    If IN_Username
      *newbuffer = AllocateMemory(1024)
      user$ = IN_Username + ":" + IN_Password
      length2.l = Len(user$) * 2
      If length2 < 64
        length2 = 64
      EndIf
      Base64Encoder(@user$, Len(user$), *newbuffer, length2)
      encoded$ = PeekS(*newbuffer)
      FreeMemory(*newbuffer)
      If FindString(text$, encoded$ + #CRLF$, 1)
        Clients()\Mode = 10
      Else
        accept$ = "401 Authorization Required"
        PrintN("Error - Wrong username/password")
      EndIf
    Else
      Clients()\Mode = 10
    EndIf
    If Clients()\Mode = 10
      server$ = Clients()\OUT_IP + ":" + Str(Clients()\OUT_Port)
      PrintN("Connecting to " + server$ + "...")
      Clients()\OUT_ID = OpenNetworkConnection(Clients()\OUT_IP, Clients()\OUT_Port)
      If Clients()\OUT_ID = 0
        accept$ = "411"
        PrintN("Unable to reach external Server " + server$)
      Else
        PrintN("Connected to " + server$)
      EndIf
    EndIf
  Else
    accept$ = "402"
    Clients()\Mode = -1
  EndIf
  text$ = "HTTP/1.1 " + accept$ + Chr(10) + "O.K." + Chr(10)
  SendNetworkData(Clients()\ClientID, @text$, Len(text$))
  If accept$ <> "200"
    Clients()\Mode = -1
  EndIf
EndProcedure
If OpenConsole()
  PrintN("Server started and listening on Port 8080")
  Repeat
    key_pressed$ = Inkey()
    Select NetworkServerEvent()
      Case 0
        Delay(5)
      Case 1
        Client.l = NetworkClientID()
        AddElement(Clients())
        Clients()\ClientID = NetworkClientID()
        Clients()\Mode = 0
        PrintN("Client Connected")
      Case 2
        ;Data Received
        Client.l = NetworkClientID()
        If SelectClient(Client)
          If Clients()\Mode < 10
            ProxyCheckConnect()
          Else
            CheckInput(Clients()\ClientID, Clients()\OUT_ID, #True)
          EndIf
        EndIf
      Case 4
        ;Disconnect
        Client.l = NetworkClientID()
        If SelectClient(Client)
          DeleteElement(Clients())
          PrintN("Client Disconnected")
        EndIf
    EndSelect
    ForEach Clients()
      If Clients()\OUT_ID
        Select NetworkClientEvent(Clients()\OUT_ID)
          Case 2
            CheckInput(Clients()\OUT_ID, Clients()\ClientID, #False)
        EndSelect
      EndIf
    Next
  Until Left(key_pressed$, 1) = Chr(27)
EndIf
CloseNetworkServer()
CloseConsole()
FreeMemory(*buffer)
End