ngrok Notes

Wednesday, May 3, 2017 🌐中文

cover

Preface

Why am I writing this post? Back when I was reproducing the CVE-2017-0199 vulnerability, I needed NAT traversal. I searched for tunneling services and found that many of them were based on ngrok. During the process I found it quite painful to configure. The version I used was 1.7, which reportedly has a memory leak bug. The latest 2.2 is closed-source, and the official documentation no longer works. I read a few posts written by others and decided to record my own setup process as well. I’ve also heard that FRP is stronger than ngrok—maybe I’ll try it next time.

Installation

git clone https://github.com/inconshreveable/ngrok
cd ngrok
make
# 服务端
mv ./ngrokd /usr/bin/ngrokd
# 客户端
mv ./ngrok /usr/bin/ngrok
echo "" > $HOME/.ngrok

Usage

Server

ngrokd roughly means “ngrok daemon”—as the name suggests, it’s the server side. Check the help:

root@gorgiaxx:~/tmp/ngrok/bin# ./ngrokd --help
Usage of ./ngrokd:
  -domain string
        Domain where the tunnels are hosted (default "ngrok.com")
  -httpAddr string
        Public address for HTTP connections, empty string to disable (default ":80")
  -httpsAddr string
        Public address listening for HTTPS connections, emptry string to disable (default ":443")
  -log string
        Write log messages to this file. 'stdout' and 'none' have special meanings (default "stdout")
  -log-level string
        The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR (default "DEBUG")
  -tlsCrt string
        Path to a TLS certificate file
  -tlsKey string
        Path to a TLS key file
  -tunnelAddr string
        Public address listening for ngrok client (default ":4443")

On my server, ports 80 and 443 were already occupied by Nginx, so I changed them to 800 and 801. I also didn’t need to configure tlsCrt and tlsKey because I wasn’t going to use them. I set the log level to WARNING. tunnelAddr is the tunnel address used by the internal machine to connect to the server.

./ngrokd -domain gorgiaxx.me -httpAddr :800 -httpsAddr :801 -tunnelAddr :802 -log-level WARNING

Client

Check the help:

gorgias@3vil:~/Tools/port_map/ngrok/bin$ ./ngrok --help
Usage: ./ngrok [OPTIONS] <local port or address>
Options:
  -authtoken string
        Authentication token for identifying an ngrok.com account
  -config string
        Path to ngrok configuration file. (default: $HOME/.ngrok)
  -hostname string
        Request a custom hostname from the ngrok server. (HTTP only) (requires CNAME of your DNS)
  -httpauth string
        username:password HTTP basic auth creds protecting the public tunnel endpoint
  -log string
        Write log messages to this file. 'stdout' and 'none' have special meanings (default "none")
  -log-level string
        The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR (default "DEBUG")
  -proto string
        The protocol of the traffic over the tunnel {'http', 'https', 'tcp'} (default: 'http+https') (default "http+https")
  -subdomain string
        Request a custom subdomain from the ngrok server. (HTTP only)

Examples:
        ngrok 80
        ngrok -subdomain=example 8080
        ngrok -proto=tcp 22
        ngrok -hostname="example.com" -httpauth="user:password" 10.0.0.1


Advanced usage: ngrok [OPTIONS] <command> [command args] [...]
Commands:
        ngrok start [tunnel] [...]    Start tunnels by name from config file
        ngork start-all               Start all tunnels defined in config file
        ngrok list                    List tunnel names from config file
        ngrok help                    Print help
        ngrok version                 Print ngrok version

Examples:
        ngrok start www api blog pubsub
        ngrok -log=stdout -config=ngrok.yml start ssh
        ngrok start-all
        ngrok version

If you want easier configuration and plan to share it with more people, it’s best to set up a wildcard DNS record. You can also host your own DNS server. If you’re just using it for yourself, then configure a specific subdomain.

ngrok -hostname="ngrok.gorgoaxx.me" -subdomain=ngrok 802 -proto=tcp 80

I’m not going to configure everything via CLI flags every time—using a config file is the way to go. Refer to this code:

ngrok/src/ngrok/client/config.go

type Configuration struct {
    HttpProxy          string                          `yaml:"http_proxy,omitempty"`
    ServerAddr         string                          `yaml:"server_addr,omitempty"`
    InspectAddr        string                          `yaml:"inspect_addr,omitempty"`
    TrustHostRootCerts bool                            `yaml:"trust_host_root_certs,omitempty"`
    AuthToken          string                          `yaml:"auth_token,omitempty"`
    Tunnels            map[string]*TunnelConfiguration `yaml:"tunnels,omitempty"`
    LogTo              string                          `yaml:"-"`
    Path               string                          `yaml:"-"`
}

type TunnelConfiguration struct {
    Subdomain  string            `yaml:"subdomain,omitempty"`
    Hostname   string            `yaml:"hostname,omitempty"`
    Protocols  map[string]string `yaml:"proto,omitempty"`
    HttpAuth   string            `yaml:"auth,omitempty"`
    RemotePort uint16            `yaml:"remote_port,omitempty"`
}

When you use ngrok start, it reads the default config file under your home directory:

$HOME/.ngrok

Using Metasploit as an example: the ngrok.gorgiaxx.me subdomain is used to deliver the payload. Usually you don’t need hostname (which is a fully qualified name). It’s only used in some special cases. If your ngrok server can be resolved via CNAME, you can also manually set your own domain. But since newer versions are closed-source now, this is no longer that relevant.

server_addr: gorgiaxx.me:802
trust_host_root_certs: false
tunnels:
  dav:
    proto:
      http: 8080
    subdomain: ngrok
  rev:
    proto:
      tcp: 4444

Then start the tunnels:

./ngrok -config ./ngrok.yml start dav rev

Or start everything at once:

./ngrok -config ./ngrok.yml start-all

ngrok

Summary

You can see that the open-source version of ngrok has many areas that could be improved. From a usability standpoint it isn’t very convenient, and the tunnels don’t have user authentication—so if someone discovers it, they can use it directly. Still, it’s a pretty decent tool.

Reference

ngrok Docs

“Translation” ngrok 1.X configuration doc

ToolsngrokNATNAT Traversal

FRP Usage Notes

Developing a Burp Suite Extension to Brute-Force a Platform