fix: skip-auth-prefixes not apply on listeners when users is unset

This commit is contained in:
wwqgtxx 2024-09-27 18:10:05 +08:00
parent 88bfe7cffe
commit cd2d1c6bb0
11 changed files with 70 additions and 49 deletions

View File

@ -5,6 +5,11 @@ type Authenticator interface {
Users() []string Users() []string
} }
type AuthStore interface {
Authenticator() Authenticator
SetAuthenticator(Authenticator)
}
type AuthUser struct { type AuthUser struct {
User string User string
Pass string Pass string

View File

@ -127,7 +127,7 @@ func initInnerTcp() {
func GetGeneral() *config.General { func GetGeneral() *config.General {
ports := listener.GetPorts() ports := listener.GetPorts()
var authenticator []string var authenticator []string
if auth := authStore.Authenticator(); auth != nil { if auth := authStore.Default.Authenticator(); auth != nil {
authenticator = auth.Users() authenticator = auth.Users()
} }
@ -422,7 +422,7 @@ func updateGeneral(general *config.General) {
func updateUsers(users []auth.AuthUser) { func updateUsers(users []auth.AuthUser) {
authenticator := auth.NewAuthenticator(users) authenticator := auth.NewAuthenticator(users)
authStore.SetAuthenticator(authenticator) authStore.Default.SetAuthenticator(authenticator)
if authenticator != nil { if authenticator != nil {
log.Infoln("Authentication of local server updated") log.Infoln("Authentication of local server updated")
} }

View File

@ -4,14 +4,30 @@ import (
"github.com/metacubex/mihomo/component/auth" "github.com/metacubex/mihomo/component/auth"
) )
var authenticator auth.Authenticator type authStore struct {
authenticator auth.Authenticator
func Authenticator() auth.Authenticator {
return authenticator
} }
func SetAuthenticator(au auth.Authenticator) { func (a *authStore) Authenticator() auth.Authenticator {
authenticator = au return a.authenticator
} }
func Nil() auth.Authenticator { return nil } func (a *authStore) SetAuthenticator(authenticator auth.Authenticator) {
a.authenticator = authenticator
}
func NewAuthStore(authenticator auth.Authenticator) auth.AuthStore {
return &authStore{authenticator}
}
var Default auth.AuthStore = NewAuthStore(nil)
type nilAuthStore struct{}
func (a *nilAuthStore) Authenticator() auth.Authenticator {
return nil
}
func (a *nilAuthStore) SetAuthenticator(authenticator auth.Authenticator) {}
var Nil auth.AuthStore = (*nilAuthStore)(nil) // always return nil, even call SetAuthenticator() with a non-nil authenticator

View File

@ -30,7 +30,7 @@ func (b *bodyWrapper) Read(p []byte) (n int, err error) {
return n, err return n, err
} }
func HandleConn(c net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) { func HandleConn(c net.Conn, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) {
additions = append(additions, inbound.Placeholder) // Add a placeholder for InUser additions = append(additions, inbound.Placeholder) // Add a placeholder for InUser
inUserIdx := len(additions) - 1 inUserIdx := len(additions) - 1
client := newClient(c, tunnel, additions) client := newClient(c, tunnel, additions)
@ -41,7 +41,7 @@ func HandleConn(c net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator,
conn := N.NewBufferedConn(c) conn := N.NewBufferedConn(c)
authenticator := getAuth() authenticator := store.Authenticator()
keepAlive := true keepAlive := true
trusted := authenticator == nil // disable authenticate if lru is nil trusted := authenticator == nil // disable authenticate if lru is nil
lastUser := "" lastUser := ""

View File

@ -32,20 +32,20 @@ func (l *Listener) Close() error {
} }
func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) {
return NewWithAuthenticator(addr, tunnel, authStore.Authenticator, additions...) return NewWithAuthenticator(addr, tunnel, authStore.Default, additions...)
} }
// NewWithAuthenticate // NewWithAuthenticate
// never change type traits because it's used in CMFA // never change type traits because it's used in CMFA
func NewWithAuthenticate(addr string, tunnel C.Tunnel, authenticate bool, additions ...inbound.Addition) (*Listener, error) { func NewWithAuthenticate(addr string, tunnel C.Tunnel, authenticate bool, additions ...inbound.Addition) (*Listener, error) {
getAuth := authStore.Authenticator store := authStore.Default
if !authenticate { if !authenticate {
getAuth = authStore.Nil store = authStore.Default
} }
return NewWithAuthenticator(addr, tunnel, getAuth, additions...) return NewWithAuthenticator(addr, tunnel, store, additions...)
} }
func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) (*Listener, error) { func NewWithAuthenticator(addr string, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) (*Listener, error) {
isDefault := false isDefault := false
if len(additions) == 0 { if len(additions) == 0 {
isDefault = true isDefault = true
@ -74,17 +74,17 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
continue continue
} }
getAuth := getAuth store := store
if isDefault { // only apply on default listener if isDefault || store == authStore.Default { // only apply on default listener
if !inbound.IsRemoteAddrDisAllowed(conn.RemoteAddr()) { if !inbound.IsRemoteAddrDisAllowed(conn.RemoteAddr()) {
_ = conn.Close() _ = conn.Close()
continue continue
} }
if inbound.SkipAuthRemoteAddr(conn.RemoteAddr()) { if inbound.SkipAuthRemoteAddr(conn.RemoteAddr()) {
getAuth = authStore.Nil store = authStore.Nil
} }
} }
go HandleConn(conn, tunnel, getAuth, additions...) go HandleConn(conn, tunnel, store, additions...)
} }
}() }()

View File

@ -12,7 +12,7 @@ type AuthUser struct {
type AuthUsers []AuthUser type AuthUsers []AuthUser
func (a AuthUsers) GetAuth() func() auth.Authenticator { func (a AuthUsers) GetAuthStore() auth.AuthStore {
if a != nil { // structure's Decode will ensure value not nil when input has value even it was set an empty array if a != nil { // structure's Decode will ensure value not nil when input has value even it was set an empty array
if len(a) == 0 { if len(a) == 0 {
return authStore.Nil return authStore.Nil
@ -25,7 +25,7 @@ func (a AuthUsers) GetAuth() func() auth.Authenticator {
} }
} }
authenticator := auth.NewAuthenticator(users) authenticator := auth.NewAuthenticator(users)
return func() auth.Authenticator { return authenticator } return authStore.NewAuthStore(authenticator)
} }
return authStore.Authenticator return authStore.Default
} }

View File

@ -45,7 +45,7 @@ func (h *HTTP) Address() string {
// 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 var err error
h.l, err = http.NewWithAuthenticator(h.RawAddress(), tunnel, h.config.Users.GetAuth(), h.Additions()...) h.l, err = http.NewWithAuthenticator(h.RawAddress(), tunnel, h.config.Users.GetAuthStore(), h.Additions()...)
if err != nil { if err != nil {
return err return err
} }

View File

@ -53,7 +53,7 @@ func (m *Mixed) Address() string {
// 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 var err error
m.l, err = mixed.NewWithAuthenticator(m.RawAddress(), tunnel, m.config.Users.GetAuth(), m.Additions()...) m.l, err = mixed.NewWithAuthenticator(m.RawAddress(), tunnel, m.config.Users.GetAuthStore(), m.Additions()...)
if err != nil { if err != nil {
return err return err
} }

View File

@ -71,7 +71,7 @@ func (s *Socks) Address() string {
// 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 var err error
if s.stl, err = socks.NewWithAuthenticator(s.RawAddress(), tunnel, s.config.Users.GetAuth(), s.Additions()...); err != nil { if s.stl, err = socks.NewWithAuthenticator(s.RawAddress(), tunnel, s.config.Users.GetAuthStore(), s.Additions()...); err != nil {
return err return err
} }
if s.udp { if s.udp {

View File

@ -37,10 +37,10 @@ func (l *Listener) Close() error {
} }
func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) {
return NewWithAuthenticator(addr, tunnel, authStore.Authenticator, additions...) return NewWithAuthenticator(addr, tunnel, authStore.Default, additions...)
} }
func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) (*Listener, error) { func NewWithAuthenticator(addr string, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) (*Listener, error) {
isDefault := false isDefault := false
if len(additions) == 0 { if len(additions) == 0 {
isDefault = true isDefault = true
@ -68,24 +68,24 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
} }
continue continue
} }
getAuth := getAuth store := store
if isDefault { // only apply on default listener if isDefault || store == authStore.Default { // only apply on default listener
if !inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) { if !inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) {
_ = c.Close() _ = c.Close()
continue continue
} }
if inbound.SkipAuthRemoteAddr(c.RemoteAddr()) { if inbound.SkipAuthRemoteAddr(c.RemoteAddr()) {
getAuth = authStore.Nil store = authStore.Nil
} }
} }
go handleConn(c, tunnel, getAuth, additions...) go handleConn(c, tunnel, store, additions...)
} }
}() }()
return ml, nil return ml, nil
} }
func handleConn(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) { func handleConn(conn net.Conn, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) {
bufConn := N.NewBufferedConn(conn) bufConn := N.NewBufferedConn(conn)
head, err := bufConn.Peek(1) head, err := bufConn.Peek(1)
if err != nil { if err != nil {
@ -94,10 +94,10 @@ func handleConn(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticato
switch head[0] { switch head[0] {
case socks4.Version: case socks4.Version:
socks.HandleSocks4(bufConn, tunnel, getAuth, additions...) socks.HandleSocks4(bufConn, tunnel, store, additions...)
case socks5.Version: case socks5.Version:
socks.HandleSocks5(bufConn, tunnel, getAuth, additions...) socks.HandleSocks5(bufConn, tunnel, store, additions...)
default: default:
http.HandleConn(bufConn, tunnel, getAuth, additions...) http.HandleConn(bufConn, tunnel, store, additions...)
} }
} }

View File

@ -36,10 +36,10 @@ func (l *Listener) Close() error {
} }
func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) {
return NewWithAuthenticator(addr, tunnel, authStore.Authenticator, additions...) return NewWithAuthenticator(addr, tunnel, authStore.Default, additions...)
} }
func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) (*Listener, error) { func NewWithAuthenticator(addr string, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) (*Listener, error) {
isDefault := false isDefault := false
if len(additions) == 0 { if len(additions) == 0 {
isDefault = true isDefault = true
@ -67,24 +67,24 @@ func NewWithAuthenticator(addr string, tunnel C.Tunnel, getAuth func() auth.Auth
} }
continue continue
} }
getAuth := getAuth store := store
if isDefault { // only apply on default listener if isDefault || store == authStore.Default { // only apply on default listener
if !inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) { if !inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) {
_ = c.Close() _ = c.Close()
continue continue
} }
if inbound.SkipAuthRemoteAddr(c.RemoteAddr()) { if inbound.SkipAuthRemoteAddr(c.RemoteAddr()) {
getAuth = authStore.Nil store = authStore.Nil
} }
} }
go handleSocks(c, tunnel, getAuth, additions...) go handleSocks(c, tunnel, store, additions...)
} }
}() }()
return sl, nil return sl, nil
} }
func handleSocks(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) { func handleSocks(conn net.Conn, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) {
bufConn := N.NewBufferedConn(conn) bufConn := N.NewBufferedConn(conn)
head, err := bufConn.Peek(1) head, err := bufConn.Peek(1)
if err != nil { if err != nil {
@ -94,16 +94,16 @@ func handleSocks(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticat
switch head[0] { switch head[0] {
case socks4.Version: case socks4.Version:
HandleSocks4(bufConn, tunnel, getAuth, additions...) HandleSocks4(bufConn, tunnel, store, additions...)
case socks5.Version: case socks5.Version:
HandleSocks5(bufConn, tunnel, getAuth, additions...) HandleSocks5(bufConn, tunnel, store, additions...)
default: default:
conn.Close() conn.Close()
} }
} }
func HandleSocks4(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) { func HandleSocks4(conn net.Conn, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) {
authenticator := getAuth() authenticator := store.Authenticator()
addr, _, user, err := socks4.ServerHandshake(conn, authenticator) addr, _, user, err := socks4.ServerHandshake(conn, authenticator)
if err != nil { if err != nil {
conn.Close() conn.Close()
@ -113,8 +113,8 @@ func HandleSocks4(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authentica
tunnel.HandleTCPConn(inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4, additions...)) tunnel.HandleTCPConn(inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4, additions...))
} }
func HandleSocks5(conn net.Conn, tunnel C.Tunnel, getAuth func() auth.Authenticator, additions ...inbound.Addition) { func HandleSocks5(conn net.Conn, tunnel C.Tunnel, store auth.AuthStore, additions ...inbound.Addition) {
authenticator := getAuth() authenticator := store.Authenticator()
target, command, user, err := socks5.ServerHandshake(conn, authenticator) target, command, user, err := socks5.ServerHandshake(conn, authenticator)
if err != nil { if err != nil {
conn.Close() conn.Close()