Exemple #1
0
// BuildOptions tries to detect whether tunnelled connection is needed
// and eventually sets up a tunnel configuration.
func (t *Tunnel) BuildOptions(opts *Options, registerURL *url.URL) error {
	t.buildOptions(opts)

	if t.opts.LastAddr != registerURL.Host {
		t.opts.Log.Info("tunnel: checking if %q is reachable", registerURL.Host)

		err := publicip.IsReachable(registerURL.Host)
		t.opts.Log.Debug("tunnel: reachability check %q: %s", registerURL.Host, err)

		t.opts.LastAddr = registerURL.Host
		t.opts.LastReachable = (err == nil)

		if err := t.db.SetOptions(t.opts); err != nil {
			t.opts.Log.Warning("tunnel: unable to update options: %s", err)
		}
	}

	clientOpts := t.clientOptions()

	if t.opts.LastReachable && !t.isVagrant {
		return nil
	}

	t.opts.Log.Debug("starting tunnel client")
	t.opts.Log.Debug("tunnel.Options=%+v", opts)
	t.opts.Log.Debug("tunnelproxy.ClientOptions=%+v", clientOpts)

	client, err := tunnelproxy.NewClient(clientOpts)
	if err != nil {
		return err
	}

	u := *registerURL
	u.Path = "/klient/kite"
	t.registerURL = &u
	t.client = client

	return nil
}
Exemple #2
0
func testTunnelserverHTTP(t *testing.T, serverURL *url.URL) {
	// Create and start local server. All requests to this server are tunneled.
	received := make(chan *http.Request, 32)
	localServer := Test.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		received <- r
		w.WriteHeader(204)
	}))

	// Create and start Tunnel Client. It takes care of forwarding requests
	// from the internet to the loceal server.
	var virtualHost string
	var wg sync.WaitGroup
	wg.Add(1)
	clientCfg, _ := Test.GenKiteConfig()
	k := kite.New("tunnelclient", "0.0.1")
	k.Config = clientCfg
	clientOpts := &tunnelproxy.ClientOptions{
		LastVirtualHost: serverURL.Host,
		LocalAddr:       host(localServer.URL),
		Kite:            k,
		OnRegister: func(req *tunnelproxy.RegisterResult) {
			virtualHost = req.VirtualHost
			wg.Done()
		},
		Log:     Test.Log.New("tunnelclient"),
		Debug:   true,
		Timeout: 1 * time.Minute,
	}

	client, err := tunnelproxy.NewClient(clientOpts)
	if err != nil {
		t.Fatalf("error creating tunnelproxy client: %s", err)
	}

	client.Start()
	defer client.Close()
	wg.Wait()

	if virtualHost == "" {
		t.Fatal("expected virtualHost to be non-empty")
	}

	cases := []struct {
		Method string
		URL    *url.URL
	}{{ // i=0
		Method: "GET",
		URL: &url.URL{
			Scheme: "http",
			Host:   serverURL.Host,
			Path:   "/",
		},
	}, { // i=1
		Method: "GET",
		URL: &url.URL{
			Scheme: "http",
			Host:   serverURL.Host,
			Path:   "/foo",
		},
	}, { // i=2
		Method: "DELETE",
		URL: &url.URL{
			Scheme: "http",
			Host:   serverURL.Host,
			Path:   "/foo/bar",
		},
	}, { // i=3
		Method: "POST",
		URL: &url.URL{
			Scheme: "http",
			Host:   serverURL.Host,
			Path:   "/" + utils.RandString(32),
		},
	}, { // i=4
		Method: "PUT",
		URL: &url.URL{
			Scheme: "http",
			Host:   serverURL.Host,
			Path:   "/" + utils.RandString(32),
		},
	}}

	// Send requests to public end of the tunnel.
	for i, cas := range cases {
		req, err := http.NewRequest(cas.Method, cas.URL.String(), nil)
		if err != nil {
			t.Fatalf("%d: error creating request to %s: %s", i, cas.URL, err)
		}
		req.Host = virtualHost
		_, err = http.DefaultClient.Do(req)
		if err != nil {
			t.Fatalf("%d: error sending request to %s: %s", i, cas.URL, err)
		}
	}

	timeout := time.After(1 * time.Minute)

	// Ensure all the requests were forwarded.
	for i, cas := range cases {
		select {
		case req := <-received:
			if req.Method != cas.Method {
				t.Errorf("%d: want Method=%q; got %q", i, cas.Method, req.Method)
			}
			if req.URL.Path != cas.URL.Path {
				t.Errorf("%d: want Path=%q; got %q", i, cas.URL.Path, req.URL.Path)
			}
		case <-timeout:
			t.Fatalf("receiving requests from %s timed out", localServer.URL)
		}
	}
}
Exemple #3
0
func testTunnelserverTCP(t *testing.T, serverURL *url.URL) {
	var (
		virtualHost string
		wg          sync.WaitGroup
		rec         = newServiceRecorder()
	)

	wg.Add(1)

	echo1, err := newEchoService()
	if err != nil {
		t.Fatalf("newEchoService()=%s", err)
	}
	defer echo1.Close()

	echo2, err := newEchoService()
	if err != nil {
		t.Fatalf("newEchoService()=%s", err)
	}
	defer echo1.Close()

	clientCfg, _ := Test.GenKiteConfig()
	k := kite.New("tunnelclient", "0.0.1")
	k.Config = clientCfg
	clientOpts := &tunnelproxy.ClientOptions{
		LastVirtualHost:    serverURL.Host,
		Kite:               k,
		OnRegisterServices: rec.Record,
		OnRegister: func(req *tunnelproxy.RegisterResult) {
			virtualHost = req.VirtualHost
			wg.Done()
		},
		Log:     Test.Log.New("tunnelclient"),
		Debug:   true,
		Timeout: 1 * time.Minute,
	}

	client, err := tunnelproxy.NewClient(clientOpts)
	if err != nil {
		t.Fatalf("error creating tunnelproxy client: %s", err)
	}

	client.Start()
	defer client.Close()
	wg.Wait()

	if virtualHost == "" {
		t.Fatal("expected virtualHost to be non-empty")
	}

	echo1service := &tunnelproxy.Service{
		Name:      "echo1",
		LocalAddr: echo1.Addr().String(),
	}

	if err := client.RegisterService(echo1service); err != nil {
		t.Fatalf("RegisterService(echo1)=%s", err)
	}

	echo2service := &tunnelproxy.Service{
		Name:      "echo2",
		LocalAddr: echo2.Addr().String(),
	}

	if err := client.RegisterService(echo2service); err != nil {
		t.Fatalf("RegisterService(echo2)=%s", err)
	}

	if err := rec.Wait("echo1", "echo2"); err != nil {
		t.Fatalf("Wait()=%s", err)
	}

	srv := rec.Services()
	rec.Clear()

	for _, service := range []string{"echo1", "echo2"} {
		client, err := dialTCP(srv[service].Port)
		if err != nil {
			t.Fatalf("%s: dialTCP()=%s", service, err)
		}

		for i := 0; i < 100; i++ {
			msg := fmt.Sprintf("hello_world_%d", i)
			client.out <- msg

			select {
			case <-time.After(tcpTimeout):
				t.Fatalf("%s(%d): timed out waiting for echo response to %q", service, i, msg)
			case resp := <-client.in:
				if resp != msg {
					t.Errorf("%s(%d): want %q, got %q", service, i, resp, msg)
				}
			}
		}

		client.Close()
	}

	// Close client to force disconnect. After connecting again, all TCP
	// services must be registered again.
	client.Close()
	wg.Add(1)
	client.Start()
	wg.Wait()

	if virtualHost == "" {
		t.Fatal("expected virtualHost to be non-empty")
	}

	if err := rec.Wait("echo1", "echo2"); err != nil {
		t.Fatalf("Wait()=%s", err)
	}
}