Go HTTP tunnel is a reverse tunnel based on HTTP/2.


Go HTTP tunnel GoDoc Go Report Card Build Status Github All Releases

Go HTTP tunnel is a reverse tunnel based on HTTP/2. It enables you to share your localhost when you don't have a public IP.


  • HTTP proxy with basic authentication
  • TCP proxy
  • SNI vhost proxy
  • Client auto reconnect
  • Client management and eviction
  • Easy to use CLI

Common use cases:

  • Hosting a game server from home
  • Developing webhook integrations
  • Managing IoT devices


Build the latest version.

$ go get -u github.com/mmatczuk/go-http-tunnel/cmd/...

Alternatively download the latest release.


There are two executables:

  • tunneld - the tunnel server, to be run on publicly available host like AWS or GCE
  • tunnel - the tunnel client, to be run on your local machine or in your private network

To get help on the command parameters run tunneld -h or tunnel -h.

Tunnel requires TLS certificates for both client and server.

$ openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout client.key -out client.crt
$ openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout server.key -out server.crt

Run client:

  • Install tunnel binary
  • Make .tunnel directory in your project directory
  • Copy client.key, client.crt to .tunnel
  • Create configuration file tunnel.yml in .tunnel
  • Start all tunnels
$ tunnel -config ./tunnel/tunnel.yml start-all

Run server:

  • Install tunneld binary
  • Make .tunneld directory
  • Copy server.key, server.crt to .tunneld
  • Start tunnel server
$ tunneld -tlsCrt .tunneld/server.crt -tlsKey .tunneld/server.key

This will run HTTP server on port 80 and HTTPS (HTTP/2) server on port 443. If you want to use HTTPS it's recommended to get a properly signed certificate to avoid security warnings.

Run Server as a Service on Ubuntu using Systemd:

  • After completing the steps above successfully, create a new file for your service (you can name it whatever you want, just replace the name below with your chosen name).
$ vim tunneld.service
  • Add the following configuration to the file
Description=Go-Http-Tunnel Service

ExecStart=/path/to/your/tunneld -tlsCrt /path/to/your/folder/.tunneld/server.crt -tlsKey /path/to/your/folder/.tunneld/server.key

  • Save and exit this file.
  • Move this new file to /etc/systemd/system/
$ sudo mv tunneld.service /etc/systemd/system/
  • Change the file permission to allow it to run.
$ sudo chmod u+x /etc/systemd/system/tunneld.service
  • Start the new service and make sure you don't get any errors, and that your client is able to connect.
$ sudo systemctl start tunneld.service
  • You can stop the service with:
$ sudo systemctl stop tunneld.service
  • Finally, if you want the service to start automatically when the server is rebooted, you need to enable it.
$ sudo systemctl enable tunneld.service

There are many more options for systemd services, and this is by not means an exhaustive configuration file.


The tunnel client tunnel requires configuration file, by default it will try reading tunnel.yml in your current working directory. If you want to specify other file use -config flag.

Sample configuration that exposes:

  • localhost:8080 as webui.my-tunnel-host.com
  • host in private network for ssh connections

looks like this

    server_addr: SERVER_IP:5223
        proto: http
        addr: localhost:8080
        auth: user:password
        host: webui.my-tunnel-host.com
        proto: tcp
  	    proto: sni
  	    addr: localhost:443
  	    host: tls.my-tunnel-host.com

Configuration options:

  • server_addr: server TCP address, i.e.
  • tls_crt: path to client TLS certificate, default: client.crt in the config file directory
  • tls_key: path to client TLS certificate key, default: client.key in the config file directory
  • root_ca: path to trusted root certificate authority pool file, if empty any server certificate is accepted
  • tunnels / [name]
    • proto: tunnel protocol, http, tcp or sni
    • addr: forward traffic to this local port number or network address, for proto=http this can be full URL i.e. https://machine/sub/path/?plus=params, supports URL schemes http and https
    • auth: (proto=http) (optional) basic authentication credentials to enforce on tunneled requests, format user:password
    • host: (proto=http, proto=sni) hostname to request (requires reserved name and DNS CNAME)
    • remote_addr: (proto=tcp) bind the remote TCP address
  • backoff
    • interval: how long client would wait before redialing the server if connection was lost, exponential backoff initial interval, default: 500ms
    • multiplier: interval multiplier if reconnect failed, default: 1.5
    • max_interval: maximal time client would wait before redialing the server, default: 1m
    • max_time: maximal time client would try to reconnect to the server if connection was lost, set 0 to never stop trying, default: 15m

How it works

A client opens TLS connection to a server. The server accepts connections from known clients only. The client is recognized by its TLS certificate ID. The server is publicly available and proxies incoming connections to the client. Then the connection is further proxied in the client's network.

The tunnel is based HTTP/2 for speed and security. There is a single TCP connection between client and server and all the proxied connections are multiplexed using HTTP/2.


If this project help you reduce time to develop, you can give me a cup of coffee.


A GitHub star is always appreciated!


Copyright (C) 2017 Michał Matczuk

This project is distributed under the AGPL-3 license. See the LICENSE file for details. If you need an enterprice license contact me directly.

  • io error on http2

    io error on http2

    I get this error: io error: Put http://localhost/login: http2: unsupported scheme .. what could be the problem?

    opened by radutopala 20
  • Lets Encrypt support

    Lets Encrypt support

    This PR adds support for Let's Encrypt by setting two new flags

      -letsEncrypt (bool) to enable lets encrypt autocert generation
      -letsEncryptCacheDir (string) path to store cached certificates

    For lets encrypt port 80 and 443 are mandatory so httpAddr and httpsAddr will ignore the port but will still be able to bind to a specific host.

    opened by jhernandezb 19
  • Identify dead connections

    Identify dead connections

    I'm having issues with long lived connections:

    • the server sometimes receives connection requests from clients that are reportedly already connected, and reject them.
    • when the server restarts, some clients do not try to connect again.

    I debugged the issue and found out that once the client is connected to the server this connection is kept open waiting for a user to connect to the server. If the connection dies without notifying the client or server, they would keep listening to dead connections.

    If the server believes that a dead connection belonging to an id is open it would reject new (valid) connections from that id.

    A client may keep listening to a dead connection forever, effectively preventing the client to retry and open a fresh connection.

    My workaround was to turn on TCP keepalive for the client connection, and to let the server ping (http ping) the existing client connection when a connection request with an already connected id is received.

    opened by goriccardo 12
  • Certificate problem

    Certificate problem

    Hello I can't connect to tunneld. I have error: "msg certificate error err ptls: expecting 1 peer certificate, got 0" Both client and server are on Windows. Both have certs files and files looks ok (I also tried files from tunnel\testdata directory). Any idea what can cause the problem?

    opened by Green7 7
  • ssh tunnel connection timeout

    ssh tunnel connection timeout

    @mmatczuk I want to ssh on system( from client using this tunnel solution tool. so i am not able to do that. getting timeout error.(attached screenshot of that) added my architecture diagram screenshot and also i have added my tunnel.yml file content in that screenshot

    i am trying to execute below command from client

    ssh -p 2222 [email protected]

    let me know what things are wrong so i can fix it.

    tunnel_diagram (1) image


    opened by dipenpatel235 7
  • TCP proxy connection remains open (CLOSED_WAIT)

    TCP proxy connection remains open (CLOSED_WAIT)

    In a client TCP Proxy, when a local connection is closed the function call transfer(local, r, ...) does not return, effectively preventing the local connection to be properly closed.

    To reproduce:

    1. Create a TCP tunnel
    2. Connect to the tunnel
    3. Close the tunnel connection
    4. invoke:
    lsof -i -a -p `pidof tunnel`

    At least one connection marked CLOSED_WAIT is present.

    A quick and dirty solution would be to close the response reader after the local connection dies:

    From 736802f154da59e23b4f1d89baafa49a1f579815 Mon Sep 17 00:00:00 2001
    From: Riccardo Gori <[email protected]>
    Date: Tue, 14 Nov 2017 16:07:31 +0100
    Subject: [PATCH] Properly close proxy connection
     tcpproxy.go | 1 +
     1 file changed, 1 insertion(+)
    diff --git a/tcpproxy.go b/tcpproxy.go
    index f7dc199..d72bb76 100644
    --- a/tcpproxy.go
    +++ b/tcpproxy.go
    @@ -104,6 +104,7 @@ func (p *TCPProxy) Proxy(w io.Writer, r io.ReadCloser, msg *proto.ControlMessage
     			"dst", msg.ForwardedBy,
     			"src", target,
    +		r.Close()
    opened by goriccardo 6
  • HTTP forwarded headers

    HTTP forwarded headers

    opened by mmatczuk 6
  • Linux/mips binary

    Linux/mips binary

    please provide linux/mips (32bit) binary

    opened by bluemeda 6
  • Update and lock latest go-http-tunnel dependency

    Update and lock latest go-http-tunnel dependency

    Update and explicitly set the go-http-tunnel dependency. A raw clone and dep ensure fails to build as the dependency on the project's own files fails to resolve to the latest version containing SNI protocol.

    opened by janpieterz 5
  • invalid identifier

    invalid identifier "2DZE5EU-...": check digit incorrect

    I cannot start server with the sample client file

    # List your client-ids here
    # Each line should contain only a single client-id followed by a comma (,) and a backslash (\)
    # The last line shouldn't have the comma and backslash!
    # Make sure no stray whitespace at the end of lines!!!
    # with vim do :%s/\s\+$//e
    # Please list the client ids here with name
    # client-id                                                       description
    opened by jmhostalet 0
  • Feature request.  I would like an option for the tunnel to never be cut.

    Feature request. I would like an option for the tunnel to never be cut.

    If I try to start a tunnel when a tunnel is already using that port on the server, the program exits with error "failed to start tunnels: connection is being cut". My use case is remote raspberry pies that I never want to lose contact with, so for me the ideal behavior would be to not exit when this error occurs. There are obviously several ways to go about this. I could obviously write a service for systemd or use cron, but it would be nice if go-http-tunnel handled this itself. I might poke around the code and figure it out myself, but I figured I'd ask first and maybe somebody already knows right where to make the change.

    opened by synaption 0
  • client not subscribed issue

    client not subscribed issue

    hi i have bought a vps and a domain and i installed the go-http-tunnel in server and client side i can see the client connects to server but when i type the host i did in tunnel.yml it returns client not subscribed im realy confused because yesterday it was just working but suddnly it showd this problem the command shows in server side : level 0 action round trip failed addr myhome_ip:62003 host my-domain.xyz url /favicon.ico err client not subscribed and in client side : 2021/04/09 22:06:43 config server_addr: vps_ip:5223 tls_crt: client.crt tls_key: client.key root_ca: "" backoff: interval: 500ms multiplier: 1.5 max_interval: 1m0s max_time: 15m0s tunnels: webui: proto: http addr: host: .webui.myip.xyz

    2021/04/09 22:06:43 level 1 action start 2021/04/09 22:06:43 level 1 action dial network tcp addr vps_ip:5223 2021/04/09 22:06:44 level 1 action handshake addr

    opened by aliakbar-bsr 1
  • Fix backoff inconsistency

    Fix backoff inconsistency

    The reset is performed at the time the connection has been established. This can cause the problem described in #76. I the server connection fails after max_time + x it tries to reconnect. If that fails once it immediately stops trying with the message "backoff limit exceeded"

    opened by hons82 0
  • stuck at handshake.

    stuck at handshake.

    When I run the start-all client command, it gets as far as the handshake then gets stuck. I have been using go-http-tunnel reliably for months to ssh into my remote sensors. This started happening after I had some problems with systemD. I have tried using different ports in my tunnel.yml. I have also tried apt update, apt upgrade with no luck. Here is the output or the command.

    2021/03/18 14:19:00 config server_addr: xxx.xxx.xxx.xxx tls_crt: /home/pi/.tunnel/client.crt tls_key: /home/pi/.tunnel/client.key root_ca: "" backoff: interval: 500ms multiplier: 1.5 max_interval: 1m0s max_time: 0s tunnels: ssh: proto: tcp addr: localhost:22 remote_addr:

    2021/03/18 14:19:00 level 1 action start 2021/03/18 14:19:00 level 1 action dial network tcp addr xxx.xxx.xxx.xxx:10008 2021/03/18 14:19:00 level 1 action handshake addr xxx.xxx.xxx.xxx:10008

    opened by synaption 2
  • configuration error: tls invalid protocol

    configuration error: tls invalid protocol "sni"

    tunnel.ymal file:

    server_addr: 64.x.x.x:5223 tunnels: webui: proto: http addr: localhost:4200 host: chatbot.x.online tls: proto: sni addr: localhost:8000 host: developer.x.online

    x was filled with my public server ip or its name, and it's hidden here.

    when I am trying to connect, the following error is appearing configuration error: tls invalid protocol "sni"

    opened by Abdo-Saleh 3
  • multiple hosts certificates

    multiple hosts certificates

    Is there a way to use multiple hosts like.x.com and y.com and use different certbot certificates for them?

    opened by stellanhaglund 0
  • failed to start HTTP: listen tcp :80: bind: permission denied

    failed to start HTTP: listen tcp :80: bind: permission denied

    failed to start HTTP: listen tcp :80: bind: permission denied

    opened by SUSTHESURFER 0
  • TLS encryption supported ?

    TLS encryption supported ?

    opened by knasim 0
  • #119 Add log level constants

    #119 Add log level constants

    No changes to current package interface.
    Adds 4 exported symbols to protect developers from magic numbers.

    logger := log.NewFilterLogger(log.NewStdLogger(), log.LevelInfo)

    See #119

    opened by kevburnsjr 2
Michal Jan Matczuk
Mate over coffee, running over biking, reading over watching, question over answers
Michal Jan Matczuk
Cloud Native Tunnel

inlets is a Cloud Native Tunnel written in Go Expose your local endpoints to the Internet or within a remote network, without touching firewalls. Foll

inlets 8.4k Jul 26, 2021
Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH.

Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH. Single executable including both client and server. Written in Go (golang). Chisel is mainly useful for passing through firewalls, though it can also be used to provide a secure endpoint into your network.

Jaime Pillora 6.1k Jul 23, 2021
tunnels to localhost and other ssh plumbing

remotemoe is a software daemon for exposing ad-hoc services to the internet without having to deal with the regular network stuff such as configuring VPNs, changing firewalls, or adding port forwards.

Kristian Mide 74 Jul 11, 2021
Iris Go binding

Iris Go binding This is the official Go language binding for the Iris cloud messaging framework. Version v1 of the binding is compatible with Iris v0.

Project Iris 135 May 4, 2021
A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.

frp README | 中文文档 What is frp? frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the Internet. As of now, it s

null 47k Jul 22, 2021
Automatically spawn a reverse shell fully interactive for Linux or Windows victim

Girsh (Golang Interactive Reverse SHell) Who didn't get bored of manually typing the few lines to upgrade a reverse shell to a full interactive revers

null 172 Jul 23, 2021
Clash - A rule-based tunnel in Go.

Clash A rule-based tunnel in Go. Features Local HTTP/HTTPS/SOCKS server with authentication support VMess, Shadowsocks, Trojan, Snell protocol support

Dreamacro 17.8k Jul 18, 2021
Crank4go API Gateway Brief Introduction It is a Golang implementation of Crank4j

Crank4go API Gateway Brief Introduction It is a Golang implementation of Crank4j, which derived from Cranker. the follow introduction is quoted from t

null 123 Jul 9, 2021
Standalone client for proxies of Opera VPN

opera-proxy Standalone Opera VPN client. Younger brother of hola-proxy. Just run it and it'll start a plain HTTP proxy server forwarding traffic throu

null 199 Jul 18, 2021
Open Source HTTP Reverse Proxy Cache and Time Series Dashboard Accelerator

Trickster is an HTTP reverse proxy/cache for http applications and a dashboard query accelerator for time series databases. Learn more below, and chec

null 1.5k Jul 27, 2021
HTTP(S)/WS(S)/TCP Tunnels to localhost using only SSH.

An open source serveo/ngrok alternative.

Antonio Mika 1.9k Jul 23, 2021
The fastest way to create self-hosted exit-servers

inletsctl - the fastest way to create self-hosted exit-servers inletsctl automates the task of creating an exit-server (tunnel server) on public cloud

inlets 349 Jul 21, 2021
Notion Official API Go Client.

go-notion Go SDK for Notion Official API. go get github.com/sorcererxw/go-notion Overview Getting Started Pagination Error Handling Reverse Proxy OAut

QianyuPan 14 Jul 22, 2021