Friday, March 31, 2006

Implementing a generic TCP/IP socket proxy in ASP.NET

I frequently work in places where I only have access to the internet via a HTTP proxy. E-mail protocols like SMTP, POP3 and IMAP 4 are not proxyable via http (normally) so I download mails via GPRS/UMTS when needed. The problem is that it costs a fortune when someone sends you a gigantic .ZIP file.

it handles all tcp/ip socket based protocols I have tried so far: smtp, pop3, http, https, Microsoft Terminal Services.(mstsc is slower, but it works like a charm via a https proxy for emergency purposes)

I hope the code is understandable even if it is fruit of late night coding sessions while I am on a tight deadline for not one, but two, releases in the middle of the night next week. Releasing solutions based on Java 1.5/Tomcat 5.5 and .NET/Win2k3 in the same week keeps life -busy- but interesting. At least I learn something new every day. There are a lot of possible improvements like automatically importing the proxy settings from the default browser and adding authentication support but I don't need them (yet)

A generic socket proxy implemented in ASP.NET

Why on earth do something like this?

I frequently work in offices where I only have access to the internet via a HTTP proxy. E-mail protocols like SMTP, POP3 and IMAP cannot be proxied via http so I download mails via GPRS/UMTS when needed. The problem is that it costs a fortune when someone sends you a gigantic Power Point presentation by mistake.

This week it happened again, several times, and I decided to do something about it. I found HTTPort, and several similar to it, but they all require me to install a new "server" somewhere. A new service that may have security problems and that may be difficult/impossible to installl with a hosting provider.

In the end I decided to roll my own ASP.NET based solution for several reasons:

Security/stability: Implementing a new socket server is always a risk in terms of buffer overruns etc. IIS/ASP.NET is heavilyt tested offers a lot of monitoring features as well.

Easy to deploy: Deploy the ASP.NET server at any site that support ASP.NET and sticky sessions.

I cannot use a VPN as my cell provider blocks some of the ports used by Microsoft VPNs.

I have been busy working on it the last couple of nights and have come up with a working solution that is "good enough for me". I do not intend to spend more time working on the user interface, or adding features I do not need. Feel free to download it and extend it in any way you see fit as long as you link back to this site. Use it at your own risk! All I can say is that I have used it exclusively for my e-mail the last few days and I have successfully used Microsoft Terminal Server via a http proxy over a slooooow link.

How it worksThe Socket Proxy consists of two parts: a server and a client. The client makes a http request to the server passing the server and port it would like to talk to. The server opens the connection to the remote host/port and stores the socket in the session if the client is allowed to do it. Multiple calls are made to proxy.aspx to proxy the actual payload before the client or server closes the connection. Close.aspx is use to close and clean up socket and session data.

- Socket Proxy Server -The Socket Proxy server is implemented in ASP.NET. Thanks to the extensive .NET libraries it is -tiny-. There are 3 aspx files (open.aspx, proxy.aspx, close.aspx) and ~500 lines of C# code, comments included! A cup of coffee is enough to go through the code.

- Socket Proxy Client -The client is bigger than the server as I got carried away and added a notification icon with statistics and some other features that are not really needed. The client can be configured to run as a normal windows form or as a notification icon only and supports a http proxy with/without authentication. The total code is ~1.000 lines of C#.

How to use itEh…I will expand this section when I have some more time. You are pretty much on your own for now but you should have no problems if you are used to .NET .config files.

- Server -The server can be xcopied to an existing ASP.NET site or you can create a new virtual directory. Edit web.config to decided which sites you want to proxy to. Add a new /configuration/appSettings key for each remote host you want to enable:

Set the key to “host:port:“, for example “loalhost:81“

Set the value to the users have access to to the service. Use “*“ for everyone or the user authenticated in IIS otherwise (implemented but not rested)

- Client -Edit the provided example SocketProxy.xml file. It consists of two main sections that let you control the uplink proxies and the ports to proxy.

