update: 更新支持socket 5端口监听

This commit is contained in:
xiamuceer-j
2026-03-06 15:17:49 +08:00
parent 20e5402854
commit a31ac4f51a
14 changed files with 166 additions and 39 deletions
+63 -32
View File
@@ -199,23 +199,19 @@ func Build(cfg *config.Config) (option.Options, error) {
Options: &perOptions,
}
outbounds = append(outbounds, perPool)
inboundOptions := &option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: addr,
ListenPort: meta.Port,
},
}
username := cfg.MultiPort.Username
password := cfg.MultiPort.Password
if username != "" {
inboundOptions.Users = []auth.User{{Username: username, Password: password}}
}
inboundTag := fmt.Sprintf("in-%s", tag)
inbounds = append(inbounds, option.Inbound{
Type: C.TypeHTTP,
Tag: inboundTag,
Options: inboundOptions,
})
inbound, err := buildInboundByProtocol(
cfg.MultiPort.Protocol,
addr,
meta.Port,
cfg.MultiPort.Username,
cfg.MultiPort.Password,
inboundTag,
)
if err != nil {
return option.Options{}, fmt.Errorf("build multi-port inbound for %s: %w", tag, err)
}
inbounds = append(inbounds, inbound)
route.Rules = append(route.Rules, option.Rule{
Type: C.RuleTypeDefault,
DefaultOptions: option.DefaultRule{
@@ -292,24 +288,59 @@ func buildPoolInbound(cfg *config.Config) (option.Inbound, error) {
if err != nil {
return option.Inbound{}, fmt.Errorf("parse listener address: %w", err)
}
inboundOptions := &option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: listenAddr,
ListenPort: cfg.Listener.Port,
},
return buildInboundByProtocol(
cfg.Listener.Protocol,
listenAddr,
cfg.Listener.Port,
cfg.Listener.Username,
cfg.Listener.Password,
"http-in",
)
}
func buildInboundByProtocol(protocol string, listenAddr *badoption.Addr, port uint16, username, password, tag string) (option.Inbound, error) {
users := []auth.User(nil)
if username != "" {
users = []auth.User{{Username: username, Password: password}}
}
if cfg.Listener.Username != "" {
inboundOptions.Users = []auth.User{{
Username: cfg.Listener.Username,
Password: cfg.Listener.Password,
}}
switch protocol {
case config.InboundProtocolHTTP:
opts := &option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: listenAddr,
ListenPort: port,
},
}
if len(users) > 0 {
opts.Users = users
}
return option.Inbound{Type: C.TypeHTTP, Tag: tag, Options: opts}, nil
case config.InboundProtocolSOCKS5:
opts := &option.SocksInboundOptions{
ListenOptions: option.ListenOptions{
Listen: listenAddr,
ListenPort: port,
},
}
if len(users) > 0 {
opts.Users = users
}
return option.Inbound{Type: C.TypeSOCKS, Tag: tag, Options: opts}, nil
case config.InboundProtocolMixed:
opts := &option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: listenAddr,
ListenPort: port,
},
}
if len(users) > 0 {
opts.Users = users
}
return option.Inbound{Type: C.TypeMixed, Tag: tag, Options: opts}, nil
default:
return option.Inbound{}, fmt.Errorf("unsupported inbound protocol %q", protocol)
}
inbound := option.Inbound{
Type: C.TypeHTTP,
Tag: "http-in",
Options: inboundOptions,
}
return inbound, nil
}
func buildNodeOutbound(tag, rawURI string, skipCertVerify bool) (option.Outbound, error) {
+49 -1
View File
@@ -50,10 +50,11 @@ type GeoIPConfig struct {
AutoUpdateInterval time.Duration `yaml:"auto_update_interval"` // 自动更新间隔,默认 24 小时
}
// ListenerConfig defines how the HTTP proxy should listen for clients.
// ListenerConfig defines how the proxy should listen for clients.
type ListenerConfig struct {
Address string `yaml:"address"`
Port uint16 `yaml:"port"`
Protocol string `yaml:"protocol"` // http, socks5, mixed
Username string `yaml:"username"`
Password string `yaml:"password"`
}
@@ -69,6 +70,7 @@ type PoolConfig struct {
type MultiPortConfig struct {
Address string `yaml:"address"`
BasePort uint16 `yaml:"base_port"`
Protocol string `yaml:"protocol"` // http, socks5, mixed
Username string `yaml:"username"`
Password string `yaml:"password"`
}
@@ -101,6 +103,27 @@ const (
NodeSourceManual NodeSource = "manual" // Added manually via WebUI
)
const (
InboundProtocolHTTP = "http"
InboundProtocolSOCKS5 = "socks5"
InboundProtocolMixed = "mixed"
)
// NormalizeInboundProtocol normalizes inbound protocol aliases and validates the value.
func NormalizeInboundProtocol(value string) (string, error) {
protocol := strings.ToLower(strings.TrimSpace(value))
switch protocol {
case "socks":
protocol = InboundProtocolSOCKS5
}
switch protocol {
case InboundProtocolHTTP, InboundProtocolSOCKS5, InboundProtocolMixed:
return protocol, nil
default:
return "", fmt.Errorf("不支持的监听协议: %q(仅支持 http/socks5/mixed)", value)
}
}
// NodeConfig describes a single upstream proxy endpoint expressed as URI.
type NodeConfig struct {
Name string `yaml:"name" json:"name"`
@@ -202,6 +225,14 @@ func (c *Config) applyDefaults() error {
if c.Listener.Port == 0 {
c.Listener.Port = 2323
}
if c.Listener.Protocol == "" {
c.Listener.Protocol = InboundProtocolHTTP
}
listenerProtocol, err := NormalizeInboundProtocol(c.Listener.Protocol)
if err != nil {
return err
}
c.Listener.Protocol = listenerProtocol
if c.Pool.Mode == "" {
c.Pool.Mode = "sequential"
}
@@ -217,6 +248,14 @@ func (c *Config) applyDefaults() error {
if c.MultiPort.BasePort == 0 {
c.MultiPort.BasePort = 28000
}
if c.MultiPort.Protocol == "" {
c.MultiPort.Protocol = InboundProtocolHTTP
}
multiPortProtocol, err := NormalizeInboundProtocol(c.MultiPort.Protocol)
if err != nil {
return err
}
c.MultiPort.Protocol = multiPortProtocol
if c.Management.Listen == "" {
c.Management.Listen = "127.0.0.1:9090"
}
@@ -1002,6 +1041,7 @@ func (c *Config) SaveSettings() error {
// ValidateSettingsRequest validates the settings request fields and returns
// a descriptive error for any invalid values, instead of silently ignoring them.
func ValidateSettingsRequest(mode string, listenerPort, multiPortBasePort uint16,
listenerProtocol, multiPortProtocol,
poolBlacklistDuration, subRefreshInterval, subRefreshTimeout,
subRefreshHealthCheckTimeout, subRefreshDrainTimeout,
geoIPAutoUpdateInterval string) error {
@@ -1021,6 +1061,14 @@ func ValidateSettingsRequest(mode string, listenerPort, multiPortBasePort uint16
return fmt.Errorf("多端口起始端口不能为 0")
}
// Validate inbound protocols
if _, err := NormalizeInboundProtocol(listenerProtocol); err != nil {
return fmt.Errorf("监听入口协议无效: %w", err)
}
if _, err := NormalizeInboundProtocol(multiPortProtocol); err != nil {
return fmt.Errorf("多端口入口协议无效: %w", err)
}
// Validate duration fields
durationFields := []struct {
name string
Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Easy Proxies</title>
<script type="module" crossorigin src="/assets/index-BkdNNtGR.js"></script>
<script type="module" crossorigin src="/assets/index-DXv5BU-I.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CZdhzSdd.css">
</head>
<body>
+13
View File
@@ -196,12 +196,14 @@ type allSettingsResponse struct {
// Listener
ListenerAddress string `json:"listener_address"`
ListenerPort uint16 `json:"listener_port"`
ListenerProtocol string `json:"listener_protocol"`
ListenerUsername string `json:"listener_username"`
ListenerPassword string `json:"listener_password"`
// Multi-port
MultiPortAddress string `json:"multi_port_address"`
MultiPortBasePort uint16 `json:"multi_port_base_port"`
MultiPortProtocol string `json:"multi_port_protocol"`
MultiPortUsername string `json:"multi_port_username"`
MultiPortPassword string `json:"multi_port_password"`
@@ -245,12 +247,14 @@ type allSettingsRequest struct {
// Listener
ListenerAddress string `json:"listener_address"`
ListenerPort uint16 `json:"listener_port"`
ListenerProtocol string `json:"listener_protocol"`
ListenerUsername string `json:"listener_username"`
ListenerPassword string `json:"listener_password"`
// Multi-port
MultiPortAddress string `json:"multi_port_address"`
MultiPortBasePort uint16 `json:"multi_port_base_port"`
MultiPortProtocol string `json:"multi_port_protocol"`
MultiPortUsername string `json:"multi_port_username"`
MultiPortPassword string `json:"multi_port_password"`
@@ -308,11 +312,13 @@ func (s *Server) getAllSettings() allSettingsResponse {
ListenerAddress: c.Listener.Address,
ListenerPort: c.Listener.Port,
ListenerProtocol: c.Listener.Protocol,
ListenerUsername: c.Listener.Username,
ListenerPassword: c.Listener.Password,
MultiPortAddress: c.MultiPort.Address,
MultiPortBasePort: c.MultiPort.BasePort,
MultiPortProtocol: c.MultiPort.Protocol,
MultiPortUsername: c.MultiPort.Username,
MultiPortPassword: c.MultiPort.Password,
@@ -346,6 +352,7 @@ func (s *Server) updateAllSettings(req allSettingsRequest) error {
// Validate request before applying
if err := config.ValidateSettingsRequest(
req.Mode, req.ListenerPort, req.MultiPortBasePort,
req.ListenerProtocol, req.MultiPortProtocol,
req.PoolBlacklistDuration, req.SubRefreshInterval, req.SubRefreshTimeout,
req.SubRefreshHealthCheckTimeout, req.SubRefreshDrainTimeout,
req.GeoIPAutoUpdateInterval,
@@ -374,12 +381,18 @@ func (s *Server) updateAllSettings(req allSettingsRequest) error {
// Listener
c.Listener.Address = req.ListenerAddress
c.Listener.Port = req.ListenerPort
if p, err := config.NormalizeInboundProtocol(req.ListenerProtocol); err == nil {
c.Listener.Protocol = p
}
c.Listener.Username = req.ListenerUsername
c.Listener.Password = req.ListenerPassword
// Multi-port
c.MultiPort.Address = req.MultiPortAddress
c.MultiPort.BasePort = req.MultiPortBasePort
if p, err := config.NormalizeInboundProtocol(req.MultiPortProtocol); err == nil {
c.MultiPort.Protocol = p
}
c.MultiPort.Username = req.MultiPortUsername
c.MultiPort.Password = req.MultiPortPassword