diff --git a/adapter/inbound/addition.go b/adapter/inbound/addition.go index 327d00e9..14fc303f 100644 --- a/adapter/inbound/addition.go +++ b/adapter/inbound/addition.go @@ -38,9 +38,27 @@ func WithSpecialProxy(specialProxy string) Addition { func WithSrcAddr(addr net.Addr) Addition { return func(metadata *C.Metadata) { - if ip, port, err := parseAddr(addr); err == nil { - metadata.SrcIP = ip - metadata.SrcPort = port + if addrPort, err := parseAddr(addr); err == nil { + metadata.SrcIP = addrPort.Addr() + metadata.SrcPort = addrPort.Port() + } + } +} + +func WithDstAddr(addr net.Addr) Addition { + return func(metadata *C.Metadata) { + if addrPort, err := parseAddr(addr); err == nil { + metadata.DstIP = addrPort.Addr() + metadata.DstPort = addrPort.Port() + } + } +} + +func WithInAddr(addr net.Addr) Addition { + return func(metadata *C.Metadata) { + if addrPort, err := parseAddr(addr); err == nil { + metadata.InIP = addrPort.Addr() + metadata.InPort = addrPort.Port() } } } diff --git a/adapter/inbound/auth.go b/adapter/inbound/auth.go new file mode 100644 index 00000000..724b5b7a --- /dev/null +++ b/adapter/inbound/auth.go @@ -0,0 +1,27 @@ +package inbound + +import ( + "net" + "net/netip" +) + +var skipAuthPrefixes []netip.Prefix + +func SetSkipAuthPrefixes(prefixes []netip.Prefix) { + skipAuthPrefixes = prefixes +} + +func SkipAuthPrefixes() []netip.Prefix { + return skipAuthPrefixes +} + +func SkipAuthRemoteAddr(addr net.Addr) bool { + if addrPort, err := parseAddr(addr); err == nil { + for _, prefix := range skipAuthPrefixes { + if prefix.Contains(addrPort.Addr()) { + return true + } + } + } + return false +} diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index b1b881ce..93ec2373 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -13,16 +13,9 @@ func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Ad metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = C.HTTP + additions = append(additions, WithSrcAddr(source), WithInAddr(conn.LocalAddr())) for _, addition := range additions { addition.Apply(metadata) } - if ip, port, err := parseAddr(source); err == nil { - metadata.SrcIP = ip - metadata.SrcPort = port - } - if ip, port, err := parseAddr(conn.LocalAddr()); err == nil { - metadata.InIP = ip - metadata.InPort = port - } return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/https.go b/adapter/inbound/https.go index 485e72bb..26f93a45 100644 --- a/adapter/inbound/https.go +++ b/adapter/inbound/https.go @@ -12,16 +12,9 @@ import ( func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) *context.ConnContext { metadata := parseHTTPAddr(request) metadata.Type = C.HTTPS + additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) for _, addition := range additions { addition.Apply(metadata) } - if ip, port, err := parseAddr(conn.RemoteAddr()); err == nil { - metadata.SrcIP = ip - metadata.SrcPort = port - } - if ip, port, err := parseAddr(conn.LocalAddr()); err == nil { - metadata.InIP = ip - metadata.InPort = port - } return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index 44e5e1a7..d481ec09 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -21,19 +21,13 @@ func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions metadata := parseSocksAddr(target) metadata.NetWork = C.UDP metadata.Type = source + additions = append(additions, WithSrcAddr(packet.LocalAddr())) + if p, ok := packet.(C.UDPPacketInAddr); ok { + additions = append(additions, WithInAddr(p.InAddr())) + } for _, addition := range additions { addition.Apply(metadata) } - if ip, port, err := parseAddr(packet.LocalAddr()); err == nil { - metadata.SrcIP = ip - metadata.SrcPort = port - } - if p, ok := packet.(C.UDPPacketInAddr); ok { - if ip, port, err := parseAddr(p.InAddr()); err == nil { - metadata.InIP = ip - metadata.InPort = port - } - } return &PacketAdapter{ packet, diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index d75901f1..5892bebc 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -15,19 +15,11 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Ad metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = source + additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) for _, addition := range additions { addition.Apply(metadata) } - if ip, port, err := parseAddr(conn.RemoteAddr()); err == nil { - metadata.SrcIP = ip - metadata.SrcPort = port - } - if ip, port, err := parseAddr(conn.LocalAddr()); err == nil { - metadata.InIP = ip - metadata.InPort = port - } - return context.NewConnContext(conn, metadata) } diff --git a/adapter/inbound/util.go b/adapter/inbound/util.go index 626687c0..32ca9f05 100644 --- a/adapter/inbound/util.go +++ b/adapter/inbound/util.go @@ -63,21 +63,25 @@ func parseHTTPAddr(request *http.Request) *C.Metadata { return metadata } -func parseAddr(addr net.Addr) (netip.Addr, uint16, error) { +func parseAddr(addr net.Addr) (netip.AddrPort, error) { // Filter when net.Addr interface is nil if addr == nil { - return netip.Addr{}, 0, errors.New("nil addr") + return netip.AddrPort{}, errors.New("nil addr") } if rawAddr, ok := addr.(interface{ RawAddr() net.Addr }); ok { - ip, port, err := parseAddr(rawAddr.RawAddr()) - if err == nil { - return ip, port, err + if addrPort, err := parseAddr(rawAddr.RawAddr()); err == nil { + return addrPort, nil + } + } + if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok { + if addrPort := addr.AddrPort(); addrPort.IsValid() { + return addrPort, nil } } addrStr := addr.String() host, port, err := net.SplitHostPort(addrStr) if err != nil { - return netip.Addr{}, 0, err + return netip.AddrPort{}, err } var uint16Port uint16 @@ -86,5 +90,5 @@ func parseAddr(addr net.Addr) (netip.Addr, uint16, error) { } ip, err := netip.ParseAddr(host) - return ip, uint16Port, err + return netip.AddrPortFrom(ip, uint16Port), err } diff --git a/config/config.go b/config/config.go index 5ea45a39..dd5ce59a 100644 --- a/config/config.go +++ b/config/config.go @@ -66,20 +66,21 @@ type General struct { // Inbound config type Inbound struct { - Port int `json:"port"` - SocksPort int `json:"socks-port"` - RedirPort int `json:"redir-port"` - TProxyPort int `json:"tproxy-port"` - MixedPort int `json:"mixed-port"` - Tun LC.Tun `json:"tun"` - TuicServer LC.TuicServer `json:"tuic-server"` - ShadowSocksConfig string `json:"ss-config"` - VmessConfig string `json:"vmess-config"` - Authentication []string `json:"authentication"` - AllowLan bool `json:"allow-lan"` - BindAddress string `json:"bind-address"` - InboundTfo bool `json:"inbound-tfo"` - InboundMPTCP bool `json:"inbound-mptcp"` + Port int `json:"port"` + SocksPort int `json:"socks-port"` + RedirPort int `json:"redir-port"` + TProxyPort int `json:"tproxy-port"` + MixedPort int `json:"mixed-port"` + Tun LC.Tun `json:"tun"` + TuicServer LC.TuicServer `json:"tuic-server"` + ShadowSocksConfig string `json:"ss-config"` + VmessConfig string `json:"vmess-config"` + Authentication []string `json:"authentication"` + SkipAuthPrefixes []netip.Prefix `json:"skip-auth-prefixes"` + AllowLan bool `json:"allow-lan"` + BindAddress string `json:"bind-address"` + InboundTfo bool `json:"inbound-tfo"` + InboundMPTCP bool `json:"inbound-mptcp"` } // Controller config @@ -271,6 +272,7 @@ type RawConfig struct { InboundTfo bool `yaml:"inbound-tfo"` InboundMPTCP bool `yaml:"inbound-mptcp"` Authentication []string `yaml:"authentication"` + SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes"` AllowLan bool `yaml:"allow-lan"` BindAddress string `yaml:"bind-address"` Mode T.TunnelMode `yaml:"mode"` @@ -620,6 +622,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) { ShadowSocksConfig: cfg.ShadowSocksConfig, VmessConfig: cfg.VmessConfig, AllowLan: cfg.AllowLan, + SkipAuthPrefixes: cfg.SkipAuthPrefixes, BindAddress: cfg.BindAddress, InboundTfo: cfg.InboundTfo, InboundMPTCP: cfg.InboundMPTCP, diff --git a/docs/config.yaml b/docs/config.yaml index bfcdc0cd..e829e5db 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -8,6 +8,11 @@ mixed-port: 10801 # HTTP(S) 和 SOCKS 代理混合端口 allow-lan: true # 允许局域网连接 bind-address: "*" # 绑定 IP 地址,仅作用于 allow-lan 为 true,'*'表示所有地址 +authentication: # http,socks入口的验证用户名,密码 + - "username:password" +skip-auth-prefixes: # 设置跳过验证的IP段 + - 127.0.0.1/8 + - ::1/128 # find-process-mode has 3 values:always, strict, off # - always, 开启,强制匹配所有进程 diff --git a/hub/executor/executor.go b/hub/executor/executor.go index ebcbac91..87e0e0b1 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -140,6 +140,7 @@ func GetGeneral() *config.General { ShadowSocksConfig: ports.ShadowSocksConfig, VmessConfig: ports.VmessConfig, Authentication: authenticator, + SkipAuthPrefixes: inbound.SkipAuthPrefixes(), AllowLan: listener.AllowLan(), BindAddress: listener.BindAddress(), }, @@ -164,6 +165,7 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList allowLan := general.AllowLan listener.SetAllowLan(allowLan) + inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes) bindAddress := general.BindAddress listener.SetBindAddress(bindAddress) diff --git a/hub/route/configs.go b/hub/route/configs.go index 1f29de0c..6edbf979 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -2,9 +2,11 @@ package route import ( "net/http" + "net/netip" "path/filepath" "sync" + "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/config" @@ -47,6 +49,7 @@ type configSchema struct { TcptunConfig *string `json:"tcptun-config"` UdptunConfig *string `json:"udptun-config"` AllowLan *bool `json:"allow-lan"` + SkipAuthPrefixes *[]netip.Prefix `json:"skip-auth-prefixes"` BindAddress *string `json:"bind-address"` Mode *tunnel.TunnelMode `json:"mode"` LogLevel *log.LogLevel `json:"log-level"` @@ -231,6 +234,10 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) { P.SetAllowLan(*general.AllowLan) } + if general.SkipAuthPrefixes != nil { + inbound.SetSkipAuthPrefixes(*general.SkipAuthPrefixes) + } + if general.BindAddress != nil { P.SetBindAddress(*general.BindAddress) } diff --git a/listener/http/proxy.go b/listener/http/proxy.go index a267fbad..173bb64a 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -100,6 +100,9 @@ func HandleConn(c net.Conn, tunnel C.Tunnel, cache *cache.LruCache[string, bool] func authenticate(request *http.Request, cache *cache.LruCache[string, bool]) *http.Response { authenticator := authStore.Authenticator() + if inbound.SkipAuthRemoteAddr(N.NewCustomAddr("", request.RemoteAddr, nil)) { + authenticator = nil + } if authenticator != nil { credential := parseBasicProxyAuthorization(request) if credential == "" { diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index 89b23562..9448f269 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -86,7 +86,11 @@ func handleSocks(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) } func HandleSocks4(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { - addr, _, err := socks4.ServerHandshake(conn, authStore.Authenticator()) + authenticator := authStore.Authenticator() + if inbound.SkipAuthRemoteAddr(conn.RemoteAddr()) { + authenticator = nil + } + addr, _, err := socks4.ServerHandshake(conn, authenticator) if err != nil { conn.Close() return @@ -95,7 +99,11 @@ func HandleSocks4(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) } func HandleSocks5(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { - target, command, err := socks5.ServerHandshake(conn, authStore.Authenticator()) + authenticator := authStore.Authenticator() + if inbound.SkipAuthRemoteAddr(conn.RemoteAddr()) { + authenticator = nil + } + target, command, err := socks5.ServerHandshake(conn, authenticator) if err != nil { conn.Close() return