Show HN: Mole – an open source tool to easily create ssh tunnels
Mole

      Mole is a cli application to create ssh tunnels focused on resiliency
and user experience.

$ mole start local --remote :3306 --server my-database-server
INFO[0000] tunnel channel is waiting for connection      destination="127.0.0.1:3306" source="127.0.0.1:32863"


Highlighted Features


  Auto address selection: find a port available and start listening to it, so the --source flag doesn’t need to be given every time you run the app.
  Create multiple tunnels using a single ssh connection: multiple tunnels can be established using a single connection to a ssh server by specifying different --destination flags.
  Aliases: save your tunnel settings under an alias, so it can be reused later.
  Leverage the SSH Config File: use some options (e.g. user name, identity key and port), specified in $HOME/.ssh/config whenever possible, so there is no need to have the same SSH server configuration in multiple places.
  Resiliency! Then tunnel will never go down if you don’t want to:
    
      Idle clients do not get disconnected from the ssh server since Mole keeps sending synthetic packets acting as a keep alive mechanism.
      Auto reconnection to the ssh server if the it is dropped by any reason.
    
  
  Embedded rpc server to retrieve runtime information about one or more instances running on the system.


Table of Contents


  Use Cases
    
      Access a computer or service behind a firewall
      Access a service that is listening on a non-routable network
      Expose a service to someone outside your network
    
  
  Installation
    
      Linux and Mac
      Homebrew
      MacPorts
      Windows
    
  
  Usage
  Examples
    
      Basics
      Use the ssh config file to lookup a given server host
      Let mole to randomly select the source endpoint
      Connect to a remote service that is running on 127.0.0.1 by specifying only the destination port
      Create an alias, so there is no need to remember the tunnel settings afterwards
      Start mole in background
      Leveraging LocalForward from SSH configuration file
      Leveraging RemoteForward from SSH configuration file
      Create multiple tunnels using a single ssh connection
      Show logs of any detached mole instance
    
  


Use Cases

…or why on Earth would I need something like this?

Access a computer or service behind a firewall

Mole can help you to access and/or expose services outside the perimeter network that are blocked by a firewall or unreachable, as long as the user has ssh access to a computer (known as Jump Server) with access to the target computer or service.

+----------+          +----------+          +----------+
|          |          |          |          |          |
|          |          | Firewall |          |          |
|          |          |          |          |          |
|  Local   |  tunnel  +----------+  tunnel  |   Jump   |
| Computer |--------------------------------|  Server  |
|          |          +----------+          |          |
|          |          |          |          |          |
|          |          | Firewall |          |          |
|          |          |          |          |          |
+----------+          +----------+          +----------+
                                                 |
                                                 |
                                                 | tunnel
                                                 |
                                                 |
                                            +----------+
                                            |          |
                                            |          |
                                            |          |
                                            |          |
                                            |  Remote  |
                                            | Computer |
                                            |          |
                                            |          |
                                            |          |
                                            +----------+


Access a service that is listening on a non-routable network

+----------------------------------------------+         +--------------------+
| Local Computer                               |         | Jump Server        |
|                                              |         |                    |
|                                              | tunnel  |                    |
|                           (172.17.0.10:5001)-+---------+---> ssh server     |
|                               mole           |         | (172.17.0.100:22)  |
|                                / \           |         |      |             |
|                                 |            |         |      |             |
|                                 | forward    |         |      |             |
|   mysql \                       |            |         |      |             |
|     --host=127.0.0.1 ----> source address    |         |      | forward     |
|     --port=3306           (127.0.0.1:3306)   |         |      |             |
|     mydb                                     |         |      |             |
+----------------------------------------------+         +------+-------------+
                                                                |
                                                                |
                                                                |
                                                        +-------+-------------+
                                                        |       |    Database |
                                                        |       |      Server |
                                                        |      \ /            |
                                                        | destination address |
                                                        |  (192.168.1.1:3306) |
                                                        |                     |
                                                        +---------------------+


$ mole start local \
  --source 127.0.0.1:3306 \
  --destination 192.168.1.1:3306 \
  --server user@172.17.0.100


