diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/basic/auth_basic.cc squid-3.3.12-patched/src/auth/basic/auth_basic.cc
--- squid-3.3.12/src/auth/basic/auth_basic.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/basic/auth_basic.cc	2013-02-15 13:03:06.530293792 +0100
@@ -249,6 +249,26 @@ Auth::Basic::Config::decodeCleartext(con
     return cleartext;
 }
 
+void
+Auth::Basic::Config::flushSessionCache(char const *proxy_auth)
+{
+    char* credentials = decodeCleartext(proxy_auth);
+    char* username = strtok(credentials, ":");
+
+    if (username)
+    {
+        AuthUserHashPointer *usernamehash;
+        usernamehash = ((AuthUserHashPointer *) hash_lookup(proxy_auth_username_cache, username));
+
+        if (usernamehash) {
+            hash_remove_link(proxy_auth_username_cache, usernamehash);
+            delete usernamehash;
+	}
+    }
+
+    free(credentials);
+}
+
 /**
  * Decode a Basic [Proxy-]Auth string, linking the passed
  * auth_user_request structure to any existing user structure or creating one
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/basic/auth_basic.h squid-3.3.12-patched/src/auth/basic/auth_basic.h
--- squid-3.3.12/src/auth/basic/auth_basic.h	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/basic/auth_basic.h	2013-02-14 20:35:58.931339976 +0100
@@ -38,6 +38,7 @@ public:
     virtual bool active() const;
     virtual bool configured() const;
     virtual Auth::UserRequest::Pointer decode(char const *proxy_auth);
+    virtual void flushSessionCache(char const *proxy_auth);
     virtual void done();
     virtual void rotateHelpers();
     virtual void dump(StoreEntry *, const char *, Auth::Config *);
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/basic/UserRequest.cc squid-3.3.12-patched/src/auth/basic/UserRequest.cc
--- squid-3.3.12/src/auth/basic/UserRequest.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/basic/UserRequest.cc	2013-02-15 11:58:45.455734657 +0100
@@ -7,6 +7,9 @@
 #include "Debug.h"
 #include "rfc1738.h"
 #include "SquidTime.h"
+#include "HttpRequest.h"
+#include "ip/Address.h"
+#include "SquidConfig.h"
 
 #if !defined(HELPER_INPUT_BUFFER)
 #define HELPER_INPUT_BUFFER  8192
@@ -30,8 +33,29 @@ Auth::Basic::UserRequest::authenticate(H
 {
     assert(user() != NULL);
 
+    // squid calls this method each time except auth has been succeded (!Auth::Ok) 
+    // or once user tries to change proxy IP after it has been authenticated with different IP (in this case )
+    // we need to store his last bound IP to the Auth::User class instance
+    // at this stage to use it on external auth handler invocations
+    if (user()->credentials() != Auth::Ok)
+    {
+    	char *server_sock_addr = (char *) malloc(MAX_IPSTRLEN),
+	     *client_sock_addr = (char *) malloc(MAX_IPSTRLEN);
+
+    	request->my_addr.ToHostname(server_sock_addr, MAX_IPSTRLEN);
+    	request->client_addr.ToHostname(client_sock_addr, MAX_IPSTRLEN);
+
+    	user()->server_addr(NULL);
+    	user()->server_addr(server_sock_addr);
+    	user()->client_addr(NULL);
+    	user()->client_addr(client_sock_addr);
+
+    	free(server_sock_addr);
+    	free(client_sock_addr);
+    }
+
     /* if the password is not ok, do an identity */
-    if (!user() || user()->credentials() != Auth::Ok)
+    if (!user() || user()->credentials() != Auth::Ok) 
         return;
 
     /* are we about to recheck the credentials externally? */
@@ -122,7 +146,8 @@ Auth::Basic::UserRequest::module_start(A
         xstrncpy(username, rfc1738_escape(user()->username()), sizeof(username));
         xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass));
     }
