Visual Studio makes programming Web Services a breeze. However, if you, like me, offer programs for download that uses Web Services, you will notice that various content filtering devices like firewalls and proxy servers sometimes block the Web Service calls. Ordinary HTTP traffic is almost always allowed, but some firewalls and proxy servers are (mis)configured to block various content-types - in regards to Web Services, the content-type "text/xml".
This article describes an easy, one line solution for how to bypass content-filtering blockages of SOAP messages.
When you develop systems for the business and/or consumer market, it is imperative that the system works without the need for the user to take special actions in order to get the system to work. As a developer of server based shareware that communicate through the use of Web Service calls to a centralized database, I sometimes get comments from users who couldn't get the system to work. During installation, I already test whether or not HTTP communication is allowed - but this was shown to be inadequate. One could have switched to another communication protocol than SOAP - but then the strongly typed interfaces would disappear. As ordinary HTTP communication is almost always allowed, I needed to find a way to make SOAP messages appear as ordinary HTTP traffic to bypass the content filtering mechanisms.
The solution I chose was to use the Pluggable Protocol interface found in the
Through the use of Reflector and Ethereal, I got a pretty clear picture of how Web Service calls are done in the .NET framework - however, it was this Microsoft article that gave me the idea for the solution.
The article How to Write a Pluggable Protocol to Support FTP in Managed Classes by Using Visual C# .NET describes how you can create your own web protocol. The idea behind this is to wrap the logic needed to support a given protocol in a black box - and let the higher levels of the system communicate indifferent of the actual protocol used.
Design of SOAP Relay Protocol
The protocol designed takes a SOAP request, and encodes it as an ordinary HTTP POST as if it was a standard HTML form that was posted. The content is sent to a proxy page located in the DMZ - which then unwraps the message and relays the message to the desired end-point. Empirical tests have shown that encoding isn't necessary for the SOAP response when it is returned in raw form.
The following three properties have been identified as necessary for the protocol to work:
- URL of the Web Service to call
- The SOAP body
Using the code
To use the code, include the code, and register the protocol prefix in the framework and the location of the proxy page which you have put on a server in the DMZ.
Wherever you want to relay SOAP calls through the proxy, just replace "HTTP:" with the protocol prefix "SOAPPROXY:".
using( MyWebservice.TestWebService websvc = new MyWebservice.TestWebService() )
bool cont = true;
bool usesSoapProxy = false;
websvc.Url = "HTTP://myserver2/MyWebservice.asmx";
while( cont )
return websvc.TestMethod("string1", "string2");
if( !usesSoapProxy )
websvc.Url = websrv.Url.Replace("HTTP:", "SOAPPROXY:");
usesSoapProxy = true;
cont = false;
The code presented in this article has support for both .NET Framework 1.1 and .NET Framework 2.0 - but because of changes to the
HttpWebRequest interface, remember to define the "Conditional Compilation Constant" NET20 if you are going to use it with .NET Framework 2.0.
Points of interest
The SOAP Relay Protocol encodes the destination URL, the SOAPACTION header, and the actual SOAP body as HEX in order to send it as a payload in a standard HTTP POST. Because of the use of HEX, the request will double in size.
If you log the IP address on the destination URL, please be aware that this will be that of the proxy page and not the source client.
The framework for the SOAP Relay Protocol is derived from the source code presented in the Microsoft article: How to Write Pluggable Protocol to Support FTP in Managed Classes by Using Visual C# .NET, but has been modified quite a bit.
One hurdle was how to create an
HttpWebRequest from scratch. Paulo Morgado shows how to do this in his article: HTTP compression in the .NET Framework 1.1 - and based on his ideas, I have made some small modifications in order to make it fit the SOAP Relay Protocol.
The real "magic" is done in the class
ProxyWebRequest. It is derived from
HttpWebRequest, and maintains a
MemoryStream (embedded as the class
ProxyStream) to which the SOAP request is written by the .NET framework. The SOAP request is encoded and sent when the .NET framework calls
GetRequestStream() which encodes the request, sends it, and returns the response back to the .NET framework.
You are free to use this code in any way you wish - both in freeware and commercial programs - free of charge. A small link in an About box etc. will be appreciated - but it is not required.
- 2007-03-06: Initial release.