* 
 * 
 * 



Hi,

 

I have been discussing this a bit with Samuli, to see if it makes sense – and 
it seems that perhaps it does, so let me raise this with the development folks 
to get your thoughts. Hopefully this is something that would help OpenVPN (or 
at least that’s my intention!). 

 

I use OpenVPN with a Windows client, and I tend to be on one network one 
minute, another the next. One time with a proxy, the next time without … so I 
really want OpenVPN to automatically detect the proxy (if there is one), and 
apply it … for every connection restart, client open, etc. My thinking is to 
add a new option, say something like “auto-proxy” (so this won’t break anything 
that is already working!). The idea being that if this option is enabled, then 
on every connection / reconnection attempt OpenVPN will first check the proxy, 
and then apply it for the actual connection back to the server. Hopefully this 
makes sense so far … J.

 

To try to help with this, I wrote a small application that detect the Windows 
proxy settings (even working with PAC files!), based on WinHTTP. I have 
attached the code to this email, so you can take a look at comment (BTW, it 
builds just fine in Visual Studio Express 2010). A few thoughts on this code,

- feel free to try it on various configurations and machines (and provide 
feedback of course!). However, it may not need to be bulletproof before it's 
included (but feel free to disagree!), as it’s disabled by just by not using 
the (new) auto-proxy option.

- I have tried it on Win XP and Win 7, with a proxy PAC file ... both on and 
off the network (so with and without proxy). It works fine in all these cases 
(and gets the right answer ... :-)).

- I'm not sure how you use proxy in your code. At least with the PAC file that 
I go through, I get a response back of the format 
proxy.domain.net:8080;10.10.10.10:8080. We may need to parse this (again, just 
not sure how you use it).

- I have not implemented asynchronous processing. It can be done, but not sure 
it buys much, as you can't proceed until the proxy information is available. I 
also haven't modified the WinHTTP timeout. Again, this can be done if needed 
(but the response is typically quite quick).

- the slew of messages that I have put in the code are just FYI for now. These 
could be split to console output, or logging, or just removed.

Whatever folks prefer.

 

So - please take a look at let me know. I’m not sure exactly how it would be 
integrated in to the OpenVPN code, as I don’t have the big picture of that. But 
I’m sure someone else does, and I can modify this as needed to get to that 
point.

 

Thanks,

… Russell

 

 
/**********************************************************************************

Utility: AutoProxy - automatically determine Windows Proxy (example for OpenVPN)
Author : R. Morris
Vesion : 1.00

Reference Information:
1) C++ Character Constants
http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(L);k(DevLang-%22C%2B%2B%22)&rd=true

2) WinHTTP Functions:
WinHttpOpen Function                          : 
http://msdn.microsoft.com/en-us/library/aa384098(v=vs.85).aspx
WinHttpGetProxyForUrl Function                : 
http://msdn.microsoft.com/en-us/library/aa384097(v=vs.85).aspx

2) WinHTTP Structures:
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG Structure: 
http://msdn.microsoft.com/en-us/library/aa384250(VS.85).aspx
WINHTTP_AUTOPROXY_OPTIONS Structure           : 
http://msdn.microsoft.com/en-us/library/aa384123(v=vs.85).aspx
WINHTTP_PROXY_INFO Structure                  : 
http://msdn.microsoft.com/en-us/library/aa383912(v=vs.85).aspx

************************************************************************************/

#include <Windows.h>
#include <winhttp.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>

// Include WinHTTP Library
#pragma comment(lib, "winhttp.lib")

void main()
{
        LPWSTR lpszURL;                                                         
                                        // LPWSTR: Input URL (pointer to 
Unicode string, to search for Proxy)
        HINTERNET hSession;                                                     
                                        // HINTERNET: Session Handle (for HTTP 
Open)
        WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyConfig;                     
        // Structure: IE Proxy Configuration (for current user)
        WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;                             
                // Structure: AutoProxy Options
        WINHTTP_PROXY_INFO AutoProxyInfo;                                       
                        // Structure: WinHTTP (Auto)Proxy Information
        BOOL bURLResult;                                                        
                                        // Boolean: URL Result (from Get HTTP 