-    int sz = snprintf(buf, sizeof(buf), "%s %s\n", username, pass);
+    // passing into script: username, password, bound ip address, user source ip address
+    int sz = snprintf(buf, sizeof(buf), "%s %s %s %s\n", username, pass, user()->server_addr(), user()->client_addr());
     if (sz<=0) {
         debugs(9, DBG_CRITICAL, "ERROR: Basic Authentication Failure. Can not build helper validation request.");
         handler(data);
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/Config.cc squid-3.3.12-patched/src/auth/Config.cc
--- squid-3.3.12/src/auth/Config.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/Config.cc	2013-02-14 00:20:22.326883151 +0100
@@ -72,6 +72,14 @@ Auth::Config::Find(const char *proxy_aut
     return NULL;
 }
 
+void
+Auth::Config::Remove(const char *proxy_auth)
+{
+    Auth::Config * config = Find(proxy_auth);
+    Auth::TheConfig.prune(config);
+}
+
+
 /** Default behaviour is to expose nothing */
 void
 Auth::Config::registerWithCacheManager(void)
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/Config.h squid-3.3.12-patched/src/auth/Config.h
--- squid-3.3.12/src/auth/Config.h	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/Config.h	2013-02-14 20:35:47.280947012 +0100
@@ -45,7 +45,6 @@ class wordlist;
 
 namespace Auth
 {
-
 /**
  * \ingroup AuthAPI
  * \par
@@ -64,6 +63,7 @@ public:
     static UserRequest::Pointer CreateAuthUser(const char *proxy_auth);
 
     static Config *Find(const char *proxy_auth);
+    static void Remove(const char *proxy_auth);
     Config() : authenticateChildren(20), authenticateProgram(NULL) {}
 
     virtual ~Config() {}
@@ -87,6 +87,7 @@ public:
      \retval *		Details needed to authenticate.
      */
     virtual UserRequest::Pointer decode(char const *proxy_auth) = 0;
+    virtual void flushSessionCache(char const *proxy_auth) {}
 
     /**
      * squid is finished with this config, release any unneeded resources.
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/User.cc squid-3.3.12-patched/src/auth/User.cc
--- squid-3.3.12/src/auth/User.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/User.cc	2013-02-11 01:04:23.531119133 +0100
@@ -59,7 +59,10 @@ Auth::User::User(Auth::Config *aConfig) 
         ipcount(0),
         expiretime(0),
         credentials_state(Auth::Unchecked),
-        username_(NULL)
+        username_(NULL),
+        client_addr_(NULL),
+        server_addr_(NULL)
+	
 {
     proxy_auth_list.head = proxy_auth_list.tail = NULL;
     proxy_match_cache.head = proxy_match_cache.tail = NULL;
@@ -162,6 +165,12 @@ Auth::User::~User()
     if (username_)
         xfree((char*)username_);
 
+    if (client_addr_)
+	xfree((char*)client_addr_);
+
+    if (server_addr_)
+	xfree((char*)server_addr_);
+
     /* prevent accidental reuse */
     auth_type = Auth::AUTH_UNKNOWN;
 }
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/User.cci squid-3.3.12-patched/src/auth/User.cci
--- squid-3.3.12/src/auth/User.cci	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/User.cci	2013-02-11 01:04:34.647583122 +0100
@@ -47,3 +47,38 @@ Auth::User::username(char const *aString
         safe_free(username_);
     }
 }
+
+char const *
+Auth::User::client_addr () const
+{
+    return client_addr_;
+}
+
+void
+Auth::User::client_addr(char const *aString)
+{
+    if (aString) {
+        assert(!client_addr_);
+        client_addr_ = xstrdup(aString);
+    } else {
+        safe_free(client_addr_);
+    }
+}
+
+char const *
+Auth::User::server_addr () const
+{
+    return server_addr_;
+}
+
+void
+Auth::User::server_addr(char const *aString)
+{
+    if (aString) {
+        assert(!server_addr_);
+        server_addr_ = xstrdup(aString);
+    } else {
+        safe_free(server_addr_);
+    }
+}
+
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/User.h squid-3.3.12-patched/src/auth/User.h
--- squid-3.3.12/src/auth/User.h	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/User.h	2013-02-11 01:54:54.682465716 +0100
@@ -83,6 +83,10 @@ public:
     virtual ~User();
     _SQUID_INLINE_ char const *username() const;
     _SQUID_INLINE_ void username(char const *);
+    _SQUID_INLINE_ char const *client_addr() const;
+    _SQUID_INLINE_ char const *server_addr() const;
+    _SQUID_INLINE_ void client_addr(char const *);
+    _SQUID_INLINE_ void server_addr(char const *);
 
     /**
      * How long these credentials are still valid for.
@@ -128,6 +132,8 @@ private:
      * xstrdup().  It is our responsibility.
      */
     const char *username_;
