The MITM module is a LittleProxy-compatible module that enables man-in-the-middle interception of HTTPS requests. MITM allows you to:
- Generate both RSA and EC private keys (EC provides a significant performance boost, ~50x faster than RSA)
- Use a custom Certificate Authority (e.g. a corporate CA) to sign impersonated certificates, or generate (and optionally save) a new CA on-the-fly
- Specify a custom trust store on proxy-to-server connections, allowing the proxy to trust personal or corporate CAs
- Use OpenSSL, improving performance over Java's built-in TLS implementation
Though MITM is developed and distributed with BrowserMob Proxy, it has no dependency on BMP and can be used in a LittleProxy-only environment. The only additional dependency is the Bouncy Castle encryption library.
To use MITM with standalone LittleProxy, add a dependency on the mitm
module in your pom:
<!-- existing LittleProxy dependency -->
<dependency>
<groupId>org.littleshoot</groupId>
<artifactId>littleproxy</artifactId>
<version>1.1.2</version>
</dependency>
<!-- new dependency on the MITM module -->
<dependency>
<groupId>net.lightbody.bmp</groupId>
<artifactId>mitm</artifactId>
<version>2.1.4</version>
</dependency>
When creating your LittleProxy server, set the MitmManager to an instance of net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager
:
HttpProxyServerBootstrap bootstrap = DefaultHttpProxyServer.bootstrap()
.withManInTheMiddle(ImpersonatingMitmManager.builder().build());
The default implementation of ImpersonatingMitmManager
will generate a new CA Root Certificate when the first request is made to the proxy. See below for instructions on saving the generated root certificate, or using your own root certificate and private key.
The MITM module is enabled by default with BrowserMob Proxy. No additional steps are required to enable MITM with BrowserMob Proxy.
By default, BrowserMob Proxy will use the ca-keystore-rsa.p12
file to load its CA Root Certificate and Private Key. The corresponding certificate file is ca-certificate-rsa.cer
, which can be installed as a trusted Certificate Authority in browsers or other HTTP clients to avoid HTTPS warnings when using BrowserMob Proxy.
Several examples are available to help you get started:
Example File | Configuration |
---|---|
LittleProxyDefaultConfigExample.java | Default configuration with LittleProxy |
SaveGeneratedCAExample.java | Save a dynamically-generated CA root certificate for installation in a browser |
CustomCAKeyStoreExample.java and CustomCAPemFileExample.java | Use an existing CA certificate and private key |
EllipticCurveCAandServerExample.java | Use EC cryptography when generating the CA private key and when impersonating server certificates |
By default, when using the MITM module with LittleProxy, the CA Root Certificate and Private Key are generated dynamically. The dynamically generated Root Certificate and Private Key can be saved for installation in a browser or later reuse by using the methods on the RootCertificateGenerator
class. For example:
// create a CA Root Certificate using default settings
RootCertificateGenerator rootCertificateGenerator = RootCertificateGenerator.builder().build();
// save the newly-generated Root Certificate and Private Key -- the .cer file can be imported
// directly into a browser
rootCertificateGenerator.saveRootCertificateAsPemFile(new File("/tmp/certificate.cer"));
rootCertificateGenerator.savePrivateKeyAsPemFile(new File("/tmp/private-key.pem"), "password");
// or save the certificate and private key as a PKCS12 keystore, for later use
rootCertificateGenerator.saveRootCertificateAndKey("PKCS12", new File("/tmp/keystore.p12"),
"privateKeyAlias", "password");
// tell the ImpersonatingMitmManager use the RootCertificateGenerator we just configured
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.rootCertificateSource(rootCertificateGenerator)
.build();
// tell LittleProxy to use the ImpersonatingMitmManager when MITMing
HttpProxyServerBootstrap bootstrap = DefaultHttpProxyServer.bootstrap()
.withManInTheMiddle(mitmManager);
Whether you are using the MITM module with LittleProxy or BrowserMob Proxy, you can provide your own root certificate and private key to use when signing impersonated server certificates. To use a root certificate and private key from a key store (PKCS12 or JKS), use the KeyStoreFileCertificateSource
class:
CertificateAndKeySource existingCertificateSource =
new KeyStoreFileCertificateSource("PKCS12", new File("/path/to/keystore.p12", "privateKeyAlias", "password");
// configure the MitmManager to use the custom KeyStore source
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.rootCertificateSource(existingCertificateSource)
.build();
// when using LittleProxy, use the .withManInTheMiddle method on the bootstrap:
HttpProxyServerBootstrap bootstrap = DefaultHttpProxyServer.bootstrap()
.withManInTheMiddle(mitmManager);
// when using BrowserMob Proxy, use .setMitmManager() on the BrowserMobProxy object:
BrowserMobProxy proxyServer = new BrowserMobProxyServer();
proxyServer.setMitmManager(mitmManager);
You can also load the root certificate and private key from separate PEM-encoded files using the PemFileCertificateSource
class, or create an implementation of CertificateAndKeySource
that loads the certificate and private key from another source.
The MITM module trusts the Certificate Authorities in the JVM's default trust store, as well as a default list of trusted CAs derived from NSS/Firefox's list of trusted CAs (courtesy of the cURL team: https://curl.haxx.se/ca/cacert.pem).
To add your own CA to the list of root CAs trusted by the MITM module, use the add()
methods in the net.lightbody.bmp.mitm.TrustSource
class. Alternatively, it is possible to disable upstream server validation, but this is only recommended when testing. Examples:
// your root CA certificate(s) may be in a Java KeyStore, a PEM-encoded File or String, or an X509Certificate
File pemEncodedCAFile = ...;
TrustSource trustSource = TrustSource.defaultTrustSource().add(pemEncodedCAFile);
// when using MITM+LittleProxy, use the trustAllServers() method, or set the TrustSource on the ImpersonatingMitmManager:
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.trustSource(trustSource) // use an explicit trust source, or:
.trustAllServers(true) // do not validate servers' certificates
.build();
// when using BrowserMob Proxy, use the .setTrustSource() method:
BrowserMobProxy proxyServer = new BrowserMobProxyServer();
proxyServer.setTrustSource(trustSource);
// or disable server certificate validation:
proxyServer.setTrustAllServers(true);
By default, the certificates generated by the MITM module use RSA private keys for both impersonated server certificates and for generated CA root certificates. However, all modern browsers support Elliptic Curve Cryptography, which uses smaller key sizes. As a result, impersonated EC server certificates can be generated significantly faster (approximately 50x faster is common, typically <10ms per impersonated certificate).
The MITM module's RootCertificateGenerator can be configured to generate an EC root certificate for use with EC server certificates. If you are using your own CA root certificate and private key, make sure to generate an EC private key if you intend to use impersonated EC server certificates. (Though it is possible to generate "hybrid" server certificates with an EC key signed by an RSA CA, they are uncommon, and not all clients support them. In particular, Java clients and servers before 8u92 do not support hybrid certificates.)
To generate EC certificates for impersonated servers, set the serverKeyGenerator
to ECKeyGenerator
in ImpersonatingMitmManager. To generate an EC root certificate and private key, set the keyGenerator
to ECKeyGenerator
in RootCertificateGenerator:
// create a RootCertificateGenerator that generates EC Certificate Authorities; you may also load your
// own EC certificate and private key using any other CertificateAndKeySource implementation
// (KeyStoreFileCertificateSource, PemFileCertificateSource, etc.).
CertificateAndKeySource rootCertificateGenerator = RootCertificateGenerator.builder()
.keyGenerator(new ECKeyGenerator())
.build();
// tell the ImpersonatingMitmManager to generate EC keys and to use the EC RootCertificateGenerator
ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder()
.rootCertificateSource(rootCertificateGenerator)
.serverKeyGenerator(new ECKeyGenerator())
.build();
// when using LittleProxy:
HttpProxyServerBootstrap bootstrap = DefaultHttpProxyServer.bootstrap()
.withManInTheMiddle(mitmManager);
// when using BrowserMob Proxy:
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.setMitmManager(mitmManager);
The MITM module takes advantage of Netty's support for OpenSSL, allowing you to use OpenSSL instead of Java's built-in TLS implementation, which may provide
significant performance benefits. The MITM module itself requires no additional configuration to use OpenSSL: all you need is an OpenSSL installation and a dependency on the netty-tcnative
library for your platform.
See Netty's OpenSSL instructions for details: http://netty.io/wiki/requirements-for-4.x.html#tls-with-openssl
The MITM module would not have been possible without the efforts of Frank Ganske, the Zed Attack Proxy, and Brad Hill. Thank you for all your excellent work!