A simple HTTPS forward proxy for bypassing browser warning of Ngrok. Full support of SSL (free certificates included!), WebSocket, SSE and CORS.
Prerequisites:
- Somebody has sent you a link to an Ngrok endpoint, but it returns a warning page instead of the expected content
- You might be a web developer who is trying to use that endpoint in your code and curious how to bypass the warning page without rewriting the logic
- You have a Docker installed on your machine
OK, take me to the good part: Usage
From the ngrok docs:
To block phishing attacks using our platform, ngrok has added an interstitial page for free accounts receiving requests from browsers. When a user visits an endpoint for the first time, ngrok will serve an interstitial page letting the user know that the content is served via ngrok and that they should not enter sensitive information unless they trust the person that sent them the link. Users should only see this page once per endpoint and it can be completely bypassed by adding the
ngrok-skip-browser-warning
header to your request.
It's tedious to add this header while developing a client for the API, which is exposed behind ngrok. In some cases, e.g. using EventSource, affecting the request headers seems to be impossible.
Add a forward proxy which will add the ngrok-skip-browser-warning
header to all HTTP requests:
For more features, consider getting the ngrok subscription.
Starting from 2023 July 9th, this image includes setup of a valid public CA signed SSL certificate and supports HTTPS (thanks to localhost.direct project).
Run this on the machine from where you are calling the ngrok endpoints:
$ docker run -d --rm \
-p 8443:443 \
-p 8080:80 \
-e NGROK_HOST=https://your-ngrok-domain.ngrok.io \
igops/ngrok-skip-browser-warning:latest
From now, use https://ngrok.localhost.direct:8443
as your API webroot.
E.g., you were told to call GET https://your-ngrok-domain.ngrok.io/api/v1/whatever
. Now you just call GET https://ngrok.localhost.direct:8443/api/v1/whatever
instead, and get the response without the warning page!
*.localhost.direct
is a wildcard record of the public DNS pointing to 127.0.0.1
. You might want to customize the domain name to bind the proxy to, as well as the SSL certificates (see ENV Variables below).
If for some reason you don't want to use HTTPS relay, you can continue using http://ngrok.localhost.direct:8080
or http://localhost:8080
as your API webroot.
You can disable all SSL-related features by passing PROXY_USE_SSL=false
environment variable:
$ docker run -d --rm \
-p 8080:80 \
-e NGROK_HOST=https://your-ngrok-domain.ngrok.io \
-e PROXY_USE_SSL=false \
igops/ngrok-skip-browser-warning:latest
WebSocket and SSE protocols require a special handling of the Upgrade
and Connection
headers. This image supports both protocols out of the box.
However, to distinguish WebSocket and SSE requests from regular HTTP requests, I have implemented the conditional routing based on the request domain names:
Protocol | Over HTTPS | Over HTTP |
---|---|---|
REST, GraphQL, etc. | https://ngrok.localhost.direct:8443 |
http://ngrok.localhost.direct:8080 |
WebSocket | wss://ngrok-ws.localhost.direct:8443 |
ws://ngrok-ws.localhost.direct:8080 |
SSE | https://ngrok-sse.localhost.direct:8443 |
http://ngrok-sse.localhost.direct:8080 |
You can customize the domain names on your own (see ENV Variables) or even the entire routing model (check out the Customization section).
If you're developing a web client which communicates with the HTTP server via multiple protocols, it's worth introducing some configurable constants, such as:
Click on the image to show the text version
Support of WebSocket and SSE was tested by running the Echo Server behind a free ngrok tunnel. Consider reporting an issue if you find any problems.
You can configure the proxy to add the Access-Control-Allow-Origin
header to all responses by setting the ADD_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN
environment variable:
$ docker run -d --rm \
-p 8443:443 \
-p 8080:80 \
-e NGROK_HOST=https://your-ngrok-domain.ngrok.io \
-e ADD_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN='*' \
igops/ngrok-skip-browser-warning:latest
This image uses Nginx as a proxy server, as well as Jinja template engine to generate the Nginx config on the fly.
Feel free to replace /etc/nginx/j2/default.j2.conf
with your own implementation, or use my config as a basis.
For instance, you might create custom.j2.conf
with a very bare minimum for your experiments:
Click on the image to show the text version
Mount it as follows:
$ docker run -d --rm \
-p 8443:443 \
-p 8080:80 \
-e NGROK_HOST=https://your-ngrok-domain.ngrok.io \
-v $PWD/custom.j2.conf:/etc/nginx/j2/default.j2.conf \
igops/ngrok-skip-browser-warning:latest
Jinja template variables refer to the ENV variables with the same names in SNAKE_UPPER_CASE.
Jinja Variable | Environment Variable |
---|---|
ProxyHostREST | PROXY_HOST_REST |
ProxyHostWSSupport | PROXY_HOST_WS_SUPPORT |
ProxyHostSSESupport | PROXY_HOST_SSE_SUPPORT |
ProxyUseSSL | PROXY_USE_SSL |
ProxySSLCertName | PROXY_SSL_CERT_NAME |
ProxySSLKeyName | PROXY_SSL_KEY_NAME |
ProxyForceHTTPS | PROXY_FORCE_HTTPS |
TargetScheme | Scheme of NGROK_HOST (typically equals to https ) |
TargetHost | Domain name of NGROK_HOST |
AddHeaderAccessControlAllowOrigin | ADD_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN |
The simplest way to add a custom endpoint is to bind an additional *.localhost.direct
subdomain with your own proxying rules:
Click on the image to show the text version
A custom location block might be as follows:
Click on the image to show the text version
Variable | Default value | Description |
---|---|---|
NGROK_HOST | - | Mandatory. Your ngrok host, e.g. https://your-ngrok-domain.ngrok.io .Specifying a protocol is optional, https will be used by default.Any url parts after a domain name will be trimmed. |
PROXY_HOST_REST | ngrok.localhost.direct |
Optional. A domain name to listen on REST API calls. |
PROXY_HOST_WS_SUPPORT | ngrok-ws.localhost.direct |
Optional. A domain name to listen on WebSocket API calls. |
PROXY_HOST_SSE_SUPPORT | ngrok-sse.localhost.direct |
Optional. A domain name to listen on SSE API calls. |
PROXY_USE_SSL | true |
Optional. Enables relay over HTTPS. You can mount your own certificates to /etc/nginx/certs . If the directory is not mounted, localhost.direct certificate will be downloaded on container bootstrap. |
PROXY_FORCE_HTTPS | false |
Optional. Forcibly redirect HTTP calls to HTTPS. |
PROXY_SSL_CERT_NAME | localhost.direct.crt |
Optional. Override the name of the certificate file. Mount the file to /etc/nginx/certs/my-custom-cert.crt . |
PROXY_SSL_KEY_NAME | localhost.direct.key |
Optional. Override the name of the certificate key. Mount the file to /etc/nginx/certs/my-custom-cert.key . |
ADD_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN | (empty string) | Optional. Add custom Access-Control-Allow-Origin to all responses. |
https://github.com/igops/ngrok-skip-browser-warning
Feel free to contribute.