Solved

Lightweight HTTP Proxy in VB6

Posted on 2008-06-10
12
2,753 Views
Last Modified: 2013-11-25
Hi,

I am looking to write a very simple HTTP proxy in VB6.  It will be VERY light usage, it will be only handelling a single user and a single web page at a time.
0
Comment
Question by:dentab
  • 6
  • 4
12 Comments
 
LVL 10

Expert Comment

by:cool12399
ID: 21781235
Use winsock and set the proxy port you are using there,

I.e.,
Winsock1.RemoteHost=proxyaddress.com
winsock1.RemotePort=80 ' or whatever

Of course you'll need to handle all the send/get requests, etc, but this will do what you need.
0
 
LVL 5

Author Comment

by:dentab
ID: 21791498
what?

Yes its the handeling bit thats important.  I dont intend to use the winsock control anyway but rather the API - or even the CSocket wrapper (previously from VBIP.com).  I was ideally looking for scripts or protocol information.  

I could have better worded my question I know - but your answer is the equivilant to telling someone who wants to change their car engine to "open the hood".
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 21841189
I've used CSocket with a SOCKS5 proxy in the past if you'd like a modified copy/paste. Would still require a bit of tweaking on your end though.
0
 
LVL 5

Author Comment

by:dentab
ID: 21841193
Sounds like an interesting project - and I am tempted to open up a new question for it but it wouldn't really help this time.

I need to write a HTTP proxy server.  
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 21841242
For what purpose? I don't exactly know how an HTTP proxy functions nor can I find any RFCs. SOCKS proxies can be used many types of situations, including browsers. They simply tunnel data back/forth between client/server and can also modify the data if needed.
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 5

Author Comment

by:dentab
ID: 21841308
Its to be installed on a student network.  Basicly it would be useful to turn internet access on/off based on individual requirements.  A HTTP proxy is at present to provide access to the students.  What my application would look to do is.

1) load when the student logs in and capture the student credentials (no problem)
2) check that the student has internet access based on the following: (no problem)
         a) is the student currently enrolled
         b) is the student timetabled or is this open-access
         c) has the student agreed to the AUP
         d) has the student got an outstanding mid-course survey to complete
3) if for any of the above reasons the student does not qualify for internet access then the application would set itelf as the proxy for IE.  If all is ok then the ISA proxy details would be set and following steps would be skipped.
4) Redirect the student to required resouce (AUP/Survey)
5) Internet requests to the VB proxy would prompt the application to re-check conditions, if they have changed then reset the proxy settings and refresh the browser request (javascript).

I dont know if that makes sense to you but as you can see, the demands of the VB "proxy server" are minimal, requests to it only ever result in a refresh or denial page.  Frankly I can probably catch the header info I need, but I thought it was worth asking in the EE world incase anyone had an answer.
0
 
LVL 5

Author Comment

by:dentab
ID: 21841313
PS Incase you diddnt guess - AUP = Acceptable Use Policy

The College requires the latest version of the AUP to be agreed by any student who requires internet access.
0
 
LVL 17

Accepted Solution

by:
zzzzzooc earned 500 total points
ID: 21841449
With that approach, determined users can probably bypass the use of a proxy. However, determined users can usually bypass anything so that's trivial. ;-)

I've dug up some old classes and made some changes to them. They still work for me (tested using proxy in Firefox) but my revised versions are in .NET projects so these will require optimizations/bug fixes/etc. My .NET SOCKS5 probably has authentication and ipv6 if that's really required.

With this posted, I don't recommend that this be DELETED. Thanks. :}


Form1:
------------------
Option Explicit

Private m_Proxies As cProxies
Private Sub Form_Load()
    Set m_Proxies = New cProxies
    m_Proxies.Port = 1234
    m_Proxies.LocalOnly = False
    m_Proxies.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Set m_Proxies = Nothing
End Sub


cProxies:
-------------------------------
Option Explicit

Private WithEvents sckProxy As cSocket

Private mBlnProxyEnabled As Boolean
Private mBlnProxyLocal As Boolean
Private mIntProxyPort As Integer

Private mColSocks As Collection
Private Sub Class_Initialize()
    'Call SettingsLoad
End Sub
Private Sub Class_Terminate()
   'Call SettingsSave
End Sub
Public Property Let Enabled(ByVal blnTemp As Boolean)
    mBlnProxyEnabled = blnTemp
    If mBlnProxyEnabled = True Then
        If (sckProxy Is Nothing) Then
            Call SocketEnable(True)
        End If
    Else
        If Not (sckProxy Is Nothing) Then
            Call SocketEnable(False)
        End If
    End If
End Property
Public Property Get Enabled() As Boolean
    Enabled = mBlnProxyEnabled
End Property
Public Property Let LocalOnly(ByVal blnTemp As Boolean)
    mBlnProxyLocal = blnTemp
