proxylite

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2023 License: MIT Imports: 15 Imported by: 1

README

Go Reference Go Report Card codecov

English|中文

proxylite

proxylite is a dynamic TCP reverse proxy Golang package for NAT or firewall traversal. It is god damn easy to integrate network traversal feature into your project with proxylite.

Different from well-known frp, proxylite is not a set of runnable programs, but a lightweight package, which provides good flexibility and is easy to integrate in golang projects. Of course, build a set of runnable programs is also a piece of cake.

Why proxylite

One day, I needed to add TCP NAT traversal to my project, so I tried to introduce frp to implement this feature. But I realized that frp needs to read configuration files and start processes, which is not a good fit for my needs:

  • First of all, starting a process introduces a new independent service to the project, which makes it more difficult to maintain.
  • Also, this approach does not allow for easy collection of logging information.
  • Most importantly, I needed to dynamically establish on-demand connections, and editing the configuration file and then restarting the process was clearly inelegant.

So why not write a package to make this more elegant? proxylite was born. Its main features are listed below:

  1. Easy to integrate into code. Both server and client structures are provided. Just import this package then register tunnels whenever you want.
  2. Dynamic on-demand reverse proxy with serivce controlling (maxOnline, maxServe and deadline).
  3. Service discovery and status display.
  4. Customized hooks are support.

Concepts

  +---------------------------------+   +-----------------------------------+
  | Inner Service <--- Inner Client +---+> Listenning Port <--- Outer Port <+---- User 
  +---------------------------------+   +-----------------------------------+
               NAT Nodes             ...             Public Server               Any User

Quick Start

First, you should import proxylite:

import "github.com/piaodazhu/proxylite"

Let's create a server:

package main
import "github.com/piaodazhu/proxylite"

func main() {
    server := proxylite.NewProxyLiteServer()
    server.AddPort(9930, 9932)

    server.Run(":9933")
}

These code create a proxylite server, and add available outer port 9930-9932 (Note that it is not 9930 and 9932, but from 9930 to 9932), then run the server. The server is blocked listening on port 9939, inner client will dial this port and server discovery also bind this port.

Then, we create a inner client:

package main

import (
    "log"

    "github.com/piaodazhu/proxylite"
)

func main() {
    client := proxylite.NewProxyLiteClient("0.0.0.0:9933")
    err := client.RegisterInnerService(
        proxylite.RegisterInfo{
            OuterPort: 9931,     // map ssh service to serverIp:9931
            InnerAddr: ":22",
            Name:      "ssh",
            Message:   "ssh login",
        },
        proxylite.ControlInfo{
			MaxServeConn:  3,     // 3 users at the same time
			MaxServeCount: 1000,  // close after 1000 servings
			MaxServeTime:  600,   // close after 10min
		},
    )
    if err != nil {
        log.Fatal(err)
        return
    }

    entry, ok := client.GetRegisterEntryByName("ssh")
    if !ok {
        log.Fatal("registration failed")
        return
    }
    <-entry.Done
    log.Print("BYE :)")
}

These code create a inner client, binding with server "0.0.0.0:9933". Then we register a inner service to the server:

proxylite.RegisterInfo{
    OuterPort: 9931,    // means we want map server's 9931 port to our inner service 
    InnerAddr: ":22",   // means inner service is 127.0.0.1:22. e.g. default ssh port.
    Name:      "ssh",   // service name
    Message:   "ssh login", // customized information
},

Then we get the registration entry if the registration is success. Finally we wait it done by reading channel.

frplite

./frplite/frpc and ./frplite/frps are 2 executable programs like frps and frpc. They can be configured and run like frp but only support tcp.

Tutorial

Server

func NewProxyLiteServer(portIntervals ...[2]int) *ProxyLiteServer

Create a Proxy server with available ports intervals.

func (s *ProxyLiteServer) AddPort(from, to int) bool

Create a Proxy server with available ports intervals. Return false if port is invalid.

func (s *ProxyLiteServer) SetLogger(logger *log.Logger)

Set customized logrus logger the the server.

func (s *ProxyLiteServer) Run(addr string) error

Run the server and let it listen on given address.

client

func NewProxyLiteClient(serverAddr string) *ProxyLiteClient

Create a inner client binding with a proxy server.

func (c *ProxyLiteClient) AvailablePorts() ([]int, bool)

Get available ports from proxy server.

func (c *ProxyLiteClient) AnyPort() (int, bool)

Get a random available port from proxy server.

type ServiceInfo struct {
	Port    uint32
	Name    string
	Message string
	Birth   time.Time

	Online       uint32    // online user count
	Capacity     uint32    // max concurrency user count
	AlreadyServe uint32    // already served user number
	TotalServe   uint32    // total user number can serve
	DeadLine     time.Time // time to close this port
}

