npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@eu-ge-ne/tunnel

v1.0.3

Published

Reverse ssh tunnel

Downloads

5

Readme

@eu-ge-ne/tunnel

Reverse ssh tunnel

Install | Example | Api | License

npm version

Forwards traffic from public to local developer's machine. Think of self-hosted alternative to ngrok, localtunnel etc, but without traffic limitations.

You will need public VPS with dns name. Reverse dns from your hosting provider should serve the purpose as well.

Install

$ npm install @eu-ge-ne/tunnel

Example

Assuming you already have VPS with Ubuntu installed, with <vps-dns-name> dns name.

Harden SSH Access

Disable password authentication for SSH logins and enable public key auth:

  1. On local machine:

    ssh-keygen -b 4096

    File where keys will be saved: id_rsa_proxy Leave passphrase blank.

  2. On VPS:

    mkdir -p ~/.ssh && sudo chmod -R 700 ~/.ssh/
  3. From local machine copy public key (id_rsa_proxy.pub) to VPS:

    scp id_rsa_proxy.pub <user>@<vps-dns-name>:~/.ssh/authorized_keys
  4. Set permissions for the public key directory and the key file itself:

    sudo chmod -R 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
  5. Set SSH daemon options (/etc/ssh/sshd_config):

    PermitRootLogin no
    PasswordAuthentication no
  6. Restart the SSH service to load the new configuration:

    sudo systemctl restart sshd

Install and configure NGINX

sudo apt update
sudo apt install nginx

/etc/nginx/sites-available/default example:

server {
    server_name <vps-dns-name>;

    location / {
        proxy_pass http://127.0.0.1:8888/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

Obtain TLS/SSL certificate from Let’s Encrypt

sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx
sudo certbot --nginx -d <vps-dns-name>

Final /etc/nginx/sites-available/default example:

server {
    server_name <vps-dns-name>;

    location / {
        proxy_pass http://127.0.0.1:8888/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/<vps-dns-name>/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/<vps-dns-name>/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    if ($host = <vps-dns-name>) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name <vps-dns-name>;
    listen 80;
    return 404; # managed by Certbot
}

API

Create instance

import { Tunnel, Options } from "@eu-ge-ne/tunnel";

const options: Options = { /* ... */ };

const tunnel = new Tunnel(options);

Options declaration:

export type Options = {
    /** Hostname or IP address of the server */
    host: string;
    /** SSH port of the server. Default = 22 */
    port?: number;
    /** SSH Username for authentication */
    username?: string;
    /** Password for password-based user authentication */
    password?: string;
    /** Buffer or string that contains a private key for either key-based or hostbased user authentication (OpenSSH format) */
    privateKey?: Buffer | string;
    /** The remote addr to bind on the server */
    remoteHost: string;
    /** The remote port to bind on the server */
    remotePort: number;
    /** The local addr to bind */
    localHost: string;
    /** The local port to bind */
    localPort: number;
    /** How long (in milliseconds) to wait for connection */
    connectTimeout?: number;
    /** How often (in milliseconds) to send SSH-level keepalive packets to the server. Set to 0 to disable */
    keepaliveInterval?: number;
    /** How often (in milliseconds) to check state of the tunnel and reconnect if disconnected */
    checkInterval?: number;
};

Start

await tunnel.start();

Stop

await tunnel.stop();

Get status

import { Status } from "@eu-ge-ne/tunnel";

const status: Status = tunnel.status();

Status declaration:

export type Status = {
    /** State of the tunnel */
    state: keyof typeof State;
    /** How many times disconnect occurred */
    disconnects: number;
    /** Number of active connections */
    connections: number;
}

enum State {
    Stopped,
    Disconnected,
    Disconnecting,
    Connecting,
    Connected,
}

Events

Events declaration:

type Events = {
    /** Emitted on every tunnel state chane */
    state: (state: keyof typeof State) => void;
    /** Emitted on remote socket end */
    end: () => void;
    /** Emitted on remote socket close */
    close: (hadError: boolean) => void;
    /** Emitted on remote socket timeout */
    timeout: () => void;
    /** Emitted when any error occurs */
    error: (message: string, data?: { err: Error }) => void;
}

License

MIT