Giter Club home page Giter Club logo

tunnel's Introduction

Tunnel GoDoc Go Report Card Build Status

Tunnel is a server/client package that enables to proxy public connections to your local machine over a tunnel connection from the local machine to the public server. What this means is, you can share your localhost even if it doesn't have a Public IP or if it's not reachable from outside.

It uses the excellent yamux package to multiplex connections between server and client.

The project is under active development, please vendor it if you want to use it.

Usage

The tunnel package consists of two parts. The server and the client.

Server is the public facing part. It's type that satisfies the http.Handler. So it's easily pluggable into existing servers.

Let assume that you setup your DNS service so all *.example.com domains route to your server at the public IP 203.0.113.0. Let us first create the server part:

package main

import (
	"net/http"

	"github.com/koding/tunnel"
)

func main() {
	cfg := &tunnel.ServerConfig{}
	server, _ := tunnel.NewServer(cfg)
	server.AddHost("sub.example.com", "1234")
	http.ListenAndServe(":80", server)
}

Once you create the server, you just plug it into your server. The only detail here is to map a virtualhost to a secret token. The secret token is the only part that needs to be known for the client side.

Let us now create the client side part:

package main

import "github.com/koding/tunnel"

func main() {
	cfg := &tunnel.ClientConfig{
		Identifier: "1234",
		ServerAddr: "203.0.113.0:80",
	}

	client, err := tunnel.NewClient(cfg)
	if err != nil {
		panic(err)
	}

	client.Start()
}

The Start() method is by default blocking. As you see you, we just passed the server address and the secret token.

Now whenever someone hit sub.example.com, the request will be proxied to the machine where client is running and hit the local server running 127.0.0.1:80 (assuming there is one). If someone hits sub.example.com:3000 (assume your server is running at this port), it'll be routed to 127.0.0.1:3000

That's it.

There are many options that can be changed, such as a static local address for your client. Have alook at the documentation

Protocol

The server/client protocol is written in the spec.md file. Please have a look for more detail.

License

The BSD 3-Clause License - see LICENSE for more details

tunnel's People

Contributors

cihangir avatar fatih avatar flibustenet avatar mmatczuk avatar rjeczalik avatar sent-hil avatar victorsnow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tunnel's Issues

Example of new api

Hi guys,

first, thanks for this project - it solves a very practical problem for me: exposing an Android app (Wireless mic) so I can "listen" to my house from work!
(Using a computer at home - but could be a RPI in the future...)

So, my " setup" works with the exact example, and a single new config line:

	cfg := &tunnel.ClientConfig{
		Identifier: "1234",
		ServerAddr: "hugows.com:9999",
		LocalAddr:  "192.168.0.21:8081",
	}

Since you say in the docs that:

// LocalAddr is DEPRECATED please use ProxyHTTP.LocalAddr, see ProxyOverwrite for more details.
LocalAddr string