Proxy: The client matches the “client“ regular expression against the local IP(s) and chooses the first match. No proxy is used if there is no match. Leave user and password blank if no authentication is required.

Port: The client listens to each configured port node on the port specified in the number attribute. You can configure:

baseUrl: the url of the ASP.NET server described earlier in this document

remoteHost/remotePort: the remote host and port you want to proxy to

user/password: used for basic authentication against the ASP.NET site. Use https as basic security passes the credentials in “clear text“

clientPoll: how long to wait for a data from the client before sending an empty request if there is no data.

noTrafficSleep: how long to wait if no data was exchanged in the last request

The last two parameters lets you tune the performance of the system.

Where can I download the codeYou can download the complete source code and binaries below. As I mentioned before; the client is -very- basic as it implements the features I need. I am very happy with it as it does what it should do, I save money and I learned something new implementing it.

Final notesLet me know if you find any problems in the code or if you improve it in any way. I would like to integrate the improvements in my code or link back to site(s) with extended versions.

Last Updates

2006/04/06: Added Basic authentication support to the clientThe server already supports Basic authentication so I added a couple of lines to the client to support it as well. Steps needed to use Basic authentication:

Enable basic security on the web site

Configure basic authentication on the client using the optional authentication settings

<addkey="port-authentication"value="basic"/>

<addkey="port-user"value="MySPClient"/>

<addkey="port-password"value="whatever"/>

Optionally configure the "allowed" setting in Web.Config. This is an optional step as you may choose to configure the user-by-user access using the security settings on the web site instead

I strongly suggest creating a user that does not have access to anything on your server apart from read/only access to the web application. This is particularly important in this basic version as the user name and password are stored in clear text in the configuration file. The application can be extended to store the credentials in protected storage or ask for them the first time they are needed but it is not a priority for me at the moment as:

I store the app on removable storage I always keep with me

The configured users cannot do anything on the remote systems. They can open the tunnel but they still have to authenticate against the back end system

2007/09/30: New configuration file Updated the client with the following new features:

Automatic proxy configuration by client IP. Changes to the client IP is detected live so there is no need to restart the client

New parameters for tuning performance.

Moved configuration from app.config to a .xml file in the same directory as the client. This makes the configuration easier to read and you can make changes on the fly as the file is parsed on each incoming connection.

Friday, March 24, 2006

How to run Macromedia Flash as "limited user" in Windows XP

I bought a PC from my ex colleague Marco earlier this week, so I have spent the last few nights configuring it to suit my needs. I configured it to use the standard "welcome screen" and "limited user" rights for the kids to keep it simple yet secure. It went pretty smooth apart from the program the kids use the most: Flash. They frequently visit WinxClub and Kinder but the flash based games they love refused to run. No "security warnings", just an ugly X where the flash game should be. Adding the sites to the “Trusted sites“ didn't work either.

RegMon came to the rescue again, and I found the problem: you have to change the security permissions on Macromedia Flash in the registry to make it work in Internet Explorer (I have not tried with Firefox). The following steps fixed the problem for me:

Run regedit.exe

Go to HKEY_CLASSES_ROOT\MacromediaFlashPaper.MacromediaFlashPaper\CLSID

The "(default)" value should be a guid like {D27CDB6E-AE6D-11cf-96B8-444553540000}

Open HKEY_CLASSES_ROOT\CLSID\{D27CDB6E-AE6D-11cf-96B8-444553540000}

Right click the key {D27CDB6E-AE6D-11cf-96B8-444553540000} and select “Permissions...“

Add the "Users" group (or the individual users you want) and give them read access

Believe it or not; this week was the first time in my life I used Windows XP. I have always used the server editions of Win2k and Win2k3 on my laptops for development work. I am sure there are a lot more "surprises" waiting for me...

Tuesday, March 21, 2006

Web Service method name is not valid error using HTTP GET

I just learned something new about using HTTP GET to access .NET web services. HTTP GET returns a "Web Service method name is not valid." error if you pass arguments by reference.