Proxy Call)
        long errNum;                                                            
                                        // Long: Error Number (from WinHTTP 
Call)
        LPCWSTR lpszDefaultURL = L"http://www.openvpn.net";;                     
        // LPCWSTR: Default URL

        // Get input from user for site to check proxy for (as proxy can be 
site dependent)
        lpszURL = (LPWSTR)GlobalAlloc(GMEM_FIXED, 512);
        wprintf(L"URL to check Proxy for [%s]: ", lpszDefaultURL);
        _getws_s(lpszURL, 256);

        printf("\nStarting Proxy processing ...\n");
        if (wcslen(lpszURL) == 0) {
                wprintf(L"   Empty URL, using default entry [%s]\n", 
lpszDefaultURL);
                wcscpy_s(lpszURL, 256, lpszDefaultURL);
        }

        // Retreive Internet Explorer Proxy Configuration (for Current User)
        ZeroMemory(&AutoProxyOptions, sizeof(AutoProxyOptions));
        ZeroMemory(&AutoProxyInfo, sizeof(AutoProxyInfo));

        printf("   Retrieving Internet Explorer Proxy Configuration (for 
Current User) ...\n");
        if (WinHttpGetIEProxyConfigForCurrentUser(&IEProxyConfig) == TRUE) {

                // Set Options for Internet Explorer = Automatically Detect 
Settings (1st Priority)
                if (IEProxyConfig.fAutoDetect == TRUE) {
                        printf("   Internet Explorer calls for AutoDetect\n");
                        AutoProxyOptions.dwFlags = 
WINHTTP_AUTOPROXY_AUTO_DETECT;
                        AutoProxyOptions.dwAutoDetectFlags = 
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
                        AutoProxyOptions.fAutoLogonIfChallenged = TRUE;

                // Set Options for Internet Explorer = Use Automatic 
Configuration Script (2nd Priority)
                } else if (IEProxyConfig.lpszAutoConfigUrl != NULL) {
                        printf("   Internet Explorer calls for Auto 
Configuration Script\n");
                        AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
                        AutoProxyOptions.lpszAutoConfigUrl = 
IEProxyConfig.lpszAutoConfigUrl;
                        AutoProxyOptions.fAutoLogonIfChallenged = TRUE;

                // Set Options for Internet Explorer = Proxy Server (3rd 
Priority)
                } else if (IEProxyConfig.lpszProxy != NULL) {
                        printf("   Internet Explorer calls for (defined) Proxy 
Server\n");
                        AutoProxyInfo.dwAccessType = 
WINHTTP_ACCESS_TYPE_NAMED_PROXY;
                        AutoProxyInfo.lpszProxy = IEProxyConfig.lpszProxy;
                        AutoProxyInfo.lpszProxyBypass = 
IEProxyConfig.lpszProxyBypass;

                // Set Options for Internet Explorer = No Proxy Options Defined 
(so no proxy!)
                } else {
                        printf("   Internet Explorer does not define any proxy 
options\n");
                        AutoProxyInfo.dwAccessType = 
WINHTTP_ACCESS_TYPE_NO_PROXY;
                }

        } else {
                // Retrieving Internet Explorer Configuration failed, so try 
Auto Detection!
                printf("   Internet Explorer Configuration Read Failed (so 
attempt Auto Detection!)\n");
                AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
                AutoProxyOptions.dwAutoDetectFlags = 
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
        }

        // Now, retreive Proxy information based on Internet Explorer 
Configuration (if appropriate)
        if (AutoProxyOptions.dwFlags != 0) {

                // Need to create a temporary WinHttp session handle -> Note: 
performance of GetProxyInfoForUrl can be improved by saving this hSession 
handle across calls instead of creating a new handle each time
                printf("   Opening WinHTTP Session\n");
                hSession = WinHttpOpen(L"OpenVPN AutoProxy Check", 
WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 
0);

                // Get Proxy Details for Target URL
                printf("      Getting Proxy Details for Target URL ...\n");
                bURLResult = WinHttpGetProxyForUrl(hSession, lpszURL, 
&AutoProxyOptions, &AutoProxyInfo);

                // Evaluate Results from URL Specific Proxy check
                if (bURLResult == TRUE) {
                        // Successful, retrieve Proxy details
                                printf("      Proxy Query Successful, Retrieved 
Proxy for URL!\n");
                } else {

                        // Proxy retreival failed, so get error number (to 
determine why it failed) ... and set for no Proxy (as call failed)
                        printf("      Proxy Query failed, retreive Error 
Code\n");
                        errNum = GetLastError();
                        AutoProxyInfo.dwAccessType = 
WINHTTP_ACCESS_TYPE_NO_PROXY;

                        // And display error information (to examine why it 
failed)
                        printf("      WinHTTPGetProxyForURL Error: ");
                        switch (errNum) {
                                case ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR:
                                        
printf("ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR\n");
                                        break;
                                case ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT:
                                        
printf("ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT\n");
                                        break;
                                case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE:
                                        
printf("ERROR_WINHTTP_INCORRECT_HANDLE_TYPE\n");
                                        break;
                                case ERROR_WINHTTP_INTERNAL_ERROR:
                                        
printf("ERROR_WINHTTP_INTERNAL_ERROR\n");
                                        break;
                                case ERROR_WINHTTP_INVALID_URL:
                                        printf("ERROR_WINHTTP_INVALID_URL\n");
                                        break;
                                case ERROR_WINHTTP_LOGIN_FAILURE:
                                        printf("ERROR_WINHTTP_LOGIN_FAILURE\n");
                                        break;
                                case ERROR_WINHTTP_OPERATION_CANCELLED:
                                        
printf("ERROR_WINHTTP_OPERATION_CANCELLED\n");
                                        break;
                                case ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT:
                                        
printf("ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT\n");
                                        break;
                                case ERROR_WINHTTP_UNRECOGNIZED_SCHEME:
                                        
printf("ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n");
                                        break;
                                case ERROR_NOT_ENOUGH_MEMORY:
                                        printf("ERROR_NOT_ENOUGH_MEMORY\n");
                                        break;
                        }

                }

                // Close WinHTTP Session
                printf("   Closing WinHTTP Session\n");
                WinHttpCloseHandle(hSession);
        }

        // Print Summary Information (i.e. Proxy details)
        printf("\nProxy Details (determined by routine):\n");
        printf("   Proxy Type: ");
        switch (AutoProxyInfo.dwAccessType) {
                case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY:
                        printf("WINHTTP_ACCESS_TYPE_DEFAULT_PROXY\n");
                        wprintf(L"   Proxy: %s\n", AutoProxyInfo.lpszProxy);
                        wprintf(L"   Proxy Bypass: %s\n", 
AutoProxyInfo.lpszProxyBypass);
                        break;
                case WINHTTP_ACCESS_TYPE_NO_PROXY:
                        printf("WINHTTP_ACCESS_TYPE_NO_PROXY\n");
                        break;
                case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
                        printf("WINHTTP_ACCESS_TYPE_NAMED_PROXY\n");
                        wprintf(L"   Proxy: %s\n", AutoProxyInfo.lpszProxy);
                        wprintf(L"   Proxy Bypass: %s\n", 
AutoProxyInfo.lpszProxyBypass);
                        break;
        }

        // Free up Memory Allocated during the Proxy Detection process
        printf("\nProxy Detection completed!\n");
        printf("Freeing up Memory Allocated during the Proxy Detection Process 
...\n");
        if (IEProxyConfig.lpszAutoConfigUrl != NULL) 
GlobalFree(IEProxyConfig.lpszAutoConfigUrl);
        if (IEProxyConfig.lpszProxy != NULL) 
GlobalFree(IEProxyConfig.lpszProxy);
        if (IEProxyConfig.lpszProxyBypass != NULL) 
GlobalFree(IEProxyConfig.lpszProxyBypass);
        if (AutoProxyInfo.lpszProxy != NULL)  
GlobalFree(AutoProxyInfo.lpszProxy);
        if (AutoProxyInfo.lpszProxyBypass != NULL) 
GlobalFree(AutoProxyInfo.lpszProxyBypass);
        GlobalFree(lpszURL);
        printf("Memory deallocation processing completed\n\n");

        // And exit (letting the user see the info first)
        printf ("\nPress any key to exit ...");
        _getch();
}

Reply via email to