+    const char *client_addr_;
+    const char *server_addr_;
 
     /** what ip addresses has this user been seen at?, plus a list length cache */
     dlink_list ip_list;
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/UserRequest.cc squid-3.3.12-patched/src/auth/UserRequest.cc
--- squid-3.3.12/src/auth/UserRequest.cc	2013-02-14 16:46:18.524100521 +0100
+++ squid-3.3.12-patched/src/auth/UserRequest.cc	2013-02-15 14:11:34.993775524 +0100
@@ -55,6 +55,16 @@ Auth::UserRequest::username() const
         return NULL;
 }
 
+char const *
+Auth::UserRequest::server_addr() const
+{
+    if (user() != NULL)
+        return user()->server_addr();
+    else
+        return NULL;
+}
+
+
 /**** PUBLIC FUNCTIONS (ALL GENERIC!)  ****/
 
 /* send the initial data to an authenticator module */
@@ -159,6 +169,7 @@ authenticateAuthUserRequestSetIp(Auth::U
     if (!auth_user)
         return;
 
+    auth_user->clearIp();
     auth_user->addIp(ipaddr);
 }
 
@@ -310,6 +321,7 @@ Auth::UserRequest::authenticate(Auth::Us
         return AUTH_ACL_CHALLENGE;
     }
 
+
     /*
      * Is this an already authenticated connection with a new auth header?
      * No check for function required in the if: its compulsory for conn based
@@ -359,6 +371,23 @@ Auth::UserRequest::authenticate(Auth::Us
             /* beginning of a new request check */
             debugs(29, 4, HERE << "No connection authentication type");
 
+            Auth::Config * scheme = Auth::Config::Find(proxy_auth);
+            if (scheme)
+            {
+                *auth_user_request = Auth::Config::CreateAuthUser(proxy_auth);
+                if (auth_user_request)
+                {
+                    const char *server_addr_src = (*auth_user_request)->server_addr();
+                    char *server_addr_cur = (char*) malloc(MAX_IPSTRLEN);
+                    request->my_addr.ToHostname(server_addr_cur, MAX_IPSTRLEN);
+
+                    if (server_addr_src && server_addr_cur && strcmp(server_addr_src, server_addr_cur)) 
+                        scheme->flushSessionCache(proxy_auth);
+
+		    free(server_addr_cur);
+                }
+            }
+
             *auth_user_request = Auth::Config::CreateAuthUser(proxy_auth);
             if (*auth_user_request == NULL)
                 return AUTH_ACL_CHALLENGE;
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/auth/UserRequest.h squid-3.3.12-patched/src/auth/UserRequest.h
--- squid-3.3.12/src/auth/UserRequest.h	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/auth/UserRequest.h	2013-02-15 11:58:02.309680068 +0100
@@ -202,6 +202,7 @@ public:
      \retval *		Null-terminated username string.
      */
     char const *username() const;
+    char const *server_addr() const;
 
     Scheme::Pointer scheme() const;
 
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/cf.data.pre squid-3.3.12-patched/src/cf.data.pre
--- squid-3.3.12/src/cf.data.pre	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/cf.data.pre	2013-02-10 18:59:18.664559363 +0100
@@ -581,6 +581,13 @@ DOC_START
 	have good reason to.
 DOC_END
 
+NAME: country
+TYPE: string
+DEFAULT: none
+LOC: Config.country
+DOC_START
+DOC_END
+
 NAME: authenticate_ttl
 TYPE: time_t
 DEFAULT: 1 hour
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/client_side.cc squid-3.3.12-patched/src/client_side.cc
--- squid-3.3.12/src/client_side.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/client_side.cc	2013-02-13 14:26:12.090199114 +0100
@@ -129,6 +129,7 @@
 #include "TimeOrTag.h"
 #include "tools.h"
 #include "URL.h"
+#include <ctype.h>
 
 #if USE_AUTH
 #include "auth/UserRequest.h"
@@ -3999,12 +4000,46 @@ AddOpenedHttpSocket(const Comm::Connecti
     return found;
 }
 