End Property
Public Property Get LocalOnly() As Boolean
    LocalOnly = mBlnProxyLocal
End Property
Public Property Let Port(ByVal intTemp As Integer)
    Dim blnReset As Boolean
    If mIntProxyPort <> intTemp Then
        blnReset = True
    End If
    mIntProxyPort = intTemp
    If blnReset = True Then
        'Call SettingsSave
        Call SocketEnable(False)
        Call SocketEnable(True)
    End If
End Property
Public Property Get Port() As Integer
    Port = mIntProxyPort
End Property
Public Sub SocketAdd(ByVal requestID As Long)
    Dim clsProxy As cProxy
    Set clsProxy = New cProxy
    Set clsProxy.mObjParent = Me
    clsProxy.mStrKey = Hex$(ObjPtr(clsProxy)) & sckProxy.RemoteHostIP
    Call clsProxy.sckClient.Accept(requestID)
    Call mColSocks.Add(clsProxy, clsProxy.mStrKey)
End Sub
Public Sub SocketEnable(ByVal blnTrue As Boolean)
    If blnTrue = True Then
        Set mColSocks = New Collection
        Set sckProxy = New cSocket
        sckProxy.LocalPort = mIntProxyPort
        sckProxy.Protocol = sckTCPProtocol
        Call sckProxy.Listen
    Else
        If Not (sckProxy Is Nothing) Then
            Call sckProxy.CloseSocket
        End If
        Set sckProxy = Nothing
        Set mColSocks = Nothing
    End If
End Sub
Public Sub SocketRemove(ByVal strKey As String)
    Dim clsProxy As cProxy
    For Each clsProxy In mColSocks
        If clsProxy.mStrKey = strKey Then
            Call mColSocks.Remove(strKey)
            Exit Sub
        End If
    Next
End Sub
Private Sub sckProxy_OnConnectionRequest(ByVal requestID As Long)
    If mBlnProxyLocal = True Then
        If sckProxy.RemoteHostIP <> "127.0.0.1" Then
            Exit Sub
        End If
    End If
    Call SocketAdd(requestID)
End Sub



cProxy:
---------------------
Option Explicit

Private Const SOCKS_VER5 As Byte = &H5

Public WithEvents sckClient As cSocket
Public WithEvents sckServer As cSocket

Public mObjParent  As cProxies
Public mStrKey     As String
Public mBytState   As Byte
Private Sub Class_Initialize()
    Set sckClient = New cSocket
    Set sckServer = New cSocket
End Sub
Private Sub Class_Terminate()
    Set sckClient = Nothing
    Set sckServer = Nothing
End Sub
Private Sub ProxyConnect(ByRef strData As String)
    Dim intLen1 As Integer, i As Integer
    Dim strHost As String, strPort As String
    intLen1 = Len(strData)
    If intLen1 > 6 Then
        If Asc(Left$(strData, 1)) = SOCKS_VER5 Then
            If Asc(Mid$(strData, 2, 1)) = 1 Then
                Select Case Asc(Mid$(strData, 4, 1))
                    Case 1 'IPv4
                        If intLen1 > 8 Then
                            For i = 0 To 2
                                strHost = strHost & Asc(Mid$(strData, 5 + i, 1)) & "."
                            Next i
                            strHost = strHost & Asc(Mid$(strData, 8, 1))
                            i = 9
                        Else
                            i = 0
                        End If
                    Case 3 'Domain
                        i = Asc(Mid$(strData, 5, 1))
                        If intLen1 > 6 + i Then
                            strHost = Mid$(strData, 6, i)
                            i = i + 6
                        Else
                            i = 0
                        End If
                    Case 4 'IPv6
                        'empty
                End Select
                If (strHost <> vbNullString) And (i <> 0) Then
                    mBytState = 2
                    strPort = Val(Asc(Mid$(strData, i, 1))) * 256 Or _
                              Val(Asc(Mid$(strData, i + 1, 1)))
                    Call sckServer.Connect(strHost, strPort)
                    Exit Sub
                End If
            End If
        End If
    End If
    Call mObjParent.SocketRemove(mStrKey)
End Sub
Private Sub ProxyMethod(ByRef strData As String)
    Dim bytMethCnt As Byte, bytMeths() As Byte, bytMeth As Byte, i As Byte
    If Len(strData) >= 3 Then
        If Asc(Left$(strData, 1)) = SOCKS_VER5 Then
            bytMethCnt = Asc(Mid$(strData, 2, 1))
            If Len(strData) = (bytMethCnt + 2) Then
                bytMeths() = StrConv(Mid$(strData, 3, bytMethCnt), vbFromUnicode)
                For i = 0 To bytMethCnt - 1
                    If bytMeths(i) = &H0 Then
                        bytMeth = &H0
                        Exit For
                    Else
                        bytMeth = &HFF
                    End If
                Next
                mBytState = 1
                Call sckClient.SendData(Chr$(SOCKS_VER5) & Chr$(bytMeth))
                Exit Sub
            End If
        End If
    End If
    Call mObjParent.SocketRemove(mStrKey)
