Ngrok for Local Infrastructure


Hello, meet ngrok (, an easy way to tunnel traffic from a local machine (i.e. VM) to an external address. With ngrok, you can quickly set up a red team infrastructure which can be used multiple times vs tearing down after every engagement. We'll go over some of the pros and cons of using this as well as how to set it all up.

Pros of Using Ngrok

  • Quickly set up a full red team infrastructure inside a local VM
  • A lot of the infrastructure can be reused if data separation is ensured
  • BIG: no need to use domain fronting or a redirector (ngrok will act as your redirector)
  • You can create multiple tunnels with multiple hostnames to redirect traffic to one teamserver
  • EDR products and proxies don't usually resolve or follow a CNAME record so it may bypass some restrictions
  • Easily and quickly set up an openssl certificate with HTTP verification
  • All data is housed on your local machine and not sitting in the cloud (see: someone else's computer)
  • Easy access to tools and payloads since everything is housed inside the VM. No more using SCP to transfer files to an external server
  • You can set up basic HTTP authentication super easily
    • This has a limitation though which only allows stageless code to be executed successfully. Otherwise this will pop up:


  • BIG: The teamserver will be running from your VM. If that gets shut down, so does the tunnel and teamserver
    • Ngrok isn't really made for extended red teams
  • You can't limit who attempts to connects to your teamserver. There is IP whitelisting with ngrok but it's applied globally instead of on a per-tunnel basis (
  • Currently, I haven't found a way to send the external IP address of the beacon within the tunnel.
  • You'll need to clear the logs/data from cobalt strike after each test to avoid cross-client contamination
  • I would recommend having a "clean" vm with the infrastructure set up and then taking a snapshot. Conduct the test, save all the info you need and revert the snapshot

Ngrok Initial Setup

This phase shouldn't need to be repeated.

  1. First, you'll have to download ngrok. It's easiest to just log into the dashboard -
  2. If you funnel everything through a specific domain or through a TLS connection, you'll want a business account (about $12 a month)
  3. Unzip the file you downloaded and run the command that's in step 3 in the ngrok dashboard. This will initialize the authorization file (we'll also specify this key in the config file below)

An easy way to test and see if it's working is start your local apache server and then run

./ngrok http 80

If all works it will serve whatever index page you're hosting or you can try to access any page in your webserver root dir. It will print out a URL for you to access

TLS/HTTP/Teamserver Access Setup

Here we'll set up a few different services using a custom domain. It's a good idea to have a list of potential ports/services you'll use with CS so you can set everything up now. For now, we'll just go over tunneling 80, 443, and 50050. I've added multiple test points in here which can be skipped if this isn't your first rodeo.

  1. First, reserve the domain you want to use on the ngrok portal. It will provide you a CNAME value for you to enter in the DNS records for your domain. It should look similar to the two images below.

Ngrok dashboard:


2. Second, reserve the TCP domain as well - we'll use this for connecting to the         cobalt strike teamserver

3. Once the DNS record is live and you see the "Correct" status similar to in step 1, test it out by running ngrok with the hostname flag and navigating to your custom domain (you'll see an error if apache isn't running, but everything is working)

./ngrok http -hostname=[your custom hostname] 80
  1. With this working, we'll want to create our SSL cert and keep ngrok running for HTTP verification. Clone down

2. This will help us install a certificate. You could also just use certbot

certbot certonly --standalone --preferred-challenges http -d [domain]

3. To test out the certificate, run ngrok with the tls flag

./ngrok tls --hostname=[your custom hostname] 443
  • This will use the local certificates that we just installed so if you're adding more subdomains or other options, YMMV
  • It's recommended to use a config file to start the tunnels you need. This will allow you to run multiple tunnels at once

4. Create a config file similar to the following. You'll need to enter your auth token. Also comment out the auth lines if not using (# is a comment in yaml):

authtoken: [redacted]
region: us
console_ui: true
   addr: 443
   # auth: testuser:testpassword
   hostname: [your custom hostname]
   bind_tls: true
   inspect: false
   proto: tls

   addr: 80
   # auth: testuser:testpassword
   hostname: [your custom hostname]
   bind_tls: false
   inspect: false
   proto: http

   addr: 50050
   proto: tcp
   remote-addr: [redacted - TCP Address from ngrok dashboard]
  • You may want to add in a section for file sharing to make it easier for a system to reach out to grab a payload (Serving Local Directories -

5. Call ngrok with the config file and specify the tunnels you want to start

./ngrok start -config myconfig.yml httpBeacon httpsBeacon teamserver-access
  • It's important to note the variables after the config file are the tunnels you want to start
  • If all works correctly, you'll see the following:

Creating Beacons

Next, we'll want to create our beacons on the teamserver.

  1. Open a new tab and start up the teamserver with any settings you want (use the local IP address for the system (ex., not the external IP address)
  2. It is recommended to use a malleable profile for this step
  3. Run cobalt strike and connect to it using the remote-addr address in the config file above

4. Create an HTTP(S) beacon with the host and stager pointing to your custom domain. This process will be almost the exact same for each beacon other than the HTTP C2 Port

HTTP Authentication (Use IP Whitelisting Instead)

If you enabled HTTP authentication in your ngrok yaml file, you'll have to modify a few things. Another way around this is to use IP whitelisting within the ngrok dashboard (probably a better option).

  1. Change the protocol in the ngrok config file above from "tls" to "http" and uncomment the auth lines
  2. Enter that info into beacon's HTTPS Proxy settings
  3. Should be similar to: http://testuser:[email protected]:80
  4. Start up Burp and a proxy, grab that URL that it spits out in the beacon setup, and enter it in your browser
  5. It should capture a request with an Authorization header. Grab that line and place that in your malleable profile for both the GET and POST blocks
  6. Hardcoding sucks, I know but this is the only way I could get it working for now. Other thoughts welcome

7. Go into the proxy settings again for the beacon and reset the info so it's all blank

8. Repeat the previous steps for the other beacon you want. You can skip the proxy auth step since you should already have that within the profile for all beacons

9. Test everything out. If using basic authentication, you'll need to generate a stageless payload. If not using any auth, you can just use a PowerShell one-liner and you'll see something like what's below.

Hopefully everything is working at this point. Remember to keep your VM up and the ngrok service running.

I hope that this helps give some ideas on how you can use ngrok for your projects. If you have any questions, feel free to Contact Us!