Skip to content


Switch branches/tags


HTTP/HTTPS proxy over SSH.


  • Local machine: go get
  • Remote server: need our old friend sshd


Config file

Default path is $HOME/.config/mallory.json, can be set when start program

mallory -config path/to/config.json


  • id_rsa is the path to our private key file, can be generated by ssh-keygen
  • local_smart is the local address to serve HTTP proxy with smart detection of destination host
  • local_normal is similar to local_smart but send all traffic through remote SSH server without destination host detection
  • remote is the remote address of SSH server
  • blocked is a list of domains that need use proxy, any other domains will connect to their server directly
  "id_rsa": "$HOME/.ssh/id_rsa",
  "local_smart": ":1315",
  "local_normal": ":1316",
  "remote": "ssh://",
  "blocked": [

Blocked list in config file will be reloaded automatically when updated, and you can do it manually:

# send signal to reload
kill -USR2 <pid of mallory>

# or use reload command by sending http request
mallory -reload

System config

  • Set both HTTP and HTTPS proxy to localhost with port 1315 to use with block list
  • Set env var http_proxy and https_proxy to localhost:1316 for terminal usage

Get the right suffix name for a domain

mallory -suffix

A simple command to forward all traffic for the given port

# install it: go get

# all traffic through port 20022 will be forwarded to
forward -network tcp -listen :20022 -forward

# you can ssh to destination:22 through localhost:20022
ssh root@localhost -p 20022


  • return http error when unable to dial
  • add host to list automatically when unable to dial
  • support multiple remote servers

Docker container

Considering the following config file:

$ cat mallory.json
  "id_rsa": "/tmp/id_rsa",
  "local_smart": ":1315",
  "local_normal": ":1316",
  "remote": "ssh://bhenrion@"

You can run the container (zoobab/mallory) my mounting the config file, the SSH key, and mapping the 2 ports:

$ docker run -v $PWD/mallory.json:/root/.config/mallory.json -p 1316:1316 -p 1315:1315 -v $PWD/.ssh/id_rsa:/tmp/id_rsa zoobab/mallory
mallory: 2020/03/30 16:51:10 main.go:22: Starting...
mallory: 2020/03/30 16:51:10 main.go:23: PID: 1
mallory: 2020/03/30 16:51:10 config.go:103: Loading: /root/.config/mallory.json
mallory: 2020/03/30 16:51:10 main.go:30: Connecting remote SSH server: ssh://bhenrion@
mallory: 2020/03/30 16:51:10 main.go:38: Local normal HTTP proxy: :1316
mallory: 2020/03/30 16:51:10 main.go:48: Local smart HTTP proxy: :1315

My use case was to connect to a Kubernetes cluster (Openshift) installed behind an SSH bastion:

$ export http_proxy=http://localhost:1316
$ export https_proxy=https://localhost:1316
$ oc login
Authentication required for (openshift)
Username: bhenrion
Login successful.