package com.btr.proxy.search.wpad; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; import java.util.List; import java.util.Properties; import com.btr.proxy.search.ProxySearchStrategy; import com.btr.proxy.util.Logger; import com.btr.proxy.util.Logger.LogLevel; import com.btr.proxy.util.ProxyUtil; /***************************************************************************** * Uses automatic proxy script search (WPAD) to find an PAC file automatically. *

* Note: at the moment only the DNS name guessing schema is implemented. All * others are missing. *

*

* For more information about WPAD: Web_Proxy_Autodiscovery_Protocol *

*

* Outdated RFC draft: draft-ietf-wrec-wpad-01.txt *

* * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 ****************************************************************************/ public class WpadProxySearchStrategy implements ProxySearchStrategy { /************************************************************************* * Constructor ************************************************************************/ public WpadProxySearchStrategy() { super(); } /************************************************************************* * Loads the proxy settings from a PAC file. * The location of the PAC file is determined automatically. * * @return a configured ProxySelector, null if none is found. ************************************************************************/ public ProxySelector getProxySelector() { Logger.log(getClass(), LogLevel.TRACE, "Using WPAD to find a proxy"); String pacScriptUrl = detectScriptUrlPerDNS(); if (pacScriptUrl == null) { return null; } Logger.log(getClass(), LogLevel.TRACE, "PAC script url found: {0}", pacScriptUrl); return ProxyUtil.buildPacSelectorForUrl(pacScriptUrl); } /************************************************************************* * Loads the settings and stores them in a properties map. * * @return the settings. ************************************************************************/ public Properties readSettings() { String pacScriptUrl = detectScriptUrlPerDNS(); if (pacScriptUrl == null) { return null; } Properties result = new Properties(); result.setProperty("url", pacScriptUrl); return result; } /************************************************************************* * Uses DNS to find the script URL. * Attention: this detection method is known to have some severe security * issues. * * @return the URL, null if not found. ************************************************************************/ private String detectScriptUrlPerDNS() { // TODO: Java way of finding all search domains? Seems not trivial // Windows workaround could be running ipconfig /all and parsing... Logger.log(getClass(), LogLevel.TRACE, "Searching per DNS guessing."); String ret; int index; ret = tryUrl("http://wpad/wpad.dat"); if (ret != null) return ret; String fqdn = null; try { fqdn = InetAddress.getLocalHost().getCanonicalHostName(); } catch (UnknownHostException e2) { // Not successful, try other methods } if (fqdn != null && !fqdn.matches("\\d+\\.\\d+\\.\\d+\\.\\d+") && (index = fqdn.indexOf('.')) != -1) { ret = tryUrl("http://wpad." + fqdn.substring(index + 1) + "/wpad.dat"); if (ret != null) return ret; } BufferedReader br = null; String[] addresses = null; try { FileReader fr = new FileReader("/etc/resolv.conf"); br = new BufferedReader(fr); String input; while ((input = br.readLine()) != null) { if (input.startsWith("search")) { // the first one is "search" and afterwards addresses are following. addresses = input.substring(6).split(" "); break; } } } catch (IOException e1) { Logger.log(getClass(), LogLevel.DEBUG, "Could not read resolv.conf"); } finally { try { br.close(); } catch (Exception e) { } } if (addresses == null) { addresses = new String[] { "" }; } for (int i = 0; i < addresses.length; ++i) { String address = addresses[i].trim().replaceAll("^\\.+", "").replaceAll("\\.+$", ""); if (address.length() < 4) continue; do { ret = tryUrl("http://wpad." + address + "/wpad.dat"); if (ret != null) return ret; // don't construct something like wpad.de.... index = address.indexOf('.'); if (index == -1 || index + 7 > address.length()) break; address = address.substring(index + 1); if (address.indexOf('.') == -1) break; } while (true); } return null; } private String tryUrl(String url) { try { URL lookupURL = new URL(url); Logger.log(getClass(), LogLevel.DEBUG, "Trying url: {0}", lookupURL); HttpURLConnection con = (HttpURLConnection) lookupURL.openConnection(Proxy.NO_PROXY); con.setConnectTimeout(1500); con.setReadTimeout(2500); con.setRequestMethod("HEAD"); con.setInstanceFollowRedirects(true); con.setRequestProperty("accept", "application/x-ns-proxy-autoconfig"); if (con.getResponseCode() == 200) { String result = lookupURL.toString(); return result; } con.disconnect(); } catch (Exception e) { Logger.log(getClass(), LogLevel.DEBUG, "Not available ({0})", e); // Not a real error, try next address } return null; } // Main method for testing. public static void main(String[] args) throws IOException { WpadProxySearchStrategy wPSS = new WpadProxySearchStrategy(); // System.setProperty("com.btr.proxy.pac.overrideLocalIP", "10.0.0.1"); try { ProxySelector pS = wPSS.getProxySelector(); ProxySelector.setDefault(pS); List proxyList = pS.select(new URI("http://www.google.de")); if (proxyList.isEmpty()) { Logger.log(WpadProxySearchStrategy.class, LogLevel.INFO, "ProxyList is empty!"); } else { Logger.log(WpadProxySearchStrategy.class, LogLevel.INFO, "proxyList contains: {0}", proxyList.toString()); } } catch (URISyntaxException e) { // TODO bjoern 28.10.2014 Auto-generated catch block e.printStackTrace(); } URL test = new URL("http://www.google.de"); URLConnection uc = test.openConnection(); BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream())); String inputLine; while ((inputLine = br.readLine()) != null) { System.out.println(inputLine); } Socket socket = new Socket("www.google.de", 80); try { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bw.write("GET / HTTP/1.1\r\nHost: www.google.de\r\nConnection: close\r\nAccept-Encoding: *\r\n\r\n"); bw.flush(); br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while ((inputLine = br.readLine()) != null) { System.out.println(inputLine); } } finally { socket.close(); } } }