In this demo you will
This tutorial explains how to setup a "cage" system for a Java 11 application
- Prepare the HAM container
- Prepare the Application container
- Docker with proxy access On the same machine (e.g. local docker or Docker Desktop)
- Docker with VPN access When the client accessing the app is on a physically different machine or in a VM
- What's next
Suppose you have an application named... testapp
Create a directory "master" and inside it
Prepare the configuration file, e.g. here you can find the default template external.json
Just setup a "Dockerfile" like the following for the HAM master
FROM ham.master:latest # Copy the configuration COPY .external.json /etc/app/ham/app/external.json
And create the image
docker build --rm -t testapp.master .
Create a directory "testapp" and inside it
Create the startup file, testapp.sh
#!/bin/sh
# Reach the application directory
cd /etc/app/testapp
# Set the java home and path
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk/
export PATH="${JAVA_HOME}/bin:${PATH}"
# Run your jar. Here with the agentlib line to allow remote debugging
# and the server port for Spring Boot
java -jar -Dserver.port=80 \
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:5005 \
/etc/app/testapp/app-1.0.0.jar
Prepare the Dockerfile. Note that the client images already handles all basic initializations like DNS resolution, services initializations and certificates management
FROM ham.client:latest
# Update the image
# Create the application dir
# Install Jdk 8
RUN apk update && apk upgrade &&
mkdir -p /etc/app/testapp &&
apk add --no-cache openjdk8
# Copy the jars
COPY /[jarAbsoluteDirTarget]/*.jar /etc/app/testapp/
# Copy the run script
COPY .testapp.sh /etc/app/testapp/
# Set the .sh as executable
# Start the application in foreground with runit
RUN chmod +x /etc/app/testapp/*.sh &&
/etc/startservice.sh --app=testapp --run=/etc/app/testapp/testapp.sh
And create the image
docker build --rm -t testapp.app .
Prepare a docker compose to connect to the application
version: "2"
networks:
testappnet: # Setup a network for the system:
driver: bridge
ipam:
config:
- subnet: 172.25.7.0/24 # Define a subnet not already used
services:
testapp.master: # The HAM instance
container_name: testapp.master # The DNS name of the instance
privileged: true # Needed for DNS hijacking
environment:
- ROOT_PWD=root
cap_add: # Needed for DNS hijacking
- NET_ADMIN
- DAC_READ_SEARCH
dns:
- 127.0.0.1
image: testapp.master
networks:
- testappnet
ports:
- "5025:5025" # Ham debug port (optional)
- "1080:1080" # Socks5 Proxy
- "1081:1081" # Http/s Proxy
testapp.app: # The application
container_name: www.testapp.com # The DNS name of the instance
environment:
- DNS_HIJACK_SERVER=testapp.master # Use HAM as final DNS server
- ROOT_PWD=root
privileged: true # Needed for DNS hijacking
cap_add: # Needed for DNS hijacking
- NET_ADMIN
- DAC_READ_SEARCH
dns:
- 127.0.0.1
image: testapp.app
ports:
- "8080:80" # To expose the application directly (optional)
networks:
- testappnet
depends_on: # Wait for HAM to start
- testapp.master
To make the test "real" we will add a DNS and SSL entry to the configuration.
In the section DNS of the "external.json" we tells that HAM should intercept all requests to our application. They will then be forwarded to the real instance
[
{
"id": "dns",
...,
"resolved": [
...,
{
"id": "123456",
"dns": "www.testapp.com",
"ip": "127.0.0.1"
}
] ...
In the section SSL of the "external.json" we tells that HAM should build certificates for all testapp.com domains
{
"id": "ssl",
...,
"domains": [
{
"id": "123456",
"address": "*.testapp.com"
}
] ...
Run the compose
docker-compose up
Setup the proxy on Firefox or Chrome (For the latter install Switch Omega) or for the application you are using to stimulate the application, like Postman
First complete the common steps:
- Prepare the HAM container
- Prepare the Application container
- Docker with proxy access On the same machine (e.g. local docker or Docker Desktop)
Install OpenVpn Connect Client on the client machine
Download the connection script and change the following line with the address of the machine running docker.
remote 127.0.0.1 3000 udp
Install the .ovpn file in your OpenVPN connect
Add the following instance to the docker compose. There is a custom image ready for that :)
testapp.vpn: # The application
container_name: testapp.vpn # The DNS name of the instance
environment:
- DNS_HIJACK_SERVER=testapp.master # Use HAM as final DNS server
- ROOT_PWD=root
privileged: true # Needed for DNS hijacking
cap_add: # Needed for DNS hijacking
- NET_ADMIN
- DAC_READ_SEARCH
dns:
- 127.0.0.1
image: ham.openvpn/latest
ports:
- "3000:1194/udp" # To expose the OpenVpn port
networks:
- testappnet
depends_on: # Wait for HAM to start
- testapp.master
Start the composer wait for the whole system to start and connect the client machine :) Now you are completely inside the HAM cage!
Running the application you can now
- Intercept the DNS calls and add them as HAM resolved, with the local CA
- Add custom Javascript filters and APIs
- Record/Replay/Test the app automatically and without coding
- Rewrite any url to anything
- Intercept ALL http/s interactions dynamically