1
votes

I worte a little Web Proxy program that uses a TcpListener, which listen on a specific port for web calls. Once it recieves a call it creates a socket, gets the header of the call, forwards it onto the web page requested, reads the response and returns it to the client doing the request. The proxy works lovely, but now I want to limit who has access to the net via the proxy by implimenting user names. How would I incorparate authentication onto my proxy?

Here is my code:

using System; using System.Net; using System.Net.Sockets; using System.Text; using System.IO; using System.Threading; using System.Windows.Forms; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing;

namespace WebProxy2 { public partial class Form1 : Form { public bool proxyOn = false;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    public void log(string logText)
    {
        Application.DoEvents();
        textBox1.Text += logText + "\r\n";
        StreamWriter sw = new StreamWriter(@"c:\proxyLog.txt",true);
        sw.WriteLine(logText);
        sw.Close();
        Application.DoEvents();
    }

    class WebProxy2
    {
        Socket clientSocket;
        Form1 proxyGui;
        Byte[] read = new byte[1024];
        Byte[] Buffer = null;
        Encoding ASCII = Encoding.ASCII;
        const string HTTP_VERSION = "HTTP/1.0";
        const string CRLF = "\r\n";
        Byte[] RecvBytes = new Byte[4096];

        public WebProxy2(Socket socket, Form1 form)
        {
            this.clientSocket = socket;
            this.proxyGui = form;
        }

        public void run()
        {
            Application.DoEvents();
            String clientmessage = " ", sURL = " ";

            int bytes = readmessage(read, ref clientSocket, ref clientmessage);
            if (bytes == 0)
            {
                return;
            }
            int index1 = clientmessage.IndexOf(' ');
            int index2 = clientmessage.IndexOf(' ', index1 + 1);
            if ((index1 == -1) || (index2 == -1))
            {
                throw new IOException();
            }
            proxyGui.log("Connecting to Site: " + clientmessage.Substring(index1 + 1, index2 - index1));
            proxyGui.log("Connection from " + clientSocket.RemoteEndPoint);
            string part1 = clientmessage.Substring(index1 + 1, index2 - index1);
            int index3 = part1.IndexOf('/', index1 + 8);
            int index4 = part1.IndexOf(' ', index1 + 8);
            int index5 = index4 - index3;
            sURL = part1.Substring(index1 + 4, (part1.Length - index5) - 8);
            try
            {


                IPHostEntry IPHost = Dns.Resolve(sURL);
                proxyGui.log("Request resolved: " + IPHost.HostName);
                string[] aliases = IPHost.Aliases;
                IPAddress[] address = IPHost.AddressList;
                proxyGui.log(address[0].ToString());
                IPEndPoint sEndpoint = new IPEndPoint(address[0], 80);
                Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                IPsocket.Connect(sEndpoint);
                if (IPsocket.Connected)
                    proxyGui.log("Socket connect OK");
                string GET = clientmessage;
                Byte[] ByteGet = ASCII.GetBytes(GET);
                IPsocket.Send(ByteGet, ByteGet.Length, 0);
                Int32 rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
                proxyGui.log("Recieved " + rBytes);
                //Buffer = RecvBytes;
                String strRetPage = null;
                strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
                while (rBytes > 0)
                {
                    rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
                    strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
                }
                IPsocket.Shutdown(SocketShutdown.Both);
                IPsocket.Close();
                sendmessage(clientSocket, strRetPage);
            }
            catch (Exception exc2)
            {
                proxyGui.log(exc2.ToString());
            }
        }

        private int readmessage(byte[] ByteArray, ref Socket s, ref String clientmessage)
        {

            int bytes = s.Receive(ByteArray, 1024, 0);
            string messagefromclient = Encoding.ASCII.GetString(ByteArray);
            clientmessage = (String)messagefromclient;
            return bytes;
        }
        private void sendmessage(Socket s, string message)
        {
            Buffer = new Byte[message.Length + 1];
            int length = ASCII.GetBytes(message, 0, message.Length, Buffer, 0);
            s.Send(Buffer, length, 0);
        }

    }

    const int port = 8080;
    TcpListener tcplistener = new TcpListener(port);
    private void btnProxy_Click_1(object sender, EventArgs e)
    {
        proxyOn = true;
        log("Listening on port " + port + " " + DateTime.Now.ToString());

        tcplistener.Start();
        while (proxyOn)
        {
            Application.DoEvents();
            if (tcplistener.Pending())
            {
                Socket socket = tcplistener.AcceptSocket();
                WebProxy2 webproxy = new WebProxy2(socket, this);
                webproxy.run();
            }
         Application.DoEvents();
        }
    }

    private void btnStop_Click_1(object sender, EventArgs e)
    {
        Application.DoEvents();
        proxyOn = false;
        tcplistener.Stop();
        log("Proxy stopped !!! " + DateTime.Now.ToString());
        Application.DoEvents();
    }

}

}

1

1 Answers

1
votes

It's not clear whether you've implemented your own HTTP proxy protocol (more or less a simple TCP redirection based on the Host header) or if you're using the standard HTTP proxy protocol.

If you go for the standard proxy (which is probably better, unless you have a good reason not to do so), you should be able to use the Proxy-Authenticate, Proxy-Authorization and Proxy-Authentication-Info headers instead of WWW-Authenticate, Authorization and Authentication-Info (respectively) for HTTP Basic or Digest authentication for example.