End Sub
Private Sub ProxySuccess()
    Dim strResp(0 To 9) As Byte, strIP() As String, i As Integer
    mBytState = 3
    strIP() = Split(sckServer.RemoteHostIP, ".")
    If UBound(strIP) <> 3 Then
        strIP() = Split(sckServer.RemoteHost, ".")
    End If
    If UBound(strIP) <> 3 Then
        strIP() = Split("255.255.255.255", ".")
    End If
    strResp(0) = SOCKS_VER5
    strResp(1) = 0
    strResp(3) = 1
    For i = 0 To 3
        strResp(4 + i) = Val(strIP(i))
    Next i
    strResp(8) = Fix(sckServer.RemotePort / 256)
    strResp(9) = sckServer.RemotePort - (Fix(sckServer.RemotePort / 256) * 256)
    Call sckClient.SendData(StrConv(strResp(), vbUnicode))
End Sub
Private Sub sckClient_OnDataArrival(ByVal bytesTotal As Long)
    Dim strData As String
    Call sckClient.GetData(strData, vbString, bytesTotal)
    Select Case mBytState
        Case 0
            Call ProxyMethod(strData)
        Case 1
            Call ProxyConnect(strData)
        Case 3
           
            Debug.Print strData
            sckServer.SendData strData
    End Select
End Sub
Private Sub sckServer_OnConnect()
    If sckClient.State = sckConnected Then
        Call ProxySuccess
    Else
        Call mObjParent.SocketRemove(mStrKey)
    End If
End Sub
Private Sub sckServer_OnDataArrival(ByVal bytesTotal As Long)
    Dim strData As String
    Call sckServer.GetData(strData, vbString, bytesTotal)
   
    Debug.Print strData
    sckClient.SendData strData
End Sub


0
 
LVL 5

Author Comment

by:dentab
ID: 21841869
Thanks zoc, not really the answer I need but its useful anyway.  And a hell of a lot better than "Use Winsock" like somebody pointed out.

"With that approach, determined users can probably bypass the use of a proxy" - not really our techs have gone overboard on lockdown to the point its almost unusable.  No right-click, no task manager, access control software allowing only executables with the right checksums.... etc etc.  Frankly I couldnt work with it (staff network is not locked down).  In addition to that the executable could always add/remove proxy credentials too.

I would be interested in your existing .Net code please, if thats not too much touble though.

Many Thanks
  DenTab
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 21842017
I can't disclose the entire source for the .NET proxy but hey I did notice that I had at some point added minimized HTTP Proxy support for it. xD


Some routines...

        Public Sub Connect() Implements IProxyProxy.Connect
            m_Parent.Connect(m_Parent.Parent.HTTPServer, m_Parent.Parent.HTTPPort, m_Client)
            If m_Client IsNot Nothing Then
                Dim reply As String = String.Empty
                Dim hostaddr As String = m_Parent.RemoteHost
                Dim hostname As String = Dns.GetHostEntry(hostaddr).HostName
                Dim hostport As UShort = m_Parent.RemotePort
                reply = "CONNECT " & hostaddr & ":" & hostport & " HTTP/1.0" & vbCrLf & _
                "Host: " & hostname & ":" & hostname & vbCrLf & vbCrLf
                BeginRecv()
                Dim b() As Byte = Text.Encoding.ASCII.GetBytes(reply)
                m_Client.Send(b, b.Length, SocketFlags.None)
            End If
        End Sub


        Private Sub BeginRecvProc()
            Dim bytesBuff(4096) As Byte
            Dim bytesRead As Integer
            Try
                m_Client.ReceiveBufferSize = bytesBuff.Length
                While True
                    bytesRead = m_Client.Receive(bytesBuff, bytesBuff.Length, SocketFlags.None)
                    If (bytesRead = 0) Then
                        Exit While
                    End If
                    If bytesRead > 12 Then
                        Dim s As String = Text.Encoding.ASCII.GetString(bytesBuff, 0, bytesRead - 1)
                        If s.StartsWith("HTTP/1.1 200") = True Then
                            RaiseEvent Success(m_Client)
                        ElseIf s.StartsWith("HTTP/1.0 200") = True Then
                            RaiseEvent Success(m_Client)
                        Else
                            RaiseEvent Failure()
                        End If
                    End If
                    Exit While
                End While
            Catch e As Exception
                RaiseEvent Failure()
            End Try
            Cleanup()
        End Sub
0
 
LVL 5

Author Comment

by:dentab
ID: 21842486
thanks zzzzzooc.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now