Could you provide an example of how to achieve the same thing with Proxy (I couldn't find the exact symbols) since it seems to be the proper way now.

tunnel server error: status=404, body=404 page not found

client log

2020-07-19 22:02:49 [tunnel-client] DEBUG    Trying to connect to "117.50.99.221:80" with identifier "123456789"
2020-07-19 22:02:49 [tunnel-client] DEBUG    CONNECT to "http://117.50.99.221:80/_controlPath/"
2020-07-19 22:02:49 [tunnel-client] DEBUG    Writing request to TCP: &{Method:CONNECT URL:http://117.50.99.221:80/_controlPath/ Proto:HTTP/1.1 ProtoMajor:1 ProtoMinor:1 Header:map[X-Ktunnel-Identifier:[123456789]] Body:<nil> GetBody:<nil> ContentLength:0 TransferEncoding:[] Close:false Host:117.50.99.221:80 Form:map[] PostForm:map[] MultipartForm:<nil> Trailer:map[] RemoteAddr: RequestURI: TLS:<nil> Cancel:<nil> Response:<nil> ctx:0xc0000ae010}
2020-07-19 22:02:49 [tunnel-client] DEBUG    Reading response from TCP
2020-07-19 22:02:49 [tunnel-client] DEBUG    client connect error: tunnel server error: status=404, body=404 page not found

on server, 80 port is listenning

sudo lsof -i :80
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
main    16252 root    3u  IPv6 345290      0t0  TCP *:http (LISTEN)
main    16252 root    4u  IPv6 345293      0t0  TCP 10-9-158-214:http->183.17.59.5:10355 (ESTABLISHED)
main    16252 root    8u  IPv6 345295      0t0  TCP 10-9-158-214:http->183.17.59.5:10661 (ESTABLISHED)
main    16252 root    9u  IPv6 345300      0t0  TCP 10-9-158-214:http->183.17.59.5:10673 (ESTABLISHED)
main    16252 root   10u  IPv6 345305      0t0  TCP 10-9-158-214:http->183.17.59.5:8397 (ESTABLISHED)
main    16252 root   11u  IPv6 345313      0t0  TCP 10-9-158-214:http->183.17.59.5:10197 (ESTABLISHED)
main    16252 root   12u  IPv6 345338      0t0  TCP 10-9-158-214:http->183.17.59.5:10218 (ESTABLISHED)
main    16252 root   13u  IPv6 345369      0t0  TCP 10-9-158-214:http->183.17.59.5:9558 (ESTABLISHED)
main    16252 root   14u  IPv6 345411      0t0  TCP 10-9-158-214:http->183.17.59.5:9483 (ESTABLISHED)
main    16252 root   15u  IPv6 345837      0t0  TCP 10-9-158-214:http->183.17.59.5:11937 (ESTABLISHED)
main    16252 root   16u  IPv6 345943      0t0  TCP 10-9-158-214:http->183.17.59.5:8659 (ESTABLISHED)
main    16252 root   17u  IPv6 346148      0t0  TCP 10-9-158-214:http->183.17.59.5:8249 (ESTABLISHED)
main    16252 root   18u  IPv6 346370      0t0  TCP 10-9-158-214:http->183.17.59.5:9753 (ESTABLISHED)
sudo lsof -i :80
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
main    16252 root    3u  IPv6 345290      0t0  TCP *:http (LISTEN)
main    16252 root    4u  IPv6 345293      0t0  TCP 10-9-158-214:http->183.17.59.5:10355 (ESTABLISHED)
main    16252 root    8u  IPv6 345295      0t0  TCP 10-9-158-214:http->183.17.59.5:10661 (ESTABLISHED)
main    16252 root    9u  IPv6 345300      0t0  TCP 10-9-158-214:http->183.17.59.5:10673 (ESTABLISHED)
main    16252 root   10u  IPv6 345305      0t0  TCP 10-9-158-214:http->183.17.59.5:8397 (ESTABLISHED)
main    16252 root   11u  IPv6 345313      0t0  TCP 10-9-158-214:http->183.17.59.5:10197 (ESTABLISHED)
main    16252 root   12u  IPv6 345338      0t0  TCP 10-9-158-214:http->183.17.59.5:10218 (ESTABLISHED)
main    16252 root   13u  IPv6 345369      0t0  TCP 10-9-158-214:http->183.17.59.5:9558 (ESTABLISHED)
main    16252 root   14u  IPv6 345411      0t0  TCP 10-9-158-214:http->183.17.59.5:9483 (ESTABLISHED)
main    16252 root   15u  IPv6 345837      0t0  TCP 10-9-158-214:http->183.17.59.5:11937 (ESTABLISHED)
main    16252 root   16u  IPv6 345943      0t0  TCP 10-9-158-214:http->183.17.59.5:8659 (ESTABLISHED)
main    16252 root   17u  IPv6 346148      0t0  TCP 10-9-158-214:http->183.17.59.5:8249 (ESTABLISHED)
main    16252 root   18u  IPv6 346370      0t0  TCP 10-9-158-214:http->183.17.59.5:9753 (ESTABLISHED)

but

curl localhost:80/_controlPath/
404 page not found

Simple question

Hello)

I have a problem.
I need a request that goes to sub.example.com:8080 to hit localhost:3000.
How should i config client for that?
Seems like ClientConfig.LocalAddr:":3000" does not help.

It does work locally. but i try to run it on appengine and always get no client session established error.

Thanks a lot)

Log filtering "no virtual host available"