Why use HTTP GET? Calling Web Services via HTTP GET can be useful for stress testing with Microsoft ACT. The systems engineers can record a simple script calling multiple web services with different arguments in no time. It is possible to use HTTP POST in Microsoft ACT but it requires some coding skills.

After modifying the test method a few times I found the problem; arguments by reference is not supporte when using HTTP GET. Why? I don't know. I can understand that complex arguments like objects are not supported but I cannot see why ref arguments are broken since the return value is passed in the output XML.

I worked around the problem by implementing a full Web Service client using HTTP POST.

Sunday, March 19, 2006

Welcome to Italy Egil!

A decade after I arrived in Italy I got a "welcome letter" from the mayor of the town I moved to:

Dear citizen.The Municipality of Paderno Dugnano has been working for some years in favour of the integration of foreign citizens.

It is now my pleasure to send you the guide to services where you can find useful information for everyday life.

I would also like to inform you that you can telephone for whichever foreign information to the shop at the following numbers … and …

Trusting in a future of mutual acquaintance and collaboration. Yours faithfully

Some people may see this as a waste of tax payers money as the project has been sponsored (i.e. paid) by the region of Lombardia. I think it is a good idea though, and I wished I had the booklet that came with the letter when I arrived 10 years ago. The booklet has a handy reference section with phone numbers and addresses. It also explains all the quirks and expressions of the Italian byrocracy. And believe me, there is a lot of it. The situation has improved the last few years but I don't know how many days I have wasted in various public offices, some times just to be sent to a different one.

Wednesday, March 15, 2006

Microsoft Action Pack Subscription

I learned about a Microsoft "program" I did not know of while attending a conference on Microsoft SQL Server 2005. The Microsoft MAPS program for partners is great news for consultants and trainers on Microsoft technologies. The Microsoft Action Pack Subscription gives you access to 25.000 euro worth of software licenses, including Office, Windows 2003 etc for 320 euro

The Microsoft Action Pack Subscription is a benefit that's available to Registered Members of the Microsoft Partner Program who promote Microsoft software or provide solutions based on Microsoft software and technologies to their customers.

Becoming a Registered Member is free and enrollment only takes a few minutes.

Your Action Pack Subscription entitles you to core internal-use software. You will be licensed to use this software for internal business purposes, application development, and testing.

What more can a consultant ask for? 320 euro for an "all you can eat" buffet of Microsoft software to study and learn play with the latest software updated quarterly.

The advancement in German encryption techniques led to significant Allied losses in the North Atlantic throughout 1942. The three unsolved Enigma intercepts were published in a cryptography journal in 1995 and have intrigued enthusiasts ever since. …Mr Krah told the BBC News website that "basic human curiosity" had motivated him to crack the codes, but stressed the debt he owed to veteran code breaking enthusiasts who have spent years researching Enigma.

"The most amazing thing about the project is the exponential growth of participants. All I did myself was to announce it in two news groups and on one mailing list." ...Stefan Krah's computerised codebreaking software uses a combination of "brute force" and algorithmic attempts to get at the truth. The combined approach increases the chances of stumbling across a match by recreating possible combinations of plugboard swaps while methodically working through combinations of rotor settings.

Wednesday, March 1, 2006

WMI code creator

WMI Code Creator is a great tool for exploring and working with Windows Management Instrumentation. Not only does it allow you to browse the name spaces but it also generates code in VBSCript, C# or VB.NET that you can use in your projects. The download includes the full source code (~10.000 lines of C# code)

Using the tool, you can query for management information such as the name and version of an operating system, how much free disk space is on a hard drive, or the state of a service. You can also use the tool to execute a method from a WMI class to perform a management task. For example, you can create code that executes the Create method of the Win32_Process class to create a new process such as Notepad or another executable. The tool also allows you to generate code to receive event notifications using WMI. For example, you can select to receive an event every time a process is started or stopped, or when a computer shuts down.