Ejemplo n.º 1
0
// Run runs the the tunnel session
func (s *Session) Run() (err error) {
	defer s.recoverPanic("Session.Run")

	go func() {
		defer s.recoverPanic("Session.mux.Wait")
		code, err, debug := s.mux.Wait()
		s.Info("Session mux shutdown with code %v error %v debug %v", code, err, debug)
	}()

	defer s.mux.Close()

	// A tunnel session starts with an auth stream
	if err = s.handleAuth(); err != nil {
		return
	}

	// then we handle new streams sent from the client
	for {
		stream, err := s.mux.Accept()
		if err != nil {
			s.Shutdown()
			return s.Error("Failed to accept stream: %v", err)
		}

		go s.handleStream(conn.Wrap(stream, "stream", s.id))
	}
}
Ejemplo n.º 2
0
// Accept returns the next stream initiated by the server over the underlying muxado session
func (s *RawSession) Accept() (conn.Conn, error) {
	raw, err := s.mux.Accept()
	if err != nil {
		return nil, err
	}

	return conn.Wrap(raw, "proxy", s.id), nil
}
Ejemplo n.º 3
0
func (s *Session) handleAuth() error {
	// accept ann auth stream
	raw, err := s.mux.Accept()
	if err != nil {
		return s.Error("Failed to accept auth stream: %v", err)
	}
	defer raw.Close()

	stream := conn.Wrap(raw, "session", "auth")

	// read the Auth message
	if err = proto.ReadMsgInto(stream, &s.auth); err != nil {
		return s.Error("Failed to read auth message; %v", err)
	}

	failAuth := func(e error) error {
		_ = proto.WriteMsg(stream, &proto.AuthResp{Error: e.Error()})
		return e
	}

	// generate a client identifier
	s.id = s.auth.ClientId
	if s.id == "" {
		// it's a new session, assign an ID
		if s.id, err = util.SecureRandId(16); err != nil {
			return failAuth(fmt.Errorf("Failed generate client identifier: %v", err))
		}
	}

	// put ourselves in the registry
	s.registry.register(s)

	// set logging prefix
	s.Logger.AddTags(s.id)

	// agree on protocol version
	// if proto.Version not in s.auth.Version
	if sort.SearchStrings(s.auth.Version, proto.Version) == len(s.auth.Version) {
		return failAuth(fmt.Errorf("No acceptable protocol version. Requested: %v, capable: %v", s.auth.Version, proto.Version))
	}

	// auth hook
	if err = s.hooks.OnAuth(s, s.auth); err != nil {
		return failAuth(err)
	}

	// Respond to authentication
	authResp := &proto.AuthResp{
		Version:  proto.Version,
		ClientId: s.id,
	}

	if err = proto.WriteMsg(stream, authResp); err != nil {
		return failAuth(fmt.Errorf("Failed to write authentication response: %v", err))
	}

	return nil
}
Ejemplo n.º 4
0
// Listens for new public connections from the internet.
func (t *Tunnel) listen(listener net.Listener) {
	defer t.recoverPanic("Tunnel.listen")

	t.Info("Listening for connections on %s", listener.Addr())
	for {
		// accept public connections
		publicConn, err := listener.Accept()

		if err != nil {
			// not an error, we're shutting down this tunnel
			if atomic.LoadInt32(&t.closing) == 1 {
				return
			}

			t.Error("Failed to accept new connection: %v", err)
			continue
		}

		go t.handlePublic(conn.Wrap(publicConn, t.url))
	}
}
Ejemplo n.º 5
0
// Opens a new proxy stream to the client and writes a StartProxy message
// with the given client address and tunnel url.
func (s *Session) openProxy(clientAddr, tunnelUrl string) (pxy conn.Conn, err error) {
	// open a new proxy stream
	pxyStream, err := s.mux.Open()
	if err != nil {
		return
	}
	pxy = conn.Wrap(pxyStream)

	// tell the client we're going to start using this proxy connection
	startProxy := &proto.StartProxy{
		ClientAddr: clientAddr,
		Url:        tunnelUrl,
	}

	if err = proto.WriteMsg(pxy, startProxy); err != nil {
		return
	}

	pxy.AddTags(tunnelUrl)
	return
}
Ejemplo n.º 6
0
func (s *RawSession) req(tag string, req interface{}, resp interface{}) (err error) {
	stream, err := s.mux.Open()
	if err != nil {
		return
	}
	defer stream.Close()

	// log what happens on the stream
	c := conn.Wrap(stream, tag, s.id)

	// send the unlisten request
	if err = proto.WriteMsg(c, req); err != nil {
		return
	}

	// read out the unlisten response
	if err = proto.ReadMsgInto(c, resp); err != nil {
		return
	}

	return
}