Expose a service to someone outside your network

+---------------------+         +----------------------+
|  Computer #1        |         |   Jump Server        |
|                     |         |                      |
|                     |  tunnel |                      |
|       mole  <-------+---------+-- (172.17.0.100:22)  |
|  (172.17.0.10:5001) |         |      ssh server      |
|        |            |         |       / \            |
|        | forward    |         |        |             |
|        |            |         |        | forward     |
|       \ /           |         |        |             |
|     web server      |         |   (192.168.1.1:8080) |
|  (127.0.0.1:8080)   |         |     source address   |
| destination address |         |               / \    |
|                     |         |                |     |
+---------------------+         |                |     |
                                |                |     |
                                +----------------+-----+
                                                 |
                                                 | connect
                                                 |
                                +----------------+-----+
                                | Computer #2    |     |
                                |                |     |
                                |                |     |
                                | $ curl \       |     |
                                |   192.168.1.1:8080   |
                                |                      |
                                +----------------------+


$ mole start remote \
  --source 192.168.1.1:8080 \
  --destination 127.0.0.1:8080 \
  --server user@172.17.0.100


Installation

Linux and Mac

bash <(curl -fsSL https://raw.githubusercontent.com/davrodpin/mole/master/tools/install.sh)


or if you prefer install it through Homebrew

brew tap davrodpin/homebrew-mole && brew install mole


or you can also install using MacPorts

sudo port selfupdate && sudo port install mole


Windows


  Download Mole for Windows from here


Usage

mole --help
Tool to manage ssh tunnels focused on resiliency and user experience.

Usage:
  mole [command]

Available Commands:
  add         Adds an alias for a ssh tunneling configuration
  delete      Deletes an alias for a ssh tunneling configuration
  help        Help about any command
  show        Shows configuration details about ssh tunnel aliases
  start       Starts a ssh tunnel
  stop        Stops a ssh tunnel
  version     Prints the version for mole

Flags:
  -h, --help   help for mole

Use "mole [command] --help" for more information about a command.


Examples

Basics

$ mole start local \
    --verbose \
    --source 127.0.0.1:8080 \
    --destination 172.17.0.100:80 \
    --server user@example.com:22 \
    --key ~/.ssh/id_rsa
INFO[0000] tunnel channel is waiting for connection      destination="172.17.0.100:80" source="127.0.0.1:8080"


Use the ssh config file to lookup a given server host

$ cat $HOME/.ssh/config
Host example
  User mole
  Hostname 127.0.0.1
  Port 22122
  IdentityFile test-env/ssh-server/keys/key
$ mole start local \
   --verbose \
   --source 127.0.0.1:8080 \
   --destination 172.17.0.100:80 \
   --server example
INFO[0000] tunnel channel is waiting for connection      destination="172.17.0.100:80" source="127.0.0.1:8080"


Let mole to randomly select the source endpoint

$ mole start local \
    --destination 172.17.0.100:80 \
    --server example
INFO[0000] tunnel channel is waiting for connection      destination="172.17.0.100:80" source="127.0.0.1:40525"

Bind the local address to 127.0.0.1 by specifying only the source port

$ mole start local \
    --source :8080 \
    --destination 172.17.0.100:80 \
    --server example
INFO[0000] tunnel channel is waiting for connection      destination="172.17.0.100:80" source="127.0.0.1:8080"


Connect to a remote service that is running on 127.0.0.1 by specifying only the destination port

$ mole start local \
    --source 127.0.0.1:8080 \
    --destination :80 \
    --server example
INFO[0000] tunnel channel is waiting for connection      destination="127.0.0.1:80" source="127.0.0.1:8080"


Create an alias, so there is no need to remember the tunnel settings afterwards

$ mole add alias local example \
    --source :8080 \
    --destination 172.17.0.100:80 \
    --server user@example.com:22
$ mole start alias example
INFO[0000] tunnel channel is waiting for connection      destination="172.17.0.100:80" source="127.0.0.1:8080"


Start mole in background

$ mole add alias local example \
    --source :8080 \
    --destination 172.17.0.100:80 \
    --server user@example.com:22
$ mole start alias example --detach
INFO[0000] execute "mole stop example" if you like to stop it at any time


Leveraging LocalForward from SSH configuration file

$ cat ~/.ssh/config
Host example
  User mole
  Hostname 127.0.0.1
  Port 22122
  LocalForward 21112 192.168.33.11:80
  IdentityFile test-env/ssh-server/keys/key
$ mole start local --server example 
INFO[0000] tunnel channel is waiting for connection      destination="192.168.33.11:80" source="127.0.0.1:21112"


Leveraging RemoteForward from SSH configuration file

$ cat ~/.ssh/config
Host example
  User mole
  Hostname 127.0.0.1
  Port 22122
  LocalForward 192.168.33.11:9090 172.0.0.1:8080
  IdentityFile test-env/ssh-server/keys/key
$ mole start remote --server example
INFO[0000] tunnel channel is waiting for connection      destination="192.168.33.11:8080" source="127.0.0.1:9090"


Create multiple tunnels using a single ssh connection

$ mole start local \
    --source :9090 \
    --source :9091 \
    --destination 192.168.33.11:80 \
    --destination 192.168.33.11:8080 \
    --server example
INFO[0000] tunnel channel is waiting for connection      destination="192.168.33.11:8080" source="127.0.0.1:9091"
INFO[0000] tunnel channel is waiting for connection      destination="192.168.33.11:80" source="127.0.0.1:9090"


Show logs of any detached mole instance

$ mole start local \
    --detach \
    --source :9090 \
    --source :9091 \
    --destination 192.168.33.11:80 \
    --destination 192.168.33.11:8080 \
    --server example
INFO[0000] instance identifier is afb046da
INFO[0000] execute "mole stop afb046da" if you like to stop it at any time
$ mole show logs --follow afb046da
time="2021-09-17T13:57:10-07:00" level=info msg="instance identifier is 1879de9f"
time="2021-09-17T13:57:10-07:00" level=debug msg="generating an empty config struct"
time="2021-09-17T13:57:10-07:00" level=debug msg="server: [name=127.0.0.01, address=127.0.0.01:22122, user=mole]"
time="2021-09-17T13:57:10-07:00" level=debug msg="tunnel: [channels:[[source=127.0.0.1:9888, destination=192.168.33.11:80]], server:127.0.0.01:22122]"
time="2021-09-17T13:57:10-07:00" level=debug msg="connection to the ssh server is established" server="[name=127.0.0.01, address=127.0.0.01:22122, user=mole]"
time="2021-09-17T13:57:10-07:00" level=info msg="tunnel channel is waiting for connection" destination="192.168.33.11:80" source="127.0.0.1:9888"
time="2021-09-17T13:57:10-07:00" level=debug msg="start sending keep alive packets"


Show the running configuration of all/any mole instance

$ mole start local \
    --detach \
    --rpc \
    --source :9090 \
    --source :9091 \
    --destination 192.168.33.11:80 \
    --destination 192.168.33.11:8080 \
    --server example
INFO[0000] instance identifier is 2b3d05be
INFO[0000] execute "mole stop 2b3d05be" if you like to stop it at any time
$ mole show instances 2b3d05be
id = "2b3d05be"
tunnel-type = "local"
verbose = false
insecure = false
detach = true
key = "$HOME/.ssh/id_rsa"
keep-alive-interval = 0
connection-retries = 3
wait-and-retry = 3000000000
ssh-agent = ""
timeout = 3000000000
ssh-config = "$HOME/.ssh/config"
rpc = true
rpc-address = "127.0.0.1:49923"

[[source]]
  user = ""
  host = "127.0.0.1"
  port = "9090"

[[source]]
  user = ""
  host = "127.0.0.1"
  port = "9092"

[[destination]]
  user = ""
  host = "192.168.33.11"
  port = "80"

[[destination]]
  user = ""
  host = "192.168.33.11"
  port = "8080"

[server]
  user = ""
  host = "example"
  port = "22"



      
    