mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-06 07:37:21 +02:00

+ Added unset subdomain custom redirection feature #46 + Optimized memory usage by space time tradeoff in geoip lookup to fix #52 + Replaced all stori/go.uuid to google/uuid for security reasons #55
186 lines
4.5 KiB
Go
186 lines
4.5 KiB
Go
package tcpprox
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
|
|
"github.com/google/uuid"
|
|
"imuslab.com/zoraxy/mod/database"
|
|
)
|
|
|
|
/*
|
|
TCP Proxy
|
|
|
|
Forward port from one port to another
|
|
Also accept active connection and passive
|
|
connection
|
|
*/
|
|
|
|
const (
|
|
ProxyMode_Listen = 0
|
|
ProxyMode_Transport = 1
|
|
ProxyMode_Starter = 2
|
|
)
|
|
|
|
type ProxyRelayOptions struct {
|
|
Name string
|
|
PortA string
|
|
PortB string
|
|
Timeout int
|
|
Mode int
|
|
}
|
|
|
|
type ProxyRelayConfig struct {
|
|
UUID string //A UUIDv4 representing this config
|
|
Name string //Name of the config
|
|
Running bool //If the service is running
|
|
PortA string //Ports A (config depends on mode)
|
|
PortB string //Ports B (config depends on mode)
|
|
Mode int //Operation Mode
|
|
Timeout int //Timeout for connection in sec
|
|
stopChan chan bool //Stop channel to stop the listener
|
|
aTobAccumulatedByteTransfer int64 //Accumulated byte transfer from A to B
|
|
bToaAccumulatedByteTransfer int64 //Accumulated byte transfer from B to A
|
|
|
|
parent *Manager `json:"-"`
|
|
}
|
|
|
|
type Options struct {
|
|
Database *database.Database
|
|
DefaultTimeout int
|
|
AccessControlHandler func(net.Conn) bool
|
|
}
|
|
|
|
type Manager struct {
|
|
//Config and stores
|
|
Options *Options
|
|
Configs []*ProxyRelayConfig
|
|
|
|
//Realtime Statistics
|
|
Connections int //currently connected connect counts
|
|
}
|
|
|
|
func NewTCProxy(options *Options) *Manager {
|
|
options.Database.NewTable("tcprox")
|
|
|
|
//Load relay configs from db
|
|
previousRules := []*ProxyRelayConfig{}
|
|
if options.Database.KeyExists("tcprox", "rules") {
|
|
options.Database.Read("tcprox", "rules", &previousRules)
|
|
}
|
|
|
|
//Check if the AccessControlHandler is empty. If yes, set it to always allow access
|
|
if options.AccessControlHandler == nil {
|
|
options.AccessControlHandler = func(conn net.Conn) bool {
|
|
//Always allow access
|
|
return true
|
|
}
|
|
}
|
|
|
|
//Create a new proxy manager for TCP
|
|
thisManager := Manager{
|
|
Options: options,
|
|
Connections: 0,
|
|
}
|
|
|
|
//Inject manager into the rules
|
|
for _, rule := range previousRules {
|
|
rule.parent = &thisManager
|
|
}
|
|
|
|
thisManager.Configs = previousRules
|
|
|
|
return &thisManager
|
|
}
|
|
|
|
func (m *Manager) NewConfig(config *ProxyRelayOptions) string {
|
|
//Generate a new config from options
|
|
configUUID := uuid.New().String()
|
|
thisConfig := ProxyRelayConfig{
|
|
UUID: configUUID,
|
|
Name: config.Name,
|
|
Running: false,
|
|
PortA: config.PortA,
|
|
PortB: config.PortB,
|
|
Mode: config.Mode,
|
|
Timeout: config.Timeout,
|
|
stopChan: nil,
|
|
aTobAccumulatedByteTransfer: 0,
|
|
bToaAccumulatedByteTransfer: 0,
|
|
|
|
parent: m,
|
|
}
|
|
m.Configs = append(m.Configs, &thisConfig)
|
|
m.SaveConfigToDatabase()
|
|
return configUUID
|
|
}
|
|
|
|
func (m *Manager) GetConfigByUUID(configUUID string) (*ProxyRelayConfig, error) {
|
|
// Find and return the config with the specified UUID
|
|
for _, config := range m.Configs {
|
|
if config.UUID == configUUID {
|
|
return config, nil
|
|
}
|
|
}
|
|
return nil, errors.New("config not found")
|
|
}
|
|
|
|
// Edit the config based on config UUID, leave empty for unchange fields
|
|
func (m *Manager) EditConfig(configUUID string, newName string, newPortA string, newPortB string, newMode int, newTimeout int) error {
|
|
// Find the config with the specified UUID
|
|
foundConfig, err := m.GetConfigByUUID(configUUID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Validate and update the fields
|
|
if newName != "" {
|
|
foundConfig.Name = newName
|
|
}
|
|
if newPortA != "" {
|
|
foundConfig.PortA = newPortA
|
|
}
|
|
if newPortB != "" {
|
|
foundConfig.PortB = newPortB
|
|
}
|
|
if newMode != -1 {
|
|
if newMode > 2 || newMode < 0 {
|
|
return errors.New("invalid mode given")
|
|
}
|
|
foundConfig.Mode = newMode
|
|
}
|
|
if newTimeout != -1 {
|
|
if newTimeout < 0 {
|
|
return errors.New("invalid timeout value given")
|
|
}
|
|
foundConfig.Timeout = newTimeout
|
|
}
|
|
|
|
/*
|
|
err = foundConfig.ValidateConfigs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*/
|
|
|
|
m.SaveConfigToDatabase()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Manager) RemoveConfig(configUUID string) error {
|
|
// Find and remove the config with the specified UUID
|
|
for i, config := range m.Configs {
|
|
if config.UUID == configUUID {
|
|
m.Configs = append(m.Configs[:i], m.Configs[i+1:]...)
|
|
m.SaveConfigToDatabase()
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("config not found")
|
|
}
|
|
|
|
func (m *Manager) SaveConfigToDatabase() {
|
|
m.Options.Database.Write("tcprox", "rules", m.Configs)
|
|
}
|