I have written a winforms client, that connects to a Windows service establishing a connection with XSockets.Net. This is working fine for a direct connection to the internet.
But when there is a proxy server, it will fail.
As I checked the XSockets API I have not found any settings, that allows me to use a proxy server.
Also for the websockets protocol I have not found a sufficient answer.
Any ideas?
Use WSS:// for connection, that is the equivalent to HTTPS in WebSocket.
The WebSocket protocol handshake sends the HTTP headers "Upgrade:websocket" and "Connection:Upgrade", meaning that the proxy will probably remove the "Upgrade" header because is set as a "Connection" header. By using a secure protocol, the proxy won't be able of intercept the request and will just let it pass.
Cheers.
Related
I hava a self-hosted wcf service which is configured for ssl.
The certifiacate is bound to the port of the service by commandline,
using the 'netsh' command, e.g.:
netsh http add sslcert ipport=0.0.0.0:8000 certhash=XYZ appid={"ABC"}
This is described here:
http://msdn.microsoft.com/de-de/library/ms733791(v=vs.110).aspx.
It works as expeced.
Now I just discovered that there is a SetCertificate-Method:
http://msdn.microsoft.com/de-de/library/system.servicemodel.description.servicecredentials.servicecertificate(v=vs.110).aspx
So, I thought I can make use of this method, and do not need the netsh comamnd
for binding the certifiacte anymore.
But it does not work? SetCertificate seems to have no effect?
So what else is it used for?
Am I missing something?
I think I can answer my own question. Found the answer here:
http://msdn.microsoft.com/de-de/library/ms789011(v=vs.110).aspx
If the transport is HTTP (using the WSHttpBinding), SSL over HTTP provides the transport-level security. In that case, you must configure the computer hosting the service with an SSL certificate bound to a port, as shown later in this topic.
If the transport is TCP (using the NetTcpBinding), by default the transport-level security provided is Windows security, or SSL over TCP. When using SSL over TCP, you must specify the certificate using the SetCertificate method, as shown later in this topic.
So the SetCertificate method is only used when Transport is TCP. In my case it is Http, so I have to bind the Certificate to the port manually as I did.
I am writing a proxy with TcpListener in C#.
This proxy listens a port that users send request to. And when accepted a user request, it will parse the request header and find the host name. Then it creates a TcpClient to the host server.
Here comes the problem. When http request comes, it should connect the port 80 of the server; while https request comes, it should connect the port 443 of the server. But I have no idea of how to distinguish http request and https request.
Question in one sentence: how to know it is a http request or https request that TcpListener accepted?
Many thanks!
You've stepped in a problem that has flustered web server administrators for a long time.
Here's the process:
Web browser establishes a TCP connection to a particular IP on the web server.
The web server knows what IP it's getting a connection from, knows that that IP is only ever used for secure.example.com, and so loads the SSL certificate for secure.example.com.
The web server and web browser negotiate a SSL connection.
The web browser sends vanilla HTTP headers down the SSL pipe, which include the "HOST: secure.example.com" line that indicates the virtual host to use.
The web server processes the request and sends the response using vanilla HTTP headers sent down the SSL pipe.
The web server has to decide which virtual host to use before it has any HTTP headers. This is because it has to negotiate an SSL connection first, and it has to know which certificate to use first. The vanilla solution is to use IP-based virtual hosts - run the web server on IP address X; whenever the server gets a request sent to address X, it knows the request belongs to the configured vhost for that address.
The problem with that scheme is that the server has to have separate IP addresses for each secure website it runs. That might be many, many IP addresses, and is either costly or impractical.
Step in Server Name Indication. When the web browser is negotiating the SSL connection to the web server, the web browser includes the hostname it wants to connect to in the SSL negotiation information. Now the web server can use that information to do normal name-based virtual hosts, and so the web server can run a thousand different secure websites each with their own SSL certificates all on exactly one IP address. Everything is right in the world again.
You want to get in the middle of this, which means that you have to understand the SSL/TLS negotiation phase, parse the server name information, and forward the request down to the right web server.
Your new flow looks something like this:
Web browser establishes a TCP connection to the proxy.
Proxy begins recording the SSL exchange.
Web browser starts to do SSL negotiation, and as part of such, sends the Server Name Information down.
The proxy parses the Server Name Information, decides which web server should handle the request, and forwards the SSL negotiation information to the web server.
The proxy does not otherwise participate in the negotiation; it reads the SNI, but otherwise is completely "pass-through".
The web browser and server complete the SSL negotiation, the server picks the right vhost, and the browser sends vanilla http headers for a request.
The web server reads the vanilla headers via the SSL connection, and processes the request.
Now that that's been said, you might realize that sticking your nose in the SSL connection negotiation might be more trouble than it's worth. Turns out a few other people have already had the same idea as you and have implemented a few programs that seem to do exactly what you're trying to do - do a search for "http sni proxy" - I came up with this: https://github.com/dlundquist/sniproxy
The headers are entirely encrypted. The only information going over the network 'in the clear' is related to the SSL setup and D/H key exchange. This exchange is carefully designed not to yield any useful information to eavesdroppers, and once it has taken place, all data is encrypted.
Update By the way After the SSL negotiation, normal HTTP headers will travel inside the encrypted stream, so there is really no difference between the two.
I have an asp.net application working in https (SSL). This is working well in my local computer and Amazon AWS(production environment).
But when I host this application in office (for testing) some strange things happens.
I can see the https in browser and the lock sign.
Fiddler also showing that the output is encrypted and shows port 443.
But HttpContext.Current.Request.IsSecureConnection returns false
And HttpContext.Current.Request.Url.Scheme returns http.
In the office we are using Juniper SSG firewall and TMG 2010 (Forefront Threat Management Gateway 2010). So server receive request through Juniper and TMG 2010. Thanks in advance.
To reduce costs I suspect that the SSL certificate is installed on the TMG Gateway and that this gateway is simply rewriting the request to standard HTTP when passing it to the actual web server. So by the time the request hits IIS and your web application it is a standard plain HTTP request.
This tripped my up after deploying to Amazon's Elastic Beanstalk environment. I couldn't see any way to get the load-balancer to allow the SSL request straight through to the server. Instead it was always terminating the SSL at the load-balancer and passing plain http back to the server.
I found this documentation: Elastic Load Balancing Concepts - X-Forwarded Headers.
Essentially the load-balancer injects a number of additional HTTP Headers into each request before forwarding it to the back-end server. The most relevant one is X-Forwarded-Proto which tracks the protocol used to connect from the client's browser to the load-balancer. This can be checked like so:
var loadbalancerReceivedSSLRequest = string.Equals(Request.Headers["X-Forwarded-Proto"], "https");
var serverReceivedSSLRequest = Request.IsSecureConnection;
if (loadbalancerReceivedSSLRequest || serverReceivedSSLRequest)
{
// SSL in use.
}
else
{
// SSL not in use.
}
Well another way to check is to check the port
if(context.Request.Url.Port == 443)
Note: check which port is used for secure connections, usually it is 443
In my corporate environment there is a transparent proxy that requires credentials for internet access (every four hours). In my application I successfully passed credentials like this:
var client = new WebClient();
client.Credientals = new NetworkCredential("username", "password");
string result = client.DownloadString("http://...");
// this works!
However, when my intial request is to a "https://" url, there is an Exception throw: "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
Now my current work around is to:
catch the WebException thrown when accessing the "https://" url
add my Credentials to a new request to an arbitrary "http://" site
(this should "open up" the internet for a four hour window)
go back and re-try the "https://" request
I am wondering if there is a better/cleaner way to do this?
What you are using right now is an HTTP proxy with authentication. So far so good. But it won't work for HTTPS requests, and here's why:
SSL/TLS is endpoint security. This means that the data must be sent between the client and the server via the single encrypted channel.
When you connect to the HTTP proxy, you tell it "GET the remote resource and send it to me", which contradicts to endpoint security. Here you don't have direct connection to the remote server and you can't validate its credentials. Also the proxy can peep into your data.
In general, it's possible to connect to regular HTTP proxy using HTTPS OR it is possible to ask the HTTP proxy to access HTTPS resource, but this breaks security cause in both cases the client can't validate server's credentials and HTTP proxy can log or alter the data being transferred.
HTTPS proxy works in a different way. Here you tell the HTTPS proxy server "CONNECT to remote address and then only resend whatever is passed". This way the proxy creates an opaque secure channel between the client and the server thus preserving endpoint security. Actually, HTTPS proxy can be used to tunnel any traffic, not necessarily SSL.
Consequently you need to establish the tunnel by sending CONNECT request (with your authentication included), and then send regular HTTP GET (without host/address in the URL) over the same channel - this request will go to the destination server, not to the proxy.
I have serious doubts that your WebClient can be made to establish a tunnel before sending a request. As an option, you can use HTTPBlackbox package of our SecureBlackbox product which lets you access HTTP and HTTPS resources, and supports HTTPS proxies (called WebTunneling in SecureBlackbox) with authentication.
My need is to communicate between 2 client behind NAT using http tunneling. Is it possible? What all setup is needed to achieve this (like http proxy server etc.)? Is there any library or sample code available for implementing http tunneling over TCP in C#?
It might be possible for you to use this library:
http://granados.sourceforge.net/
It supports port forwarding (tunneling in this case),
but I haven't tried it myself.
It's an SSH library... so if you can set up an SSH server on either end of the connection
you'll be able to establish an SSH connection and create a tunnel.