feat: inbound's port can use ports format
Some checks failed
Trigger CMFA Update / trigger-CMFA-update (push) Failing after 1s

This commit is contained in:
wwqgtxx 2025-02-27 09:59:09 +08:00
parent d81c19a7c8
commit 1dc4155195
15 changed files with 267 additions and 161 deletions

View File

@ -1096,7 +1096,7 @@ sub-rules:
listeners: listeners:
- name: socks5-in-1 - name: socks5-in-1
type: socks type: socks
port: 10808 port: 10808 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
#listen: 0.0.0.0 # 默认监听 0.0.0.0 #listen: 0.0.0.0 # 默认监听 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理
@ -1107,7 +1107,7 @@ listeners:
- name: http-in-1 - name: http-in-1
type: http type: http
port: 10809 port: 10809 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1117,7 +1117,7 @@ listeners:
- name: mixed-in-1 - name: mixed-in-1
type: mixed # HTTP(S) 和 SOCKS 代理混合 type: mixed # HTTP(S) 和 SOCKS 代理混合
port: 10810 port: 10810 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1128,14 +1128,14 @@ listeners:
- name: reidr-in-1 - name: reidr-in-1
type: redir type: redir
port: 10811 port: 10811 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
- name: tproxy-in-1 - name: tproxy-in-1
type: tproxy type: tproxy
port: 10812 port: 10812 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1143,7 +1143,7 @@ listeners:
- name: shadowsocks-in-1 - name: shadowsocks-in-1
type: shadowsocks type: shadowsocks
port: 10813 port: 10813 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1152,7 +1152,7 @@ listeners:
- name: vmess-in-1 - name: vmess-in-1
type: vmess type: vmess
port: 10814 port: 10814 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1176,7 +1176,7 @@ listeners:
- name: tuic-in-1 - name: tuic-in-1
type: tuic type: tuic
port: 10815 port: 10815 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1196,7 +1196,7 @@ listeners:
- name: tunnel-in-1 - name: tunnel-in-1
type: tunnel type: tunnel
port: 10816 port: 10816 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1205,7 +1205,7 @@ listeners:
- name: vless-in-1 - name: vless-in-1
type: vless type: vless
port: 10817 port: 10817 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)
@ -1230,7 +1230,7 @@ listeners:
- name: anytls-in-1 - name: anytls-in-1
type: anytls type: anytls
port: 10818 port: 10818 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
users: users:
username1: password1 username1: password1
@ -1242,7 +1242,7 @@ listeners:
- name: trojan-in-1 - name: trojan-in-1
type: trojan type: trojan
port: 10819 port: 10819 # 支持使用ports格式例如200,302 or 200,204,401-429,501-503
listen: 0.0.0.0 listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules # rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错) # proxy: proxy # 如果不为空则直接将该入站流量交由指定 proxy 处理 (当 proxy 不为空时,这里的 proxy 名称必须合法,否则会出错)

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/listener/anytls" "github.com/metacubex/mihomo/listener/anytls"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
@ -52,12 +54,13 @@ func (v *AnyTLS) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (v *AnyTLS) Address() string { func (v *AnyTLS) Address() string {
var addrList []string
if v.l != nil { if v.l != nil {
for _, addr := range v.l.AddrList() { for _, addr := range v.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener

View File

@ -5,8 +5,10 @@ import (
"net" "net"
"net/netip" "net/netip"
"strconv" "strconv"
"strings"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/common/utils"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
) )
@ -15,7 +17,7 @@ type Base struct {
name string name string
specialRules string specialRules string
listenAddr netip.Addr listenAddr netip.Addr
port int ports utils.IntRanges[uint16]
} }
func NewBase(options *BaseOption) (*Base, error) { func NewBase(options *BaseOption) (*Base, error) {
@ -26,11 +28,15 @@ func NewBase(options *BaseOption) (*Base, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
ports, err := utils.NewUnsignedRanges[uint16](options.Port)
if err != nil {
return nil, err
}
return &Base{ return &Base{
name: options.Name(), name: options.Name(),
listenAddr: addr, listenAddr: addr,
specialRules: options.SpecialRules, specialRules: options.SpecialRules,
port: options.Port, ports: ports,
config: options, config: options,
}, nil }, nil
} }
@ -57,7 +63,15 @@ func (b *Base) Name() string {
// RawAddress implements constant.InboundListener // RawAddress implements constant.InboundListener
func (b *Base) RawAddress() string { func (b *Base) RawAddress() string {
return net.JoinHostPort(b.listenAddr.String(), strconv.Itoa(int(b.port))) if len(b.ports) == 0 {
return net.JoinHostPort(b.listenAddr.String(), "0")
}
address := make([]string, 0, len(b.ports))
b.ports.Range(func(port uint16) bool {
address = append(address, net.JoinHostPort(b.listenAddr.String(), strconv.Itoa(int(port))))
return true
})
return strings.Join(address, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener
@ -74,7 +88,7 @@ var _ C.InboundListener = (*Base)(nil)
type BaseOption struct { type BaseOption struct {
NameStr string `inbound:"name"` NameStr string `inbound:"name"`
Listen string `inbound:"listen,omitempty"` Listen string `inbound:"listen,omitempty"`
Port int `inbound:"port,omitempty"` Port string `inbound:"port,omitempty"`
SpecialRules string `inbound:"rule,omitempty"` SpecialRules string `inbound:"rule,omitempty"`
SpecialProxy string `inbound:"proxy,omitempty"` SpecialProxy string `inbound:"proxy,omitempty"`
} }

View File

@ -1,6 +1,10 @@
package inbound package inbound
import ( import (
"errors"
"fmt"
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/listener/http" "github.com/metacubex/mihomo/listener/http"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
@ -18,7 +22,7 @@ func (o HTTPOption) Equal(config C.InboundConfig) bool {
type HTTP struct { type HTTP struct {
*Base *Base
config *HTTPOption config *HTTPOption
l *http.Listener l []*http.Listener
} }
func NewHTTP(options *HTTPOption) (*HTTP, error) { func NewHTTP(options *HTTPOption) (*HTTP, error) {
@ -39,24 +43,37 @@ func (h *HTTP) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (h *HTTP) Address() string { func (h *HTTP) Address() string {
return h.l.Address() var addrList []string
for _, l := range h.l {
addrList = append(addrList, l.Address())
}
return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener
func (h *HTTP) Listen(tunnel C.Tunnel) error { func (h *HTTP) Listen(tunnel C.Tunnel) error {
var err error for _, addr := range strings.Split(h.RawAddress(), ",") {
h.l, err = http.NewWithAuthenticator(h.RawAddress(), tunnel, h.config.Users.GetAuthStore(), h.Additions()...) l, err := http.NewWithAuthenticator(addr, tunnel, h.config.Users.GetAuthStore(), h.Additions()...)
if err != nil { if err != nil {
return err return err
} }
h.l = append(h.l, l)
}
log.Infoln("HTTP[%s] proxy listening at: %s", h.Name(), h.Address()) log.Infoln("HTTP[%s] proxy listening at: %s", h.Name(), h.Address())
return nil return nil
} }
// Close implements constant.InboundListener // Close implements constant.InboundListener
func (h *HTTP) Close() error { func (h *HTTP) Close() error {
if h.l != nil { var errs []error
return h.l.Close() for _, l := range h.l {
err := l.Close()
if err != nil {
errs = append(errs, fmt.Errorf("close tcp listener %s err: %w", l.Address(), err))
}
}
if len(errs) > 0 {
return errors.Join(errs...)
} }
return nil return nil
} }

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing_hysteria2" "github.com/metacubex/mihomo/listener/sing_hysteria2"
@ -83,12 +85,13 @@ func (t *Hysteria2) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (t *Hysteria2) Address() string { func (t *Hysteria2) Address() string {
var addrList []string
if t.l != nil { if t.l != nil {
for _, addr := range t.l.AddrList() { for _, addr := range t.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener

View File

@ -1,7 +1,9 @@
package inbound package inbound
import ( import (
"errors"
"fmt" "fmt"
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
@ -23,8 +25,8 @@ func (o MixedOption) Equal(config C.InboundConfig) bool {
type Mixed struct { type Mixed struct {
*Base *Base
config *MixedOption config *MixedOption
l *mixed.Listener l []*mixed.Listener
lUDP *socks.UDPListener lUDP []*socks.UDPListener
udp bool udp bool
} }
@ -47,21 +49,28 @@ func (m *Mixed) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (m *Mixed) Address() string { func (m *Mixed) Address() string {
return m.l.Address() var addrList []string
for _, l := range m.l {
addrList = append(addrList, l.Address())
}
return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener
func (m *Mixed) Listen(tunnel C.Tunnel) error { func (m *Mixed) Listen(tunnel C.Tunnel) error {
var err error for _, addr := range strings.Split(m.RawAddress(), ",") {
m.l, err = mixed.NewWithAuthenticator(m.RawAddress(), tunnel, m.config.Users.GetAuthStore(), m.Additions()...) l, err := mixed.NewWithAuthenticator(addr, tunnel, m.config.Users.GetAuthStore(), m.Additions()...)
if err != nil { if err != nil {
return err return err
} }
m.l = append(m.l, l)
if m.udp { if m.udp {
m.lUDP, err = socks.NewUDP(m.RawAddress(), tunnel, m.Additions()...) lUDP, err := socks.NewUDP(addr, tunnel, m.Additions()...)
if err != nil { if err != nil {
return err return err
} }
m.lUDP = append(m.lUDP, lUDP)
}
} }
log.Infoln("Mixed(http+socks)[%s] proxy listening at: %s", m.Name(), m.Address()) log.Infoln("Mixed(http+socks)[%s] proxy listening at: %s", m.Name(), m.Address())
return nil return nil
@ -69,22 +78,23 @@ func (m *Mixed) Listen(tunnel C.Tunnel) error {
// Close implements constant.InboundListener // Close implements constant.InboundListener
func (m *Mixed) Close() error { func (m *Mixed) Close() error {
var err error var errs []error
if m.l != nil { for _, l := range m.l {
if tcpErr := m.l.Close(); tcpErr != nil { err := l.Close()
err = tcpErr if err != nil {
errs = append(errs, fmt.Errorf("close tcp listener %s err: %w", l.Address(), err))
} }
} }
if m.udp && m.lUDP != nil { for _, l := range m.lUDP {
if udpErr := m.lUDP.Close(); udpErr != nil { err := l.Close()
if err == nil { if err != nil {
err = udpErr errs = append(errs, fmt.Errorf("close udp listener %s err: %w", l.Address(), err))
} else {
return fmt.Errorf("close tcp err: %s, close udp err: %s", err.Error(), udpErr.Error())
} }
} }
if len(errs) > 0 {
return errors.Join(errs...)
} }
return err return nil
} }
var _ C.InboundListener = (*Mixed)(nil) var _ C.InboundListener = (*Mixed)(nil)

View File

@ -1,6 +1,10 @@
package inbound package inbound
import ( import (
"errors"
"fmt"
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/listener/redir" "github.com/metacubex/mihomo/listener/redir"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
@ -17,7 +21,7 @@ func (o RedirOption) Equal(config C.InboundConfig) bool {
type Redir struct { type Redir struct {
*Base *Base
config *RedirOption config *RedirOption
l *redir.Listener l []*redir.Listener
} }
func NewRedir(options *RedirOption) (*Redir, error) { func NewRedir(options *RedirOption) (*Redir, error) {
@ -38,24 +42,37 @@ func (r *Redir) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (r *Redir) Address() string { func (r *Redir) Address() string {
return r.l.Address() var addrList []string
for _, l := range r.l {
addrList = append(addrList, l.Address())
}
return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener
func (r *Redir) Listen(tunnel C.Tunnel) error { func (r *Redir) Listen(tunnel C.Tunnel) error {
var err error for _, addr := range strings.Split(r.RawAddress(), ",") {
r.l, err = redir.New(r.RawAddress(), tunnel, r.Additions()...) l, err := redir.New(addr, tunnel, r.Additions()...)
if err != nil { if err != nil {
return err return err
} }
r.l = append(r.l, l)
}
log.Infoln("Redir[%s] proxy listening at: %s", r.Name(), r.Address()) log.Infoln("Redir[%s] proxy listening at: %s", r.Name(), r.Address())
return nil return nil
} }
// Close implements constant.InboundListener // Close implements constant.InboundListener
func (r *Redir) Close() error { func (r *Redir) Close() error {
if r.l != nil { var errs []error
r.l.Close() for _, l := range r.l {
err := l.Close()
if err != nil {
errs = append(errs, fmt.Errorf("close redir listener %s err: %w", l.Address(), err))
}
}
if len(errs) > 0 {
return errors.Join(errs...)
} }
return nil return nil
} }

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing_shadowsocks" "github.com/metacubex/mihomo/listener/sing_shadowsocks"
@ -52,12 +54,13 @@ func (s *ShadowSocks) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (s *ShadowSocks) Address() string { func (s *ShadowSocks) Address() string {
var addrList []string
if s.l != nil { if s.l != nil {
for _, addr := range s.l.AddrList() { for _, addr := range s.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener

View File

@ -1,7 +1,10 @@
package inbound package inbound
import ( import (
"errors"
"fmt" "fmt"
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/listener/socks" "github.com/metacubex/mihomo/listener/socks"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
@ -21,8 +24,8 @@ type Socks struct {
*Base *Base
config *SocksOption config *SocksOption
udp bool udp bool
stl *socks.Listener stl []*socks.Listener
sul *socks.UDPListener sul []*socks.UDPListener
} }
func NewSocks(options *SocksOption) (*Socks, error) { func NewSocks(options *SocksOption) (*Socks, error) {
@ -44,40 +47,49 @@ func (s *Socks) Config() C.InboundConfig {
// Close implements constant.InboundListener // Close implements constant.InboundListener
func (s *Socks) Close() error { func (s *Socks) Close() error {
var err error var errs []error
if s.stl != nil { for _, l := range s.stl {
if tcpErr := s.stl.Close(); tcpErr != nil { err := l.Close()
err = tcpErr if err != nil {
errs = append(errs, fmt.Errorf("close tcp listener %s err: %w", l.Address(), err))
} }
} }
if s.udp && s.sul != nil { for _, l := range s.sul {
if udpErr := s.sul.Close(); udpErr != nil { err := l.Close()
if err == nil { if err != nil {
err = udpErr errs = append(errs, fmt.Errorf("close udp listener %s err: %w", l.Address(), err))
} else {
return fmt.Errorf("close tcp err: %s, close udp err: %s", err.Error(), udpErr.Error())
} }
} }
if len(errs) > 0 {
return errors.Join(errs...)
} }
return nil
return err
} }
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (s *Socks) Address() string { func (s *Socks) Address() string {
return s.stl.Address() var addrList []string
for _, l := range s.stl {
addrList = append(addrList, l.Address())
}
return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener
func (s *Socks) Listen(tunnel C.Tunnel) error { func (s *Socks) Listen(tunnel C.Tunnel) error {
var err error for _, addr := range strings.Split(s.RawAddress(), ",") {
if s.stl, err = socks.NewWithAuthenticator(s.RawAddress(), tunnel, s.config.Users.GetAuthStore(), s.Additions()...); err != nil { stl, err := socks.NewWithAuthenticator(addr, tunnel, s.config.Users.GetAuthStore(), s.Additions()...)
if err != nil {
return err return err
} }
s.stl = append(s.stl, stl)
if s.udp { if s.udp {
if s.sul, err = socks.NewUDP(s.RawAddress(), tunnel, s.Additions()...); err != nil { sul, err := socks.NewUDP(addr, tunnel, s.Additions()...)
if err != nil {
return err return err
} }
s.sul = append(s.sul, sul)
}
} }
log.Infoln("SOCKS[%s] proxy listening at: %s", s.Name(), s.Address()) log.Infoln("SOCKS[%s] proxy listening at: %s", s.Name(), s.Address())

View File

@ -1,7 +1,9 @@
package inbound package inbound
import ( import (
"errors"
"fmt" "fmt"
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/listener/tproxy" "github.com/metacubex/mihomo/listener/tproxy"
@ -20,8 +22,8 @@ func (o TProxyOption) Equal(config C.InboundConfig) bool {
type TProxy struct { type TProxy struct {
*Base *Base
config *TProxyOption config *TProxyOption
lUDP *tproxy.UDPListener lUDP []*tproxy.UDPListener
lTCP *tproxy.Listener lTCP []*tproxy.Listener
udp bool udp bool
} }
@ -45,21 +47,28 @@ func (t *TProxy) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (t *TProxy) Address() string { func (t *TProxy) Address() string {
return t.lTCP.Address() var addrList []string
for _, l := range t.lTCP {
addrList = append(addrList, l.Address())
}
return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener
func (t *TProxy) Listen(tunnel C.Tunnel) error { func (t *TProxy) Listen(tunnel C.Tunnel) error {
var err error for _, addr := range strings.Split(t.RawAddress(), ",") {
t.lTCP, err = tproxy.New(t.RawAddress(), tunnel, t.Additions()...) lTCP, err := tproxy.New(addr, tunnel, t.Additions()...)
if err != nil { if err != nil {
return err return err
} }
t.lTCP = append(t.lTCP, lTCP)
if t.udp { if t.udp {
t.lUDP, err = tproxy.NewUDP(t.RawAddress(), tunnel, t.Additions()...) lUDP, err := tproxy.NewUDP(addr, tunnel, t.Additions()...)
if err != nil { if err != nil {
return err return err
} }
t.lUDP = append(t.lUDP, lUDP)
}
} }
log.Infoln("TProxy[%s] proxy listening at: %s", t.Name(), t.Address()) log.Infoln("TProxy[%s] proxy listening at: %s", t.Name(), t.Address())
return nil return nil
@ -67,23 +76,21 @@ func (t *TProxy) Listen(tunnel C.Tunnel) error {
// Close implements constant.InboundListener // Close implements constant.InboundListener
func (t *TProxy) Close() error { func (t *TProxy) Close() error {
var tcpErr error var errs []error
var udpErr error for _, l := range t.lTCP {
if t.lTCP != nil { err := l.Close()
tcpErr = t.lTCP.Close() if err != nil {
errs = append(errs, fmt.Errorf("close tcp listener %s err: %w", l.Address(), err))
} }
if t.lUDP != nil {
udpErr = t.lUDP.Close()
} }
for _, l := range t.lUDP {
if tcpErr != nil && udpErr != nil { err := l.Close()
return fmt.Errorf("tcp close err: %s and udp close err: %s", tcpErr, udpErr) if err != nil {
errs = append(errs, fmt.Errorf("close udp listener %s err: %w", l.Address(), err))
} }
if tcpErr != nil {
return tcpErr
} }
if udpErr != nil { if len(errs) > 0 {
return udpErr return errors.Join(errs...)
} }
return nil return nil
} }

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/trojan" "github.com/metacubex/mihomo/listener/trojan"
@ -83,12 +85,13 @@ func (v *Trojan) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (v *Trojan) Address() string { func (v *Trojan) Address() string {
var addrList []string
if v.l != nil { if v.l != nil {
for _, addr := range v.l.AddrList() { for _, addr := range v.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/tuic" "github.com/metacubex/mihomo/listener/tuic"
@ -66,12 +68,13 @@ func (t *Tuic) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (t *Tuic) Address() string { func (t *Tuic) Address() string {
var addrList []string
if t.l != nil { if t.l != nil {
for _, addr := range t.l.AddrList() { for _, addr := range t.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener

View File

@ -1,7 +1,9 @@
package inbound package inbound
import ( import (
"errors"
"fmt" "fmt"
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LT "github.com/metacubex/mihomo/listener/tunnel" LT "github.com/metacubex/mihomo/listener/tunnel"
@ -21,8 +23,8 @@ func (o TunnelOption) Equal(config C.InboundConfig) bool {
type Tunnel struct { type Tunnel struct {
*Base *Base
config *TunnelOption config *TunnelOption
ttl *LT.Listener ttl []*LT.Listener
tul *LT.PacketConn tul []*LT.PacketConn
} }
func NewTunnel(options *TunnelOption) (*Tunnel, error) { func NewTunnel(options *TunnelOption) (*Tunnel, error) {
@ -43,56 +45,62 @@ func (t *Tunnel) Config() C.InboundConfig {
// Close implements constant.InboundListener // Close implements constant.InboundListener
func (t *Tunnel) Close() error { func (t *Tunnel) Close() error {
var err error var errs []error
if t.ttl != nil { for _, l := range t.ttl {
if tcpErr := t.ttl.Close(); tcpErr != nil { err := l.Close()
err = tcpErr if err != nil {
errs = append(errs, fmt.Errorf("close tcp listener %s err: %w", l.Address(), err))
} }
} }
if t.tul != nil { for _, l := range t.tul {
if udpErr := t.tul.Close(); udpErr != nil { err := l.Close()
if err == nil { if err != nil {
err = udpErr errs = append(errs, fmt.Errorf("close udp listener %s err: %w", l.Address(), err))
} else {
return fmt.Errorf("close tcp err: %s, close udp err: %s", err.Error(), udpErr.Error())
} }
} }
} if len(errs) > 0 {
return errors.Join(errs...)
return err
}
// Address implements constant.InboundListener
func (t *Tunnel) Address() string {
if t.ttl != nil {
return t.ttl.Address()
}
if t.tul != nil {
return t.tul.Address()
}
return ""
}
// Listen implements constant.InboundListener
func (t *Tunnel) Listen(tunnel C.Tunnel) error {
var err error
for _, network := range t.config.Network {
switch network {
case "tcp":
if t.ttl, err = LT.New(t.RawAddress(), t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...); err != nil {
return err
}
case "udp":
if t.tul, err = LT.NewUDP(t.RawAddress(), t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...); err != nil {
return err
}
default:
log.Warnln("unknown network type: %s, passed", network)
continue
}
log.Infoln("Tunnel[%s](%s/%s)proxy listening at: %s", t.Name(), network, t.config.Target, t.Address())
} }
return nil return nil
} }
// Address implements constant.InboundListener
func (t *Tunnel) Address() string {
var addrList []string
for _, l := range t.ttl {
addrList = append(addrList, "tcp://"+l.Address())
}
for _, l := range t.tul {
addrList = append(addrList, "udp://"+l.Address())
}
return strings.Join(addrList, ",")
}
// Listen implements constant.InboundListener
func (t *Tunnel) Listen(tunnel C.Tunnel) error {
for _, addr := range strings.Split(t.RawAddress(), ",") {
for _, network := range t.config.Network {
switch network {
case "tcp":
ttl, err := LT.New(addr, t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...)
if err != nil {
return err
}
t.ttl = append(t.ttl, ttl)
case "udp":
tul, err := LT.NewUDP(addr, t.config.Target, t.config.SpecialProxy, tunnel, t.Additions()...)
if err != nil {
return err
}
t.tul = append(t.tul, tul)
default:
log.Warnln("unknown network type: %s, passed", network)
continue
}
}
}
log.Infoln("Tunnel[%s](%s)proxy listening at: %s", t.Name(), t.config.Target, t.Address())
return nil
}
var _ C.InboundListener = (*Tunnel)(nil) var _ C.InboundListener = (*Tunnel)(nil)

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing_vless" "github.com/metacubex/mihomo/listener/sing_vless"
@ -72,12 +74,13 @@ func (v *Vless) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (v *Vless) Address() string { func (v *Vless) Address() string {
var addrList []string
if v.l != nil { if v.l != nil {
for _, addr := range v.l.AddrList() { for _, addr := range v.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener

View File

@ -1,6 +1,8 @@
package inbound package inbound
import ( import (
"strings"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config" LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing_vmess" "github.com/metacubex/mihomo/listener/sing_vmess"
@ -72,12 +74,13 @@ func (v *Vmess) Config() C.InboundConfig {
// Address implements constant.InboundListener // Address implements constant.InboundListener
func (v *Vmess) Address() string { func (v *Vmess) Address() string {
var addrList []string
if v.l != nil { if v.l != nil {
for _, addr := range v.l.AddrList() { for _, addr := range v.l.AddrList() {
return addr.String() addrList = append(addrList, addr.String())
} }
} }
return "" return strings.Join(addrList, ",")
} }
// Listen implements constant.InboundListener // Listen implements constant.InboundListener