Skip to content

Instantly share code, notes, and snippets.

@jrialland
Created October 6, 2015 09:36
Show Gist options
  • Save jrialland/a900b743ac3d99816540 to your computer and use it in GitHub Desktop.
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
#!/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