func (c *ProxyLiteClient) ActiveServices() ([]ServiceInfo, error)

Discover all active services from proxy server.

type RegisterInfo struct {
    OuterPort int
    InnerAddr string
    Name      string
    Message   string
}

type ControlInfo struct {
	MaxServeTime  uint32
	MaxServeConn  uint32
	MaxServeCount uint32
}

func (c *ProxyLiteClient) RegisterInnerService(info RegisterInfo, 
    ctrl ControlInfo) (func(), chan struct{}, error)

Register inner server to proxy server's outer port.

type RegisterEntry struct {
    // Basic Info
    Info   RegisterInfo
    // Cancel function
    Cancel func()
    // Done channel
    Done   <-chan struct{}
}

func (c *ProxyLiteClient) GetRegisterEntryByName(name string) (*RegisterEntry, bool) 
func (c *ProxyLiteClient) GetRegisterEntryByPort(port int) (*RegisterEntry, bool)

Get RegisterEntry by name or port. RegisterEntry can be used to canncel tunnel or wait done.

func (c *ProxyLiteClient) SetLogger(logger *log.Logger)

Set customized logrus logger for the inner client.

Others

func AskFreePort(addr string) ([]int, error)

Ask available free port from proxy server with given address.

func DiscoverServices(addr string) ([]ServiceInfo, error)

Discover all active services from proxy server with given address.

Contributing

Feel free to open issues or pull requests to make this project better. 🌈

Documentation

Overview

Package proxylite is a dynamic reverse proxy package for Go.

Index

Constants

View Source
const (
	TypeMsgUndefined = iota
	TypeMsgMalformed
	TypeAskFreePortReq
	TypeAskFreePortRsp
	TypeAskServiceReq
	TypeAskServiceRsp
	TypeRegisterServiceReq
	TypeRegisterServiceRsp

	TypeDataSegment = 64
)
View Source
const (
	RegisterRspOK = iota
	RegisterRspPortNotAllowed
	RegisterRspPortOccupied
	RegisterRspServerError
)

Variables

This section is empty.

Functions

func AskFreePort

func AskFreePort(addr string) ([]uint32, error)

AskFreePort Ask available free port from proxy server with given address.

func GenConnId added in v0.2.0

func GenConnId(conn *net.Conn) uint64

Types

type AskFreePortReq

type AskFreePortReq struct{}

AskFreePortReq Ask available free ports request

type AskFreePortRsp

type AskFreePortRsp struct {
	Ports []uint32
}

AskFreePortRsp Ask available free ports response

type AskServiceReq

type AskServiceReq struct {
	Prefix string
}

AskServiceReq Service discovery request

type AskServiceRsp

type AskServiceRsp struct {
	Services []ServiceInfo
}

AskServiceRsp Service discovery response

type Context added in v0.3.0

type Context struct {
	// contains filtered or unexported fields
}

func (*Context) AbortTunnel added in v0.3.0

func (ctx *Context) AbortTunnel() error

func (*Context) AbortUser added in v0.3.0

func (ctx *Context) AbortUser() error

func (*Context) DataBuffer added in v0.3.0

func (ctx *Context) DataBuffer() []byte

func (*Context) GetValue added in v0.3.0

func (ctx *Context) GetValue(key interface{}) (interface{}, bool)

func (*Context) InnerLocalConn added in v0.3.0

func (ctx *Context) InnerLocalConn() net.Addr

func (*Context) InnerRemoteConn added in v0.3.0

func (ctx *Context) InnerRemoteConn() net.Addr

func (*Context) PutValue added in v0.3.0

func (ctx *Context) PutValue(key, value interface{})

func (*Context) ServiceInfo added in v0.3.0

func (ctx *Context) ServiceInfo() ServiceInfo

func (*Context) UserLocalAddress added in v0.3.0

func (ctx *Context) UserLocalAddress() net.Addr

func (*Context) UserRemoteAddress added in v0.3.0

func (ctx *Context) UserRemoteAddress() net.Addr

type ControlInfo added in v0.2.0

type ControlInfo struct {
	MaxServeTime  uint32
	MaxServeConn  uint32
	MaxServeCount uint32
}

ControlInfo Register Controlling information

type HookFunc added in v0.3.0

type HookFunc func(ctx *Context)

func (HookFunc) Trigger added in v0.3.0

func (hf HookFunc) Trigger(ctx *Context)

type ProxyLiteClient

type ProxyLiteClient struct {
	// contains filtered or unexported fields
}

ProxyLiteClient inner client that forwards traffic between inner service and proxy server server.

func NewProxyLiteClient

func NewProxyLiteClient(serverAddr string) *ProxyLiteClient

NewProxyLiteClient Create a inner client binding with a proxy server.

func (*ProxyLiteClient) ActiveServices

func (c *ProxyLiteClient) ActiveServices() ([]ServiceInfo, error)

ActiveServices Discover all active services from proxy server.

func (*ProxyLiteClient) AnyPort

func (c *ProxyLiteClient) AnyPort() (uint32, bool)

AnyPort Get a random available port from proxy server.

func (*ProxyLiteClient) AvailablePorts added in v0.2.1

func (c *ProxyLiteClient) AvailablePorts() ([]uint32, bool)

availablePorts Get available ports from proxy server.

func (*ProxyLiteClient) GetRegisterEntryByName

func (c *ProxyLiteClient) GetRegisterEntryByName(name string) (*RegisterEntry, bool)

GetRegisterEntryByName Get RegisterEntry

func (*ProxyLiteClient) GetRegisterEntryByPort

func (c *ProxyLiteClient) GetRegisterEntryByPort(port int) (*RegisterEntry, bool)

GetRegisterEntryByPort Get RegisterEntry

func (*ProxyLiteClient) RegisterInnerService

func (c *ProxyLiteClient) RegisterInnerService(info RegisterInfo, ctrl ControlInfo) (func(), chan struct{}, error)

RegisterInnerService Register inner server to proxy server's outer port.

func (*ProxyLiteClient) SetLogger

func (c *ProxyLiteClient) SetLogger(logger *log.Logger)

SetLogger Set customized logrus logger for the inner client.

type ProxyLiteServer

type ProxyLiteServer struct {
	// contains filtered or unexported fields
}

ProxyLiteServer Public server that forwards traffic between user and inner client.

func NewProxyLiteServer

func NewProxyLiteServer(portIntervals ...[2]int) *ProxyLiteServer

NewProxyLiteServer Create a Proxy server with available ports intervals.

func (*ProxyLiteServer) AddPort

func (s *ProxyLiteServer) AddPort(from, to int) bool

AddPort Add available ports intervals for server. Return false if port is invalid.

func (*ProxyLiteServer) OnForwardTunnelToUser added in v0.3.0

func (s *ProxyLiteServer) OnForwardTunnelToUser(f HookFunc)

func (*ProxyLiteServer) OnForwardUserToTunnel added in v0.3.0

func (s *ProxyLiteServer) OnForwardUserToTunnel(f HookFunc)

func (*ProxyLiteServer) OnTunnelCreated added in v0.3.0

func (s *ProxyLiteServer) OnTunnelCreated(f HookFunc)

func (*ProxyLiteServer) OnTunnelDestroyed added in v0.3.0

func (s *ProxyLiteServer) OnTunnelDestroyed(f HookFunc)

func (*ProxyLiteServer) OnUserComming added in v0.3.0

func (s *ProxyLiteServer) OnUserComming(f HookFunc)

func (*ProxyLiteServer) OnUserLeaving added in v0.3.0

func (s *ProxyLiteServer) OnUserLeaving(f HookFunc)

func (*ProxyLiteServer) Run

func (s *ProxyLiteServer) Run(addr string) error

Run Run the server and let it listen on given address.

func (*ProxyLiteServer) SetLogger

func (s *ProxyLiteServer) SetLogger(logger *log.Logger)

SetLogger Set customized logrus logger for the server.

func (*ProxyLiteServer) Stop added in v0.3.0

func (s *ProxyLiteServer) Stop() error

Stop Stop the server

type RegisterEntry

type RegisterEntry struct {
	// Basic Info
	Info RegisterInfo
	// Control Info
	Ctrl ControlInfo
	// Cancel function
	Cancel func()
	// Done channel
	Done <-chan struct{}
}

RegisterEntry entry to describe a single service registration

type RegisterInfo

type RegisterInfo struct {
	OuterPort uint32
	InnerAddr string
	Name      string
	Message   string
}

RegisterInfo Register information

type RegisterServiceReq

type RegisterServiceReq struct {
	Info RegisterInfo
	Ctrl ControlInfo
}

RegisterServiceReq inner service registration request

type RegisterServiceRsp

type RegisterServiceRsp struct {
	Code int32
}

RegisterServiceRsp inner service registration response

type ServiceInfo

type ServiceInfo struct {
	Port    uint32
	Name    string
	Message string
	Birth   time.Time

	Online       uint32    // online user count
	Capacity     uint32    // max concurrency user count
	AlreadyServe uint32    // already served user number
	TotalServe   uint32    // total user number can serve
	DeadLine     time.Time // time to close this port
}

ServiceInfo Service basic information

func DiscoverServices

func DiscoverServices(addr string) ([]ServiceInfo, error)

DiscoverServices Discover all active services from proxy server with given address.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL