Пример #1
0
//AddSSHBundles hands a default bundle to the supplied director
func AddSSHBundles(x ProxyDirector, sv SSHStreamer, serv *SSHStreamServer, check bool) error {

	if serv == nil {
		return ErrBadBundle
	}

	if sv == nil {
		return ErrBadBundle
	}

	x.Register("ssh", func(req *ProxyRequest, d *Director, a Action) error {

		var err error
		var cert *tls.Config

		if req.CertFile != "" && req.KeyFile != "" {
			cert, err = LoadTLS(req.CertFile, req.KeyFile)

			if err != nil {
				return err
			}
		}

		return x.ServeCustomTCP(req.From, cert, func(con net.Conn, d Directors) error {

			addr := net.JoinHostPort(req.Addr, fmt.Sprintf("%d", req.Port))
			// addr := net.JoinHostPort(req.Addr, string(req.Port))

			sl, cl, err := serv.StreamConnection(con, addr, nil)

			flux.Report(err, fmt.Sprintf("Initiated ssh authentication Scheme for %s and %s", con.RemoteAddr().String(), addr))

			if err != nil {
				return err
			}

			cn, err := sv.Stream(sl, cl)

			flux.Report(err, fmt.Sprintf("Initiated ssh proxy Scheme for %s -> %s", con.RemoteAddr().String(), addr))

			if err != nil {
				return err
			}

			a(cn)
			return nil
		}, check)
	})

	return nil
}
Пример #2
0
//DialClient returns two channels where one returns a ssh.Client and the other and error
func DialClient(dial, expire time.Duration, ip string, conf *ssh.ClientConfig, retry <-chan struct{}) (*ssh.Client, error) {

	flux.Report(nil, fmt.Sprintf("MakeDial for %s for dailing at %+s and expiring in %+s", conf.User, dial, expire))

	cons := make(chan *ssh.Client)
	errs := make(chan error)

	var con net.Conn
	var sc ssh.Conn
	var chans <-chan ssh.NewChannel
	var req <-chan *ssh.Request
	var err error

	flux.GoDefer("MakeDial", func() {
		con, err = net.DialTimeout("tcp", ip, dial)

		if err != nil {
			flux.Report(err, fmt.Sprintf("MakeDial:Before for %s net.DailTimeout", ip))
			errs <- err
			return
		}

		sc, chans, req, err = ssh.NewClientConn(con, ip, conf)

		if err != nil {
			flux.Report(err, fmt.Sprintf("MakeDial:After for %s ssh.NewClientConn", ip))
			errs <- err
			return
		}

		flux.Report(nil, fmt.Sprintf("MakeDial initiating NewClient for %s", ip))
		cons <- ssh.NewClient(sc, chans, req)
		return
	})

	expiration := threshold(expire)

	go func() {
		for _ = range retry {
			expiration = threshold(expire)
		}
	}()

	select {
	case err := <-errs:
		flux.Report(err, fmt.Sprintf("NewClient Ending!"))
		return nil, err
	case som := <-cons:
		flux.Report(nil, fmt.Sprintf("NewClient Created!"))
		expiration = nil
		return som, nil
	case <-expiration:
		flux.Report(nil, fmt.Sprintf("MakeDial Expired for %s!", ip))
		defer con.Close()
		if sc != nil {
			sc.Close()
		}
		return nil, ErrTimeout
	}
}
Пример #3
0
//StreamWithConn handles streaming two http conns
func (h *TCP) StreamWithConn(src net.Conn, addr string, conf *tls.Config) (*ConnInsight, error) {
	rsrc := NewStreamConn(src)

	var rdest *StreamConn
	var err error

	if conf == nil {
		rdest, err = NewNetConn(addr)
	} else {
		rdest, err = NewTLSConn(addr, conf)
	}

	if err != nil {
		flux.Report(err, fmt.Sprintf("StreamWithConn Unable to Create Request for %s!", src.RemoteAddr()))
		return nil, err
	}

	return h.Stream(rsrc, rdest)
}
Пример #4
0
//handleOperations manages the operations and behaviours of the connserver
func (c *ConnServe) handleOperations() {
	var killsig int64

	flux.GoDefer(fmt.Sprintf("%s:ConnectionCycleManager", c.ID), func() {
		flux.Report(nil, fmt.Sprintf("ConnServe:Listener Connection Cycle Management Started for %s", c.ID))
		defer flux.Report(nil, fmt.Sprintf("ConnServe:Listener Closed for %s!", c.ID))

		func() {
			log.Info("ConnServer checking HealthCheck Status: %t For: %s", c.checkable, c.ID)
		connloop:
			defer func() {
				defer flux.Report(nil, fmt.Sprintf("ConnServe:Listener Setting Kill Singal for %s!", c.ID))
				atomic.StoreInt64(&killsig, 1)
			}()
			for {
				select {
				case <-c.director.HealthNotify():
					log.Info("ConnServer checking HealthCheck Status: %t For: %s", c.checkable, c.ID)
					if c.checkable {
						age := c.director.MaxAge()
						idle := time.Duration(c.idle.Unix())
						if idle > age {
							break connloop
						}
					}
				case <-c.closer:
					flux.Report(nil, fmt.Sprintf("ConnServe:Listener User Closing Operation for %s", c.ID))
					break connloop
				case <-c.director.CloseNotify():
					flux.Report(nil, fmt.Sprintf("ConnServe:Listener Director Closing Operation for %s", c.ID))
					break connloop
				}
			}

		}()
	})

	flux.GoDefer(fmt.Sprintf("%s:AcceptCycleHandler", c.ID), func() {
		flux.Report(nil, fmt.Sprintf("ConnServe:Listener Accept Cycle Started for %s", c.ID))
		for {

			if killsig > 0 {
				break
			}

			defer flux.Report(nil, fmt.Sprintf("ConnServe:Listener Finished Handling Accept for %s", c.ID))
			con, err := c.listener.Accept()

			flux.Report(err, fmt.Sprintf("ConnServe:Listener Operation Processing for %s", c.ID))
			if err != nil {
				flux.GoDefer("ReportError", func() {
					errs, ok := c.director.Errors()
					if !ok {
						errs <- err
					}
				})
				return
			}

			c.idle = time.Now()

			//send the process in to a goroutine,lets not block
			flux.GoDefer("Handling net.Conn from ConnServe", func() {
				c.director.Requests().Emit(con)
				c.director.Wait()
				err := c.target(con, c.director)
				flux.Report(err, fmt.Sprintf("Received On Request for %s by %s", con.RemoteAddr().String(), c.ID))
				if err != nil {
					fmt.Fprint(con, EOFV)
					flux.Report(con.Close(), fmt.Sprintf("Closing ConnServe Request for %s by %s", con.RemoteAddr().String(), c.ID))
					flux.GoDefer("ReportError", func() {
						errs, ok := c.director.Errors()
						if !ok {
							errs <- err
						}
					})
				}
			})

		}
	})
}
Пример #5
0
//AddHTTPSpecialBundles hands a default bundle to the supplied director
func AddHTTPSpecialBundles(x ProxyDirector, stream HTTPStreamer, controls *xnet.Control, check bool, each xnet.EachControl, report *flux.StackReport) error {

	if stream == nil {
		return ErrBadBundle
	}

	if controls == nil {
		return ErrBadBundle
	}

	x.Register("chttp", func(req *ProxyRequest, d *Director, a Action) error {

		var err error
		var cert *tls.Config

		if req.CertFile != "" && req.KeyFile != "" {
			cert, err = LoadTLS(req.CertFile, req.KeyFile)

			if err != nil {
				return err
			}
		}

		ls, err := xnet.ListenTCP("tcp", req.From, cert, controls, each, report)

		if err != nil {
			return err
		}

		return x.ServeCustom(ls, func(con net.Conn, d Directors) error {

			xcon, ok := con.(*xnet.XConn)

			flux.Report(nil, fmt.Sprintf("Retrieving HTTP XConn from net.Conn for IP  %s -> %t", con.RemoteAddr().String(), ok))

			if !ok {
				return xnet.ErrBadXConn
			}

			ip, err := xcon.Container().IP()

			flux.Report(err, fmt.Sprintf("Retrieving Container IP from HTTP XConn for %s -> %s", con.RemoteAddr().String(), ip))

			if err != nil {
				return err
			}

			req.Addr = ip
			addr := net.JoinHostPort(ip, fmt.Sprintf("%d", req.Port))
			// addr := net.JoinHostPort(ip, string(req.Port))

			cn, err := stream.StreamWithConn(xcon, addr, cert)

			flux.Report(err, fmt.Sprintf("Initiated HTTP tcp container proxy Scheme for %s -> %s", con.RemoteAddr().String(), addr))

			if err != nil {
				return err
			}

			rip, _, _ := net.SplitHostPort(ip)
			cn.Meta["container_ip"] = ip
			cn.Meta["remote_ip"] = rip
			cn.Meta["local_ip"] = con.LocalAddr().String()
			cn.Meta["name"] = xcon.Container().Name()
			cn.Meta["port"] = fmt.Sprintf("%d", req.Port)

			a(cn)
			return nil
		}, check)
	})

	return nil
}
Пример #6
0
//AddSSHSpecialBundles hands a default bundle to the supplied director
func AddSSHSpecialBundles(x ProxyDirector, sv SSHStreamer, serv *SSHStreamServer, controls *xnet.Control, check bool, each xnet.EachControl) error {

	if serv == nil {
		return ErrBadBundle
	}

	if sv == nil {
		return ErrBadBundle
	}

	if controls == nil {
		return ErrBadBundle
	}

	x.Register("cssh", func(req *ProxyRequest, d *Director, a Action) error {

		var err error
		var cert *tls.Config

		if req.CertFile != "" && req.KeyFile != "" {
			cert, err = LoadTLS(req.CertFile, req.KeyFile)

			if err != nil {
				return err
			}
		}

		rq, _ := serv.Reports()
		ls, err := xnet.ListenTCP("tcp", req.From, cert, controls, each, rq)

		if err != nil {
			return err
		}

		return x.ServeCustom(ls, func(con net.Conn, d Directors) error {

			xcon, ok := con.(*xnet.XConn)

			flux.Report(nil, fmt.Sprintf("Retrieving XConn from net.Conn for IP  %s -> %t", con.RemoteAddr().String(), ok))

			if !ok {
				return xnet.ErrBadXConn
			}

			ip, err := xcon.Container().IP()

			flux.Report(err, fmt.Sprintf("Retrieving Container IP from XConn for %s -> %s", con.RemoteAddr().String(), ip))

			if err != nil {
				return err
			}

			req.Addr = ip
			addr := net.JoinHostPort(ip, fmt.Sprintf("%d", req.Port))
			// addr := net.JoinHostPort(ip, string(req.Port))

			sl, cl, err := serv.StreamConnection(xcon, addr, nil)

			flux.Report(err, fmt.Sprintf("Initiated ssh authentication Scheme for %s and %s", con.RemoteAddr().String(), addr))

			if err != nil {
				return err
			}

			cn, err := sv.Stream(sl, cl)

			flux.Report(err, fmt.Sprintf("Initiated ssh proxy Scheme for %s -> %s", con.RemoteAddr().String(), addr))

			if err != nil {
				return err
			}

			rip, _, _ := net.SplitHostPort(cl.Client.Meta.RemoteAddr().String())

			cn.Meta["cip"] = ip
			cn.Meta["rip"] = rip
			cn.Meta["name"] = xcon.Container().Name()
			cn.Meta["port"] = fmt.Sprintf("%d", req.Port)
			cn.Meta["pass"] = string(cl.Client.Pass)
			cn.Meta["user"] = cl.Client.Meta.User()

			a(cn)
			cn.open.Emit(true)
			return nil
		}, check)
	})

	return nil
}
Пример #7
0
//AddTCPBundles hands a default bundle to the supplied director
func AddTCPBundles(x ProxyDirector, stream TCPStreamer, check bool) {

	x.Register("tcp", func(req *ProxyRequest, d *Director, a Action) error {

		var err error
		var cert *tls.Config

		if req.CertFile != "" && req.KeyFile != "" {
			cert, err = LoadTLS(req.CertFile, req.KeyFile)

			if err != nil {
				return err
			}
		}

		to := net.JoinHostPort(req.Addr, fmt.Sprintf("%d", req.Port))
		return TCPProvider(x, stream, a, req.From, to, cert, check)
	})

	x.Register("xtcp", func(req *ProxyRequest, d *Director, a Action) error {

		var err error
		var cert *tls.Config

		if req.CertFile != "" && req.KeyFile != "" {
			cert, err = LoadTLS(req.CertFile, req.KeyFile)

			if err != nil {
				return err
			}
		}

		log.Info("XTcp Will set up custom Addr to %s", req.From)
		return x.ServeCustomTCP(req.From, cert, func(con net.Conn, dir Directors) error {

			var c *ConnInsight
			var err error

			ip, _, _ := net.SplitHostPort(con.RemoteAddr().String())

			log.Info("XTCP using IP:%s to Port: %d", ip, req.Port)
			addr := net.JoinHostPort(ip, fmt.Sprintf("%d", req.Port))
			log.Info("XTCP using new endpoint Addr: %d", addr)

			req.Addr = ip
			log.Info("XTCP Done setting IP Addr: %d", addr)

			// flux.GoDefer("StreamWithConn.XTcp", func() {
			log.Info("XTCP Begin streaming using tcp.StreamWithConn IP Addr: %d", addr)
			c, err = stream.StreamWithConn(con, addr, cert)
			log.Info("XTCP Done streaming using tcp.StreamWithConn IP Addr: %d", addr)

			if err != nil {
				flux.Report(err, fmt.Sprintf("XTcp XConn Closing Connection for %s", ip))
				flux.Report(con.Close(), fmt.Sprintf("XTcp XConn Closing Connection for %s", ip))
				return err
			}
			// })

			a(c)
			return nil
		}, check)
	})
}
Пример #8
0
//ServeHTTPWith provides a different approach,instead of using the base net.Conn ,itself uses the http.Request and http.Response as means of proxying using the director
func ServeHTTPWith(t TargetReqResOp, addr string, d Directors, conf *tls.Config, check bool) (*HTTPServe, error) {
	var hs *http.Server
	var ls net.Listener
	var err error

	handler := http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
		defer flux.Report(err, fmt.Sprintf("Request Processor Completed!"))
		flux.GoDefer("HttpServer", func() {
			d.Requests().Emit(true)
			flux.Report(err, fmt.Sprintf("Request Process Begin!"))
			// d.Wait()
			err := t(res, req, d)
			flux.Report(err, fmt.Sprintf("Request Processed Finished!"))
			if err != nil {
				res.WriteHeader(404)
				res.Write([]byte(err.Error()))
				flux.GoDefer("ReportError", func() {
					eos, ok := d.Errors()
					if ok {
						eos <- err
					}
				})
			}
		})
	})

	if conf != nil {
		hs, ls, err = CreateTLS(addr, conf, handler)
	} else {
		hs, ls, err = CreateHTTP(addr, handler)
	}

	flux.Report(err, fmt.Sprintf("HttpServe Listener Processor!"))
	if err != nil {
		return nil, err
	}

	hps := &HTTPServe{
		listener: ls,
		server:   hs,
		director: d,
		idle:     time.Now(),
		closer:   make(Notifier),
	}

	go func() {
		defer ls.Close()
		flux.Report(nil, fmt.Sprintf("HttpServer HealthCheck Status %t", check))
	nloop:
		for {
			select {
			case <-d.HealthNotify():
				flux.Report(nil, fmt.Sprintf("HttpServer checking HealthCheck status %t", check))
				if check {
					age := hps.director.MaxAge()
					idle := time.Duration(hps.idle.Unix())
					if idle > age {
						break nloop
					}
				}
			case <-hps.closer:
				break nloop
			}
		}
	}()

	return hps, nil
}