+/// exports IP addresses as environment variables for external auth helper 
+void nvpnExportBoundIPs(AnyP::PortCfg* s)
+{
+        char *bound_ip_sock = strdup(s->name),
+             *bound_ip = NULL,
+	     *bound_proto = strdup(s->protocol),
+             *export_var = (char*) calloc(32, sizeof(char));
+
+	static int ipid = 0;
+
+        int isPortOnly = 1;
+	for (char *p = bound_ip_sock ; *p ; p++) if (!isdigit(*p)) isPortOnly = 0;
+	for (char *p = bound_proto ; *p ; *p = toupper(*p), p++);
+
+        if (isPortOnly)
+                bound_ip = strdup("0.0.0.0");
+        else
+                bound_ip = strtok(bound_ip_sock, ":");
+
+        sprintf(export_var, "SQUID_NVPN_%s_IP_%d", bound_proto, ipid);
+
+	// exporting variable
+        setenv(export_var, bound_ip, 1);
+
+	ipid++;
+
+	// cleaning up
+        free(bound_ip_sock);
+        free(export_var);
+}
+
 static void
 clientHttpConnectionsOpen(void)
 {
     AnyP::PortCfg *s = NULL;
 
     for (s = Config.Sockaddr.http; s; s = s->next) {
+
+        nvpnExportBoundIPs(s);
+
         if (MAXTCPLISTENPORTS == NHttpSockets) {
             debugs(1, DBG_IMPORTANT, "WARNING: You have too many 'http_port' lines.");
             debugs(1, DBG_IMPORTANT, "         The limit is " << MAXTCPLISTENPORTS << " HTTP ports.");
@@ -4054,6 +4089,9 @@ clientHttpsConnectionsOpen(void)
     AnyP::PortCfg *s;
 
     for (s = Config.Sockaddr.https; s; s = s->next) {
+        
+	nvpnExportBoundIPs(s);
+
         if (MAXTCPLISTENPORTS == NHttpSockets) {
             debugs(1, DBG_IMPORTANT, "Ignoring 'https_port' lines exceeding the limit.");
             debugs(1, DBG_IMPORTANT, "The limit is " << MAXTCPLISTENPORTS << " HTTPS ports.");
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/forward.cc squid-3.3.12-patched/src/forward.cc
--- squid-3.3.12/src/forward.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/forward.cc	2013-02-15 11:53:34.391590375 +0100
@@ -1415,14 +1415,20 @@ getOutgoingAddress(HttpRequest * request
         // else no tproxy today ...
     }
 
-    if (!Config.accessList.outgoing_address) {
-        return; // anything will do.
-    }
+    //if (!Config.accessList.outgoing_address) {
+    //    return; // anything will do.
+    //}
 
     ACLFilledChecklist ch(NULL, request, NULL);
     ch.dst_peer = conn->getPeer();
     ch.dst_addr = conn->remote;
 
+    if (request) {
+        conn->local = request->my_addr;
+	conn->local.SetPort(0);
+        return;
+    }
+
     // TODO use the connection details in ACL.
     // needs a bit of rework in ACLFilledChecklist to use Comm::Connection instead of ConnStateData
 
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/main.cc squid-3.3.12-patched/src/main.cc
--- squid-3.3.12/src/main.cc	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/main.cc	2013-02-12 21:28:39.484788250 +0100
@@ -1340,6 +1340,8 @@ SquidMain(int argc, char **argv)
         Debug::parseOptions("ALL,1");
     }
 
+    setenv("SQUID_NVPN_COUNTRY", Config.country, 1);
+
 #if USE_WIN32_SERVICE
 
     if (opt_install_service) {
diff -rupN --exclude='.*' --exclude=Makefile --exclude=ProtocolType.cc --exclude=CredentialState.cc --exclude=Type.cc --exclude=swap_log_op.cc squid-3.3.12/src/SquidConfig.h squid-3.3.12-patched/src/SquidConfig.h
--- squid-3.3.12/src/SquidConfig.h	2013-02-09 08:30:01.000000000 +0100
+++ squid-3.3.12-patched/src/SquidConfig.h	2013-02-10 17:37:33.889820659 +0100
@@ -78,6 +78,7 @@ public:
     } Swap;
 
     YesNoNone memShared; ///< whether the memory cache is shared among workers
+    char *country;
     size_t memMaxSize;
 
     struct {
