Created
October 6, 2015 09:36
-
-
Save jrialland/a900b743ac3d99816540 to your computer and use it in GitHub Desktop.
small script that uses a proxy.pac js configuration file and credentials for simplifying proxy connections
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env groovy | |
/*######################################################################*/ | |
//Configuration | |
/** username & password for proxy authentication */ | |
username = "user" | |
password = "p@zzW0rD" | |
/** Location of the Proxy configuration file (http://, and file:// urls are supported) */ | |
pacFileUrl = new URL("http://example.com/proxy.pac"); | |
/** On wich tcp port we bind the relay proxy */ | |
int local_port = 8887; | |
//End of configurable section | |
/*######################################################################*/ | |
proxyAuth = "Basic " + (username+":"+password).bytes.encodeBase64().toString(); | |
@Grab(group='org.littleshoot', module='littleproxy', version='0.5.3') | |
@GrabExclude('org.slf4j:slf4j-log4j12') | |
@Grab(group='org.slf4j', module='slf4j-simple', version='1.7.12') | |
import org.littleshoot.proxy.* | |
import org.littleshoot.proxy.impl.* | |
import org.jboss.netty.handler.codec.http.* | |
import javax.script.* | |
import org.slf4j.* | |
// Logging setup | |
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug"); | |
LOGGER = LoggerFactory.getLogger("pacproxy"); | |
// Javascript engine for evaluating PAC script | |
manager = new ScriptEngineManager(); | |
engine = manager.getEngineByName("javascript"); | |
// Install some mock implementation for the 'standard' PAC functions | |
engine.eval(""" | |
/**Evaluates hostnames and returns true if hostnames match. Used mainly to match and exception individual hostnames.*/ | |
dnsDomainIs = function(host, domain) { | |
return (host === domain) || host.endsWith(domain); | |
} | |
/**Will attempt to match hostname or URL to a specified shell expression, and returns true if matched.*/ | |
shExpMatch = function(url, pattern) { | |
throw new Exception('not implemented'); | |
} | |
/** This function evaluates the IP address of a hostname, and if within a specified subnet returns true. | |
* If a hostname is passed the function will resolve the hostname to an IP address. | |
*/ | |
isInNet = function(ip, net, mask) { | |
throw new Exception('not implemented'); | |
} | |
/** Returns the IP address of the host machine. */ | |
myIpAddress = function() { | |
return '127.0.0.1'; | |
} | |
/**Resolves hostnames to an IP address. This function can be used to reduce the number of DNS lookups*/ | |
dnsResolve = function(host) { | |
throw new Exception('not implemented'); | |
} | |
/** This function will return true if the hostname contains no dots */ | |
isPlainHostName = function(host) { | |
return ! host.contains('.'); | |
} | |
/** Evaluates hostname and only returns true if exact hostname match is found */ | |
localHostOrDomainIs = function(host) { | |
throw new Exception('not implemented'); | |
} | |
/** Attempts to resolve a hostname to an IP address and returns true if successful. */ | |
isResolvable = function(host) { | |
throw new Exception('not implemented') | |
} | |
/** This function returns the number of DNS domain levels (number of dots) in the hostname. Can be used to exception internal websites which use short DNS names, e.g. http://intranet */ | |
dnsDomainLevels = function(host) { | |
return (host.match(new RegExp("\\.","g")) || []).length; | |
} | |
/** Allows rules to be time based, e.g. only return a proxy during specific days. | |
ex: weekdayRange("MON", "FRI") | |
*/ | |
weekdayRange = function(day1, day2) { | |
throw new Exception('not implemented') | |
} | |
/** Allows rules to be time based, e.g. only return a proxy during specific months. dateRange("JAN", "MAR") */ | |
dateRange = function(m1, m2) { | |
throw new Exception('not implemented') | |
} | |
/** Allows rules to be time based, e.g. only return a proxy during specific hours. */ | |
timeRange = function(h1, h2) { | |
throw new Exception('not implemented') | |
} | |
""") | |
//Download and eval PAC file | |
LOGGER.info("Loading PAC file : " + pacFileUrl.toExternalForm()); | |
engine.eval(pacFileUrl.getText()) | |
String findProxyForUrl(url, host) { | |
LOGGER.debug("Calling js function FindProxyForURL('"+url+"', '"+host+"')"); | |
String decision = engine.invokeFunction("FindProxyForURL", url, host); | |
LOGGER.debug("\t=> "+decision); | |
return decision; | |
} | |
//Relay proxy configuration | |
proxyServer = new DefaultHttpProxyServer(local_port, | |
new HttpResponseFilters() { | |
public HttpFilter getFilter(String hostAndPort) { | |
return null; | |
} | |
}, | |
new ChainProxyManager() { | |
public void onCommunicationError(String hostAndPort) { | |
LOGGER.error("Communication error : " + hostAndPort); | |
} | |
public String getChainProxy(HttpRequest httpRequest) { | |
def url = new URL(httpRequest.getUri()); | |
for(decision in findProxyForUrl(url.toExternalForm(), url.getHost()).split(";")) { | |
if(decision.startsWith('PROXY')) { | |
decision = decision.replaceFirst("PROXY","").trim();//choose first one | |
LOGGER.debug("<"+decision+"> : " + url); | |
return decision; | |
} | |
} | |
LOGGER.debug("<direct> : "+ url); | |
request.addHeader('X-Direct','True'); | |
return null; | |
} | |
}, | |
null,//mitmManager | |
new HttpRequestFilter() { | |
public void filter(HttpRequest httpRequest) { | |
if(httpRequest.getHeader("X-Direct") == null) { | |
httpRequest.addHeader("Proxy-Authorization", proxyAuth); | |
} | |
} | |
} | |
); | |
LOGGER.info("Proxy Starting, will wait for connections at http://127.0.0.1:"+local_port); | |
proxyServer.start(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment