Skip to content

Add useEcc convenience option to BrowserMobProxyServer and REST API #368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -1563,5 +1578,4 @@ public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerCont
});
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -129,38 +129,48 @@ public void onRemoval(RemovalNotification<Integer, LegacyProxyServer> removal) {
}
}

public LegacyProxyServer create(Map<String, String> options, Integer port, String bindAddr) {
public LegacyProxyServer create(Map<String, String> 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);
}
Expand All @@ -169,19 +179,19 @@ public LegacyProxyServer create(Map<String, String> options, Integer port, Strin
}

public LegacyProxyServer create(Map<String, String> options, Integer port) {
return create(options, port, null);
return create(options, port, null, false);
}

public LegacyProxyServer create(Map<String, String> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ public Reply<?> newProxy(Request<String> 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){
Expand Down