locked
Why does StreamSocket::ConnectAsync set up two TCP connections when proxy is configured in system?

    Question

  • Hello, Dear all,

    Per my test, the proxy for HTTPS will be selected as the actual used one for the out-going packets if we do the following test in an corporate network environment. Two connections will be set up: one is with the proxy, the other one is with the target address.

     

    Some info about my env:

    1. the configured proxy could only be accessed in the corporate network;

    2. the target host has both private and public IPs;

    3. I don't check whether there is proxy configured in code.

    4. the issue could only occurr in the private network; If I do the test out of the corporate network, the behavior is correct because no proxy is configured. But I am not sure whether the issue would occur if there would be a usable proxy configured.

     

    The repro steps are:

    1. Create a Windows Store App project with VS2013. The testing code is pretty simple as the following:

       using namespace Windows::Networking::Sockets;
       StreamSocket^ streamSock = ref new StreamSocket();
       IAsyncAction ^sconn = streamSock->ConnectAsync(
          ref new Windows::Networking::HostName("10.1.2.3"), "56789",
          SocketProtectionLevel::PlainSocket);

    The target address and port (10.1.2.3:56789) could be any meaningful or bad one. We only need to observe the packet sent out from the client side in the following steps.
     
    2. Configure the proxy in Internet Options -> Connections -> LAN Settings -> Advanced -> Secure. Give a good proxy/port to it;

    2.1. Run the program and capturing the packet from Wireshark or other tools.
       ==> You will see that a HTTP request with header "CONNECT" is sent to the proxy. That's to say, the client will connect to the proxy.
       ==> You will also see that the client side also sent out a TCP SYN packet to the remote target address (10.1.2.3:56789).

    3. Disable or remove the proxy setting;

    3.1. Run the program and capturing the packet from Wireshark or other tools.
       ==> You will see that there would be no HTTP request sent out.
     
    I am using Win8.1/VS2013 and the system is up-to-date... I am not sure the behavior is designed as this, or it is a bug of the StreamSocket?

     

    BTW: I didn't use Windows::Networking::Connectivity::NetworkInformation::GetProxyConfigurationAsync on purpose.

     

    For the classical WinSock, we could only see the TCP SYN packet in step 2. That's to say, the behaviors between StreamSocket and WinSocket are different.

     

    Thank you all.

          





    • Edited by B0L Wednesday, March 26, 2014 12:30 PM
    Tuesday, March 25, 2014 6:17 AM

Answers

  • This is by design and was added in Windows 8.1. It's a feature referred to as "proxy tunneling" and is intended to allow an app to work seamlessly in a corporate environment without it being aware that a connection through a proxy may be required. The two connections you see are intentional. We do this to avoid latency... the first one to succeed wins.

    Can you elaborate a little how this is negatively impacting your app? Ultimately, the connection should be established with the remote endpoint. Whether or not a proxy was involved should be invisible to the app (but of course, visible to WireShark).


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Marked as answer by B0L Tuesday, April 1, 2014 1:00 AM
    Friday, March 28, 2014 5:36 PM

