expose-localhost

Reverse proxy that creates a secure tunnel from public endpoint to locally running web service


Keywords
route53, certificate, ec2, ngrok-alternative, tunnel
License
Other
Install
pip install expose-localhost==0.5

Documentation

Python

Platform Supported

Generic badge

Repo Stats

GitHub GitHub repo size GitHub code size

Deployments

doc pypi markdown

Pypi-format Pypi-status sourcerank

Expose localhost using EC2

Reverse proxy that creates a secure tunnel from public endpoint to locally running web service

Setup

Environment Variables:

Environment variables can be loaded from any .env file.

  • PORT: Port number that has to be exposed (on which a localhost service/app/api is running)

Optional env
  • OPEN_PORT: Boolean flag to enable ingress and egress on the specified port. Defaults to False
  • CHANNEL_TIMEOUT: Timeout in seconds to wait for an incoming channel connection. Defaults to 100
  • IMAGE_ID: ID of any public AMI with an Ubuntu OS. Defaults to a region specific image ID.
  • INSTANCE_TYPE: Instance type for tunneling. Defaults to t2.nano
  • AWS_ACCESS_KEY: Access key to access AWS resources. Defaults to ~/.aws/config
  • AWS_SECRET_KEY: Secret key to access AWS resources. Defaults to ~/.aws/config
  • AWS_REGION_NAME: Region name where the instance should live. Defaults to US-WEST-2
  • KEY_PAIR: Name for the ec2 key pair file. Defaults to expose_localhost
  • SECURITY_GROUP: Name for the security group to allow port access. Defaults to Expose Localhost
  • SERVER_INFO: Name for the JSON file to store the configuration info. Defaults to server_info.json
  • EMAIL_ADDRESS: Email address to create the self-signed SSL and private key. Defaults to USER@expose-localhost.com
  • ORGANIZATION: Organization name for the certificate. Defaults to the AWS endpoint.
  • HOSTED_ZONE: Hosted zone name registered using route53. Example: mywebsite.com
  • SUBDOMAIN: Sub-domain that has to be added for the domain name. Example: tunnel
Latency

CHANNEL_TIMEOUT can be adjusted to improve latency depending on the application's role.

Network Latency

Shorter timeouts can make your server more responsive to incoming connections but may also lead to false negatives if network latency is high. If connections take longer to establish due to network conditions, a short timeout might reject valid connections prematurely.

Connection Rate

If your server expects a high rate of incoming connections, and you want to process them quickly, a shorter timeout can be beneficial. However, it also means that your server needs to be able to process connections rapidly.

Resource Usage

Short timeouts can lead to a higher rate of repeated checks, which may consume more CPU resources on the server. Ensure that your server has the capacity to handle frequent connection checks, if you are setting CHANNEL_TIMEOUT too low.

Custom endpoint

The public DNS names for EC2 instances are long and messy. To avoid that, an A record can be added to the route53 hosted zone.

⚠️   Requires an active hosted zone on route53.

💡   SUBDOMAIN.HOSTED_ZONE will be the endpoint to access the localhost from public internet.

SSL certificate
  • Securing the tunnel requires the certificate chain and the key file.
  • The certificate and key files should be in pem format stored in current working directory.
  • File names should be stored as key_file and cert_file env var.
  • No certs? No problem. expose will generate a self-signed certificate and a private key automatically.

⚠️   Some web browsers might throw a warning and some might even block a self-signed certificate/private CA.

Manually generate self-signed certificate

openssl req -newkey rsa:2048 -sha256 -nodes -keyout private.pem -x509 -days 365 -out public.pem -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=tunnel.example.com"

To verify the generated certificate

openssl x509 -inform pem -in public.pem -noout -text

Usage

Installation
python3 -m pip install expose-localhost
Tunneling:
import os

os.environ['env_file'] = 'custom'  # to load a custom .env file

import expose

# Instantiate object
tunnel = expose.Tunnel()

# Start tunneling
tunnel.start()

# set 'purge' flag to 'True' to reclaim AWS resources if configuration fails
# tunnel.start(purge=True)

# Stop tunneling - deletes all AWS resources acquired
tunnel.stop()

Troubleshooting

If E: Could not get lock /var/lib/dpkg/lock-frontend occurs during startup, simply rerun the script with start command.

This occurs when apt hasn't released the resources yet. A retry logic is in place to delete the lock file automatically. However, if any such issues persist, re-running tunnel.start() will simply re-configure the instance entirely.

Limitations

Currently expose cannot handle, tunneling multiple port numbers without modifying the following env vars in the .env file.

KEY_PAIR        # SSH connection to AWS ec2
KEY_FILE        # Private key filename for self signed SSL
CERT_FILE       # Public certificate filename for self signed SSL
SERVER_INFO     # Filename to dump JSON data with server configuration information
SECURITY_GROUP  # Ingress and egress firewall rules to control traffic allowed via VPC

Coding Standards

Docstring format: Google
Styling conventions: PEP 8
Clean code with pre-commit hooks: flake8 and isort

Release Notes

Requirement

python -m pip install gitverse

Usage

gitverse-release reverse -f release_notes.rst -t 'Release Notes'

Linting

PreCommit will ensure linting, and the doc creation are run on every commit.

Requirement

pip install sphinx==5.1.1 pre-commit recommonmark

Usage

pre-commit run --all-files

Pypi Package

pypi-module

https://pypi.org/project/expose-localhost/

Runbook

made-with-sphinx-doc

https://thevickypedia.github.io/expose/

License & copyright

© Vignesh Rao

Licensed under the MIT License