https://github.com/koding/tunnel/blob/master/server.go#L161

if !strings.Contains(err.Error(), "no virtual host available") { // this one is outputted too much, unnecessarily
    s.log.Error("remote %s (%s): %s", r.RemoteAddr, r.RequestURI, err)
}

Such filtering could be moved to logging package for grater flexibility.

Also logging could have a filter that would print this log every 100 or so occurrences so that you can see when system is flooded with those logs.

Issues with http basic auth on the client side

Hi guys,

I think I arrived at an interesting problem - I wish I could understand it better.

Let me define the parts:

a. server.go: runs on hugows.com, a linux vps
b. client.go: runs on my windows pc, in home network, exposing the android app (192.168.0.10)
c. android: local client runs on my home network (w/ Wireless mic app) (192.168.0.20)
d. outsider: a browser connecting to hugows.com:9999

Now, this android application has HTTP Basic Auth. I see the following pattern, with both Go apps running:

  1. outsider open hugows.com:9999; http response seems to hang indefinitely
  2. if I kill client.go, finally it popups up asking for auth details. If I enter then I receive the expeced error from server.go (could not connect to client or something - client is not running now)
  3. If I run client.go again then:
  4. outsider can properly open the page!!!

Sorry I couldn't explain it better...

udp connections

Hey,

I'm in need of proxying udp ports (serf uses it for gossip protocol). Do you maybe support them?

Using as a transparent proxy

I'm trying to use this library as a transparent proxy that connects to a proxy in another server but keep receiving a 502 bad request. The connection arrives at the server but it is not routed to the identifier because it gets the identifier from the host.

I`m using curl for testing purposes just like this:

curl -v https://google.com -x identifier.server:port

The response is:

curl: (56) Received HTTP code 502 from proxy after CONNECT

Require port mapping to be explicit

If I don't specify LocalAddr in the client then I get this error

2015-05-31 11:20:46 [tunnel-client] DEBUG    Dialing local server 127.0.0.1:
2015-05-31 11:20:46 [tunnel-client] DEBUG    Dialing local server(127.0.0.1:) failed: dial tcp: unknown port tcp/

However, I think you should make the LocalAddr required to be explicit. Since this is explicitly "punching holes in network security", having it be simple and explicit feels much safer.

If developers need something more dynamic, you could make an API where the client gets to choose LocalAddr on a per-request basis.

Tunneling over HTTP/2

@rjeczalik I took your tip and did an experiment to replace yamux with HTTP/2. At first I wanted to make it a small change but it turned out that there were many incompatibilities so I decided to start fresh.

I did a POC that can proxy HTTP and TCP and uses ProxyFunc design (no default functions yet). It turns out that the implementation can be really short and concise with http2 package. Server is ~300LOC and client ~100LOC (mostly consumed by structs and comments). The code is available at https://github.com/mmatczuk/h2tun.

Performance using HTTP/2 is slightly better than using yamux but I think the key benefit is improved stability, you can see a report that I wrote https://github.com/mmatczuk/h2tun/blob/master/benchmark/report/README.md.

This implementation follows a similar design that the current tunnel, I'd like to highlight some changes here

  • There is no identifier sent by client, instead certificate pinning is used
  • ProxyFunc takes io.Writer and io.Reader instead of net.Conn
  • ControlMessage is changed, protocol is a string, it has extra fields, in general it follows some version of Forwarded HTTP Extension https://tools.ietf.org/html/rfc7239.

It's a POC, some things that exists in the tunnel should be migrated to make it truly usable. I also have some new ideas you can see in https://github.com/mmatczuk/h2tun/blob/master/TODO.md.

Please let me know what do you think.
I'd be really grateful for a review if find some time.

Cheers.

cc @cihangir

ignore steam EOF errors

We ignore io.EOF, yamux.EOF (or alike) should also be ignored.

2016-07-13T14:42:20.51Z  ERROR    [tunnelclient   ][PID:1905][logging/context.go:29] [transport] local to remote: copy error: stream closed

yamux: keepalive failed: session shutdown

Hi)

I wonder how to reconnect client if errors like:

yamux: keepalive failed: session shutdown
yamux: keepalive failed: i/o deadline reached

appears?

Thanks for help)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.