// handleProxy is the client side of the Tunnel (on public network).
181920
func (p *Proxy) handleProxy(session sockjs.Session, req *http.Request) {
	const ttl = time.Duration(1 * time.Hour)
	const leeway = time.Duration(1 * time.Minute)

	kiteID := req.URL.Query().Get("kiteID")

	client, ok := p.kites[kiteID]
	if !ok {
		p.Kite.Log.Error("Remote kite is not found: %s", req.URL.String())
		return
	}

	// TODO(rjeczalik): keep *rsa.PrivateKey in Proxy struct
	rsaPrivate, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(p.privKey))
	if err != nil {
		p.Kite.Log.Error("key pair encrypt error: %s", err)
		return
	}

	tunnel := client.newTunnel(session)
	defer tunnel.Close()

	claims := jwt.MapClaims{
		"sub": client.ID,                                    // kite ID
		"seq": tunnel.id,                                    // tunnel number
		"iat": time.Now().UTC().Unix(),                      // Issued At
		"exp": time.Now().UTC().Add(ttl).Add(leeway).Unix(), // Expiration Time
		"nbf": time.Now().UTC().Add(-leeway).Unix(),         // Not Before
	}

	signed, err := jwt.NewWithClaims(jwt.GetSigningMethod("RS256"), claims).SignedString(rsaPrivate)
	if err != nil {
		p.Kite.Log.Error("Cannot sign token: %s", err.Error())
		return
	}

	tunnelURL := *p.url
	tunnelURL.Path = "/tunnel" + strings.TrimPrefix(req.URL.Path, "/proxy")
	tunnelURL.RawQuery = "token=" + signed

	_, err = client.TellWithTimeout("kite.tunnel",
		4*time.Second, map[string]string{"url": tunnelURL.String()})
	if err != nil {
		p.Kite.Log.Error("Cannot open tunnel to the kite: %s err: %s", client.Kite, err.Error())
		return
	}

	select {
	case <-tunnel.StartNotify():
		<-tunnel.CloseNotify()
	case <-time.After(1 * time.Minute):
		p.Kite.Log.Error("timeout")
	}
}
470299
func (r *Request) SetProxy(proxy func(*http.Request) (*url.URL, error)) *Request {
	r.setting.Proxy = proxy
	return r
}
477562
func (p *Proxy) Handler() http.Handler {
	mux := goji.NewMux()

	mux.HandleFuncC(pat.Get("/healthcheck"), func(c context.Context, w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("ok\n"))
	})

	mux.Handle(pat.Post("/import"), handleProxy(p))

	mux.Handle(pat.Get("/debug/pprof/cmdline"), http.HandlerFunc(pprof.Cmdline))
	mux.Handle(pat.Get("/debug/pprof/profile"), http.HandlerFunc(pprof.Profile))
	mux.Handle(pat.Get("/debug/pprof/symbol"), http.HandlerFunc(pprof.Symbol))
	mux.Handle(pat.Get("/debug/pprof/trace"), http.HandlerFunc(pprof.Trace))
	// TODO match without trailing slash as well
	mux.Handle(pat.Get("/debug/pprof/*"), http.HandlerFunc(pprof.Index))

	return mux
}
168152
func (h *ProxyQueryHandler) handlePostQuery(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	var req query.ProxyRequest
	req.WithCompilerMappings(h.CompilerMappings)
	req.WithDialectMappings(h.DialectMappings)
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		EncodeError(ctx, err, w)
		return
	}

	hd, ok := req.Dialect.(HTTPDialect)
	if !ok {
		EncodeError(ctx, fmt.Errorf("unsupported dialect over HTTP %T", req.Dialect), w)
		return
	}
	hd.SetHeaders(w)

	n, err := h.ProxyQueryService.Query(ctx, w, &req)
	if err != nil {
		if n == 0 {
			// Only record the error headers IFF nothing has been written to w.
			EncodeError(ctx, err, w)
			return
		}
		h.Logger.Info("Error writing response to client",
			zap.String("handler", "transpilerde"),
			zap.Error(err),
		)
	}
}
1334252
func getProxyFunc(http_proxy string) func(*http.Request) (*url.URL, error) {
	if http_proxy == "" {
		return http.ProxyFromEnvironment
	}
	proxyURL, err := url.Parse(http_proxy)
	if err != nil {
		return func(_ *http.Request) (*url.URL, error) {
			return nil, errors.New("bad proxy: " + err.Error())
		}
	}
	return func(r *http.Request) (*url.URL, error) {
		return proxyURL, nil
	}
}
924527
func SetProxy(proxy func(*http.Request) (*url.URL, error)) error {
	return std.SetProxy(proxy)
}
1157467
func (s *PresenceService) DeleteProxy(name string) error {
	key := backend.Key(proxiesPrefix, name)
	return s.Delete(context.TODO(), key)
}
373830
func NewProxy(addr, trans string) *Proxy {
	p := &Proxy{
		addr:      addr,
		fails:     0,
		probe:     up.New(),
		transport: newTransport(addr),
	}
	p.health = NewHealthChecker(trans)
	runtime.SetFinalizer(p, (*Proxy).finalizer)
	return p
}
840114
func LocalProxy(proxy, local interface{}) error {
	dstValue := reflect.ValueOf(proxy)
	srcValue := reflect.ValueOf(local)
	if dstValue.Kind() != reflect.Ptr {
		return errors.New("proxy must be a pointer")
	}
	dstValue = dstValue.Elem()
	t := dstValue.Type()
	et := t
	if et.Kind() == reflect.Ptr {
		et = et.Elem()
	}
	if et.Kind() != reflect.Struct {
		return errors.New("proxy must be a struct pointer or pointer to a struct pointer")
	}
	ptr := reflect.New(et)
	obj := ptr.Elem()
	count := obj.NumField()
	for i := 0; i < count; i++ {
		f := obj.Field(i)
		ft := f.Type()
		sf := et.Field(i)
		if f.CanSet() && ft.Kind() == reflect.Func {
			f.Set(srcValue.MethodByName(sf.Name))
		}
	}
	if t.Kind() == reflect.Ptr {
		dstValue.Set(ptr)
	} else {
		dstValue.Set(obj)
	}
	return nil
}
294201
func (tc *TeleportClient) connectToProxy(ctx context.Context) (*ProxyClient, error) {
	var err error

	proxyPrincipal := tc.getProxySSHPrincipal()
	sshConfig := &ssh.ClientConfig{
		User:            proxyPrincipal,
		HostKeyCallback: tc.HostKeyCallback,
	}

	// helper to create a ProxyClient struct
	makeProxyClient := func(sshClient *ssh.Client, m ssh.AuthMethod) *ProxyClient {
		return &ProxyClient{
			teleportClient:  tc,
			Client:          sshClient,
			proxyAddress:    tc.Config.SSHProxyAddr,
			proxyPrincipal:  proxyPrincipal,
			hostKeyCallback: sshConfig.HostKeyCallback,
			authMethod:      m,
			hostLogin:       tc.Config.HostLogin,
			siteName:        tc.Config.SiteName,
			clientAddr:      tc.ClientAddr,
		}
	}
	successMsg := fmt.Sprintf("Successful auth with proxy %v", tc.Config.SSHProxyAddr)
	// try to authenticate using every non interactive auth method we have:
	for i, m := range tc.authMethods() {
		log.Infof("Connecting proxy=%v login='%v' method=%d", tc.Config.SSHProxyAddr, sshConfig.User, i)
		var sshClient *ssh.Client

		sshConfig.Auth = []ssh.AuthMethod{m}
		sshClient, err = ssh.Dial("tcp", tc.Config.SSHProxyAddr, sshConfig)
		if err != nil {
			return nil, trace.Wrap(err)
		}
		log.Infof(successMsg)
		return makeProxyClient(sshClient, m), nil
	}
	// we have exhausted all auth existing auth methods and local login
	// is disabled in configuration, or the user refused connecting to untrusted hosts
	if err == nil {
		err = trace.BadParameter("failed to authenticate with proxy %v", tc.Config.SSHProxyAddr)
	}
	return nil, trace.Wrap(err)
}
1154436
func (f FuncRespHandler) Handle(resp *http.Response, ctx *ProxyCtx) *http.Response {
	return f(resp, ctx)
}
140849
func (s *APIServer) deleteProxy(auth ClientI, w http.ResponseWriter, r *http.Request, p httprouter.Params, version string) (interface{}, error) {
	name := p.ByName("name")
	if name == "" {
		return nil, trace.BadParameter("missing proxy name")
	}
	err := auth.DeleteProxy(name)
	if err != nil {
		return nil, trace.Wrap(err)
	}
	return message("ok"), nil
}
1297829
func proxyTransport(p *transportParams) {
	defer p.channel.Close()

	// Always push space into stderr to make sure the caller can always
	// safely call read (stderr) without blocking. This stderr is only used
	// to request proxying of TCP/IP via reverse tunnel.
	fmt.Fprint(p.channel.Stderr(), " ")

	// Wait for a request to come in from the other side telling the server
	// where to dial to.
	var req *ssh.Request
	select {
	case <-p.closeContext.Done():
		return
	case req = <-p.requestCh:
		if req == nil {
			return
		}
	case <-time.After(defaults.DefaultDialTimeout):
		p.log.Warnf("Transport request failed: timed out waiting for request.")
		return
	}

	server := string(req.Payload)
	var servers []string

	// Handle special non-resolvable addresses first.
	switch server {
	// Connect to an Auth Server.
	case RemoteAuthServer:
		authServers, err := p.authClient.GetAuthServers()
		if err != nil {
			p.log.Errorf("Transport request failed: unable to get list of Auth Servers: %v.", err)
			req.Reply(false, []byte("connection rejected: failed to connect to auth server"))
			return
		}
		if len(authServers) == 0 {
			p.log.Errorf("Transport request failed: no auth servers found.")
			req.Reply(false, []byte("connection rejected: failed to connect to auth server"))
			return
		}
		for _, as := range authServers {
			servers = append(servers, as.GetAddr())
		}
	// Connect to the Kubernetes proxy.
	case RemoteKubeProxy:
		if p.component == teleport.ComponentReverseTunnelServer {
			req.Reply(false, []byte("connection rejected: no remote kubernetes proxy"))
			return
		}

		// If Kubernetes is not configured, reject the connection.
		if p.kubeDialAddr.IsEmpty() {
			req.Reply(false, []byte("connection rejected: configure kubernetes proxy for this cluster."))
			return
		}
		servers = append(servers, p.kubeDialAddr.Addr)
	// LocalNode requests are for the single server running in the agent pool.
	case LocalNode:
		if p.component == teleport.ComponentReverseTunnelServer {
			req.Reply(false, []byte("connection rejected: no local node"))
			return
		}
		if p.server == nil {
			req.Reply(false, []byte("connection rejected: server missing"))
			return
		}
		if p.sconn == nil {
			req.Reply(false, []byte("connection rejected: server connection missing"))
			return
		}

		req.Reply(true, []byte("Connected."))

		// Hand connection off to the SSH server.
		p.server.HandleConnection(utils.NewChConn(p.sconn, p.channel))
		return
	default:
		servers = append(servers, server)
	}

	p.log.Debugf("Received out-of-band proxy transport request: %v", servers)

	// Loop over all servers and try and connect to one of them.
	var err error
	var conn net.Conn
	for _, s := range servers {
		conn, err = net.Dial("tcp", s)
		if err == nil {
			break
		}

		// Log the reason the connection failed.
		p.log.Debugf(trace.DebugReport(err))
	}

	// If all net.Dial attempts failed, write the last connection error to stderr
	// of the caller (via SSH channel) so the error will be propagated all the
	// way back to the client (tsh or ssh).
	if err != nil {
		fmt.Fprint(p.channel.Stderr(), err.Error())
		req.Reply(false, []byte(err.Error()))
		return
	}

	// Dail was successful.
	req.Reply(true, []byte("Connected."))
	p.log.Debugf("Successfully dialed to %v, start proxying.", server)

	errorCh := make(chan error, 2)

	go func() {
		// Make sure that we close the client connection on a channel
		// close, otherwise the other goroutine would never know
		// as it will block on read from the connection.
		defer conn.Close()
		_, err := io.Copy(conn, p.channel)
		errorCh <- err
	}()

	go func() {
		_, err := io.Copy(p.channel, conn)
		errorCh <- err
	}()

	for i := 0; i < 2; i++ {
		select {
		case err := <-errorCh:
			if err != nil && err != io.EOF {
				p.log.Warnf("Proxy transport failed: %v %T.", trace.DebugReport(err), err)
			}
		case <-p.closeContext.Done():
			p.log.Warnf("Proxy transport failed: closing context.")
			return
		}
	}
}
519796
func (parser *Parser) FindProxy(url, host string) (string, error) {
	if parser.rt == nil {
		return "", errors.New("A proxy auto-config file has not been loaded")
	}

	return parser.rt.findProxyForURL(url, host)
}
1242374
func NewProxyWithOptions(router route.Router, o Options) (*Proxy, error) {
	o, err := validateOptions(o)
	if err != nil {
		return nil, err
	}

	p := &Proxy{
		options: o,
		router:  router,
	}
	return p, nil
}
357368
func (facade *Facade) Proxy() (params.SSHProxyResult, error) {
	if err := facade.checkIsModelAdmin(); err != nil {
		return params.SSHProxyResult{}, errors.Trace(err)
	}
	config, err := facade.backend.ModelConfig()
	if err != nil {
		return params.SSHProxyResult{}, err
	}
	return params.SSHProxyResult{UseProxy: config.ProxySSH()}, nil
}
983664
func (ctx *Context) Proxy(url string) (err error) {
	proxyReq := fasthttp.AcquireRequest()
	ctx.Request.CopyTo(proxyReq)
	proxyReq.SetRequestURI(url)

	err = fasthttp.Do(proxyReq, &ctx.Response)

	fasthttp.ReleaseRequest(proxyReq)
	return
}