diff --git a/browsermob-core-littleproxy/src/main/java/net/lightbody/bmp/BrowserMobProxyServer.java b/browsermob-core-littleproxy/src/main/java/net/lightbody/bmp/BrowserMobProxyServer.java index 0471af427..aff2cda49 100644 --- a/browsermob-core-littleproxy/src/main/java/net/lightbody/bmp/BrowserMobProxyServer.java +++ b/browsermob-core-littleproxy/src/main/java/net/lightbody/bmp/BrowserMobProxyServer.java @@ -31,6 +31,7 @@ import net.lightbody.bmp.filters.UnregisterRequestFilter; import net.lightbody.bmp.filters.WhitelistFilter; import net.lightbody.bmp.mitm.KeyStoreFileCertificateSource; +import net.lightbody.bmp.mitm.keys.ECKeyGenerator; import net.lightbody.bmp.mitm.keys.RSAKeyGenerator; import net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager; import net.lightbody.bmp.proxy.ActivityMonitor; @@ -97,7 +98,8 @@ public class BrowserMobProxyServer implements BrowserMobProxy, LegacyProxyServer private static final HarNameVersion HAR_CREATOR_VERSION = new HarNameVersion("BrowserMob Proxy", "2.1.0-beta-4-littleproxy"); /* Default MITM resources */ - private static final String KEYSTORE_RESOURCE = "/sslSupport/ca-keystore-rsa.p12"; + private static final String RSA_KEYSTORE_RESOURCE = "/sslSupport/ca-keystore-rsa.p12"; + private static final String EC_KEYSTORE_RESOURCE = "/sslSupport/ca-keystore-ec.p12"; private static final String KEYSTORE_TYPE = "PKCS12"; private static final String KEYSTORE_PRIVATE_KEY_ALIAS = "key"; private static final String KEYSTORE_PASSWORD = "password"; @@ -248,6 +250,11 @@ public class BrowserMobProxyServer implements BrowserMobProxy, LegacyProxyServer */ private volatile boolean trustAllServers = true; + /** + * When true, use Elliptic Curve keys and certificates when impersonating upstream servers. + */ + private volatile boolean useEcc = false; + /** * Resolver to use when resolving hostnames to IP addresses. This is a bridge between {@link org.littleshoot.proxy.HostResolver} and * {@link net.lightbody.bmp.proxy.dns.AdvancedHostResolver}. It allows the resolvers to be changed on-the-fly without re-bootstrapping the @@ -377,8 +384,12 @@ public int getMaximumResponseBufferSizeInBytes() { if (!mitmDisabled) { if (mitmManager == null) { mitmManager = ImpersonatingMitmManager.builder() - .rootCertificateSource(new KeyStoreFileCertificateSource(KEYSTORE_TYPE, KEYSTORE_RESOURCE, KEYSTORE_PRIVATE_KEY_ALIAS, KEYSTORE_PASSWORD)) - .serverKeyGenerator(new RSAKeyGenerator()) + .rootCertificateSource(new KeyStoreFileCertificateSource( + KEYSTORE_TYPE, + useEcc ? EC_KEYSTORE_RESOURCE : RSA_KEYSTORE_RESOURCE, + KEYSTORE_PRIVATE_KEY_ALIAS, + KEYSTORE_PASSWORD)) + .serverKeyGenerator(useEcc ? new ECKeyGenerator() : new RSAKeyGenerator()) .trustAllServers(trustAllServers) .build(); } @@ -1421,6 +1432,10 @@ public boolean isMitmDisabled() { return this.mitmDisabled; } + public void setUseEcc(boolean useEcc) { + this.useEcc = useEcc; + } + /** * Adds the basic browsermob-proxy filters, except for the relatively-expensive HAR capture filter. */ @@ -1563,5 +1578,4 @@ public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerCont }); } } - } diff --git a/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/ProxyManager.java b/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/ProxyManager.java index 4c3f7970e..ad19bab93 100644 --- a/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/ProxyManager.java +++ b/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/ProxyManager.java @@ -129,38 +129,48 @@ public void onRemoval(RemovalNotification removal) { } } - public LegacyProxyServer create(Map options, Integer port, String bindAddr) { + public LegacyProxyServer create(Map options, Integer port, String bindAddr, boolean useEcc) { LOG.debug("Instantiate ProxyServer..."); LegacyProxyServer proxy = proxyServerProvider.get(); + if (useEcc) { + if (proxy instanceof BrowserMobProxyServer) { + LOG.info("Using Elliptic Curve Cryptography for certificate impersonation"); + + ((BrowserMobProxyServer)proxy).setUseEcc(true); + } else { + LOG.warn("Cannot use Eliiptic Curve Cryptography with legacy ProxyServer implementation. Using default RSA certificates."); + } + } + if (options != null) { LOG.debug("Apply options `{}` to new ProxyServer...", options); proxy.setOptions(options); } - - if (bindAddr != null) { + + if (bindAddr != null) { LOG.debug("Bind ProxyServer to `{}`...", bindAddr); InetAddress inetAddress; try { inetAddress = InetAddress.getByName(bindAddr); } catch (UnknownHostException e) { LOG.error("Unable to bind proxy to address: " + bindAddr + "; proxy will not be created.", e); - + throw new RuntimeException("Unable to bind proxy to address: ", e); } - + proxy.setLocalHost(inetAddress); } - - if (port != null) { - return startProxy(proxy, port); - } - + + if (port != null) { + return startProxy(proxy, port); + } + while(proxies.size() <= maxPort-minPort){ LOG.debug("Use next available port for new ProxyServer..."); - port = nextPort(); + port = nextPort(); try{ - return startProxy(proxy, port); + return startProxy(proxy, port); }catch(ProxyExistsException ex){ LOG.debug("Proxy already exists at port {}", port); } @@ -169,19 +179,19 @@ public LegacyProxyServer create(Map options, Integer port, Strin } public LegacyProxyServer create(Map options, Integer port) { - return create(options, port, null); + return create(options, port, null, false); } public LegacyProxyServer create(Map options) { - return create(options, null, null); + return create(options, null, null, false); } public LegacyProxyServer create() { - return create(null, null, null); + return create(null, null, null, false); } public LegacyProxyServer create(int port) { - return create(null, port, null); + return create(null, port, null, false); } public LegacyProxyServer get(int port) { diff --git a/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/bricks/ProxyResource.java b/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/bricks/ProxyResource.java index 5de832ed4..cb1527d6c 100644 --- a/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/bricks/ProxyResource.java +++ b/browsermob-rest/src/main/java/net/lightbody/bmp/proxy/bricks/ProxyResource.java @@ -85,11 +85,13 @@ public Reply newProxy(Request request) { String paramBindAddr = request.param("bindAddress"); Integer paramPort = request.param("port") == null ? null : Integer.parseInt(request.param("port")); + String useEccString = request.param("useEcc"); + boolean useEcc = Boolean.parseBoolean(useEccString); LOG.debug("POST proxy instance on bindAddress `{}` & port `{}`", paramBindAddr, paramPort); LegacyProxyServer proxy; try{ - proxy = proxyManager.create(options, paramPort, paramBindAddr); + proxy = proxyManager.create(options, paramPort, paramBindAddr, useEcc); }catch(ProxyExistsException ex){ return Reply.with(new ProxyDescriptor(ex.getPort())).status(455).as(Json.class); }catch(ProxyPortsExhaustedException ex){