-
-
Save rjz/af40158c529d7c407420fc0de490758b to your computer and use it in GitHub Desktop.
#!/bin/sh | |
# ngrok's web interface is HTML, but configuration is bootstrapped as a JSON | |
# string. We can hack out the forwarded hostname by extracting the next | |
# `*.ngrok.io` string from the JSON | |
# | |
# Brittle as all get out--YMMV. If you're still reading, usage is: | |
# | |
# $ ./ngrok_hostname.sh <proto> <addr> | |
# | |
# To retrieve the ngrok'd URL of an HTTP service running locally on :3332, use: | |
# | |
# $ ./ngrok_hostname.sh http localhost:3332 | |
# | |
# The protocol (http, https, etc) of the forwarded service | |
PROTO=$1 | |
# The address of the forwarded service | |
ADDR=$2 | |
# Hack JSON out of the web interface bootstrap | |
json=$(curl -s localhost:4040/inspect/http \ | |
| grep -oP 'window.common[^;]+' \ | |
| sed 's/^[^\(]*("//' \ | |
| sed 's/")\s*$//' \ | |
| sed 's/\\"/"/g') | |
# Parse JSON for the URLs matching the configured `$ADDR` | |
hosts=$(echo $json \ | |
| jq -r ".Session.Tunnels \ | |
| values \ | |
| map(select(.Config.addr == \"$ADDR\") | .URL) | .[]") | |
echo "$hosts" | grep "^${PROTO}:" |
Thanks @fvclaus!
Thanks @fvclaus :)
Thanks guys! 👍
my ngrok doesn't expose anything on port 4040, Is there a specific option when starting ngrok that I should use (normally I start it using ngrok tcp 123
)
Thanks. On minimal system setup I used:
echo -e 'GET /api/tunnels HTTP/1.1\nHost: 127.0.0.1\n' | nc localhost 4040
Apologies for the rez, but to answer @krzyk: You can configure a web_addr
property in the ngrok.yml
(see "The ngrok configuration file" and "web_addr" here: https://ngrok.com/docs).
If you just want to know the port, it's the one listed in ngrok's session under Web Interface
:
Mine alternates from 4040
to 4041
at-whim.
Thanks a lot. Works like charm. This is exactly what I was looking for.
Extract the public url:
curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p'
Hi, I have two tunnels in Ngrok.. how do I extract the public url of two different tunnels?
curl --silent http://127.0.0.1:4040/api/tunnels | jq '.tunnels[0].public_url' ---> This will give you the public URL of the first tunnel
curl --silent http://127.0.0.1:4041/api/tunnels | jq '.tunnels[0].public_url' ---> This will give you the public URL of the second tunnel.
Likewise, if you have multiple tunnels, increment the port number (4041) in the above URL by one to get the corresponding public URL.
Ex : 4042 for third tunnel, 4043 for fourth tunnel and so on.
This one worked for me.
curl -s localhost:4040/api/tunnels | jq -r .tunnels[0].public_url
is there any way to do that with C#?
Is there a JavaScript version of this?
def get_ngrok_hostname():
url = "http://127.0.0.1:4040/api/tunnels"
try:
response = requests.get(url)
url_new_https = response.json()["tunnels"][0]["public_url"]
return url_new_https
except:
return None
# print(json.dumps(r.json(), indent=4))
# pprint.pprint(r, width=1)
Or to query by name rather than position:
curl --silent http://127.0.0.1:4040/api/tunnels | jq -r '.tunnels[] | select(.name == "MY_TUNNEL_NAME") | .public_url'
=>
https://abcde12345.ngrok.io
** Edit Jan 15 2021: added -r
to remove quotes
for the Rails community:
With this code you run the rails app with assets pointing to the tunnel, if available 👍
Create an initializer and call it "ngrok.rb" (just for the sake of sanity) and paste this on:
require 'net/http'
require 'json'
begin
uri = URI("http://127.0.0.1:4040/api/tunnels")
ngork_resp = Net::HTTP.get(uri)
ngork_json = JSON.parse(ngork_resp)
tunnel = ngork_json["tunnels"].first
tunnel_uri = URI(tunnel["public_url"])
Rails.application.configure do
config.hosts << tunnel_uri.host
config.action_controller.asset_host = tunnel_uri.to_s
config.action_mailer.asset_host = config.action_controller.asset_host
end
puts "Yep, tunnel configured! all set on #{tunnel_uri.to_s}"
rescue
puts "no tunnel configured! skiping configuration..."
end
@michael-lins That initializer is excellent! Thank you for posting that.
Nice threads !! I make python scripts to send all ngrok connections to telegram bot. So, we can connect to ssh without login to ngrok web.
https://github.com/vanbwodonk/Ngrok-TelegramBot-Status
Thanks @fvclaus)
My gosh guys...thanks, this is awesome!
I've created a bash script with the snippets found here, which takes the ngrok hostname and copies it into a spring configuration file (yml).
#!/bin/sh
#
# Wrapper script to launch reverse proxy with local configuration
# and copy tunnel's hostname into (spring) yml configuration
#
# Created 15 december 2020 - Federico Ricchiuto <f.ricchiuto@ital.dev>
#
FILE=./ngrok
CONFIGURATION=./ngrok.yml
SPRING_CONFIG_PATH=~/yourprojectpath/src/main/resources/config/application-dev.yml
OIDC_PROTOCOL='http'
OIDC_PATH='auth/realms/jhipster'
bold=$(tput bold)
echo "Checking ngrok executable..."
if test -f "$FILE"; then
if test -f "$CONFIGURATION"; then
echo "Starting ngrok..."
(./ngrok start -config ./ngrok.yml --all ) > /dev/null &
sleep .7 # Wait for ngrok launch
NGROK_HOSTNAME=$(curl --silent --show-error http://127.0.0.1:4040/api/tunnels | sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p')
echo "Replacing backend app IdP setting..."
NEW_SETTING="$OIDC_PROTOCOL://$NGROK_HOSTNAME/$OIDC_PATH"
sed -i -e "s#issuer-uri.*#issuer-uri: ${NEW_SETTING}#" "$SPRING_CONFIG_PATH"
echo "${bold}ngrok running @ $NGROK_HOSTNAME"
wait
else
echo "Missing ngrok.yml configuration file - Pull from repository if deleted"
fi
else
echo "ngrok executable not found" >&2
echo "Download from: https://ngrok.com/download"
fi
It verifies also if the ngrok executable is present in the same folder. You can call directly ngrok without checking it's configuration file, but in case that you need it:
authtoken: xxxx
region: eu
tunnels:
revproxy:
addr: 80
proto: http
# bind_tls: true # enables https only
inspect: true # enables console @ localhost:4040
Im not a bash scripting expert, it can be improved. The hard part is calling curl after it's launch, as the process is running. Without redirecting it to /dev/null it wouldn't be possible to execute the following commands.
This way ngrok's output is lost, it's kinda sad :/
seems not working anymore:
% curl --silent --show-error http://127.0.0.1:4040/api/tunnels
curl: (52) Empty reply from server
% curl -v http://localhost:4040/inspect/http
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 4040 (#0)
> GET /inspect/http HTTP/1.1
> Host: localhost:4040
> User-Agent: curl/7.64.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
* Closing connection 0
Which version of ngrok?
Which version of ngrok?
should be latest one, just tried one hour ago
should be latest one, just tried one hour ago
Just tried with the latest stable, it is working as usual.
Did you add inspect: true
in your config file? (ngrok.yml
)
no luck.thx anyway
url_new_https = response.json()["tunnels"][0]["public_url"]
Nice, good stuff. Amazing thread here.
Shell script
OSX Sonoma 14.3
ngrok version 3.5.0
local json_data=$(curl -s localhost:4040/api/tunnels)
local public_url=$(echo "$json_data" | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])")
echo $public_url
local json_data=$(curl -s localhost:4040/api/tunnels)
local public_url=$(echo "$json_data" | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])")
echo $public_
local json_data=$(curl -Chikita Isaac bitcoin.comlocalhost:4040/api/tunnels)
local public_url=$(echo "$json_data" | python3 -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])")varonis.com
echo $public_freewallet(100000000000000000000000000000000000000000000000000009)
Thanks @fvclaus!