All replies

  • Is this affecting an application in some way? 

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Wednesday, March 26, 2014 12:24 PM
    Moderator
  • Hi, Matt, thank you very much for the reply. Yeah, the connection to the proxy makes our program go bad in the network layer packet recv loop.

     

    But why there would be any two connections sent out? This behavior is totally unreasonable. If there is no specific configuration, I would assue that the ConnectAsync has done much thing that are unknown to us. I've tried the classical WinSocket, only one connection to the target address will be set up.

    Wednesday, March 26, 2014 12:35 PM
  • Hi, Matt,

     

    Is there any app in the WinStore that uses the StreamSocket (and ConnectAsync)? I've tried several apps but non of them reproduces the issue I've encountered. So I am not sure whether they are using the StreamSocket.

     

    Another uncertain thing is that: if the above store apps are using a higher level network API, such as HttpClient, that means there should be some configurations that I've missed for StreamSocket because I think whether we use the lower or higher network API, the behavior should be the same for TCP handshake at least.

    Thanks.




    • Edited by B0L Thursday, March 27, 2014 10:26 AM
    Thursday, March 27, 2014 12:49 AM
  • Would anyone give me some hints? Thanks.
    Friday, March 28, 2014 11:06 AM
  • I'll ask our networking guru to look at this thread.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.



    Friday, March 28, 2014 1:41 PM
    Moderator
  • This is by design and was added in Windows 8.1. It's a feature referred to as "proxy tunneling" and is intended to allow an app to work seamlessly in a corporate environment without it being aware that a connection through a proxy may be required. The two connections you see are intentional. We do this to avoid latency... the first one to succeed wins.

    Can you elaborate a little how this is negatively impacting your app? Ultimately, the connection should be established with the remote endpoint. Whether or not a proxy was involved should be invisible to the app (but of course, visible to WireShark).


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Marked as answer by B0L Tuesday, April 1, 2014 1:00 AM
    Friday, March 28, 2014 5:36 PM
  • Hi, david, thank you very much for your reply!

     

    The caused problem is: the proxy will issue a connection to our remote server.

    The scenario in our app is: in our remote server, it will create an overlapped IO recv loop. If a connection request comes in, it will accect the connection and stop the recv. So if the request from the proxy comes to our remote server comes earlier than the second end-to-end request, the latter will surely fail.

     

    Yeah, we may argue that the design of our remote server, but the current solution is the final decision after many choices and balances. We are still looking for a solution while I am putting the question in this thread.

     

    Thanks!



    • Edited by B0L Monday, March 31, 2014 3:54 AM
    Saturday, March 29, 2014 10:43 PM
  • Is there any way of turning off this Proxy Tunneling feature?  (In fact, is it actually documented anywhere?  The only reference I've found online to this feature is in this thread!)   We also use an outgoing tcp connection to one of our servers (using our own protocol over TCP/SSL) and when the "proxy" connection gets there first, the TCP connection is basically locked out.

    As an aside, why is this "feature" implemented at the TCP layer?  Proxies are generally configured for HTTP/port 80  and it looks like your Proxy Tunneling feature makes that assumption by sending out an http CONNECT anyway?

    And when is WinSock coming back fpr Win RT?  The Microsoft climbdown announcement last month said that changes were coming that would make it easier to port existing apps from other  platforms but I haven't seen any followup announcements or other details ....

     
    Tuesday, April 29, 2014 10:23 PM
  • Unfortunately, there is no direct way to turn off the proxy tunneling feature. An indirect way would be to include a DIRECT entry as a final fallback in the PAC script, but of course this would only work if you have control over the PAC script where the app is deployed.

    We are using this feedback as we plan changes for a future release.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, May 5, 2014 11:36 PM
  • A workaround to avoid proxy connection requests from being sent out is to use the ConnectAsync(Hostname, String, SocketProtectionLevel, NetworkAdapter) method with a specific adapter. The proxy-related logic is disabled when a specific network adapter is selected.

    You can retrieve the main active network adapter by calling GetInternetConnectionProfile() and then referencing the NetworkAdapter property of the returned information:

    ConnectionProfile^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
    NetworkAdapter^ adapter = connectionProfile->NetworkAdapter;

    You could also enumerate all possible adapters and try to connect on each of them, one by one:

    for each (HostName^ localHostInfo in NetworkInformation::GetHostNames())
    {
        if (localHostInfo->IPInformation != nullptr)
        {
            NetworkAdapter^ adapter = localHostInfo->IPInformation->NetworkAdapter;
            // Attempt to connect with this adapter.
        }
    }

    Saturday, June 28, 2014 2:13 AM
  • I run into this issue as well,  i will try the workaround, thanks to Diego Perez Botero.

    But i really hope Microsoft could officially fix it ASAP. 

    Thursday, July 3, 2014 6:46 AM
  • You'll be glad to hear that we have introduced a new StreamSocket control option in Windows 10 that can be used to alter the proxy tunneling behavior: StreamSocket.Control.SerializeConnectionAttempts

    When set to true, the WinRT StreamSocket will only attempt a proxy connection if the direct connection attempt fails.

    Monday, April 20, 2015 7:55 PM
  • Hi, Diego,

    Thank you very much for your info! Yeah, it is exciting news.


    Tuesday, April 21, 2015 8:06 AM