feat: add skip-auth-prefixes

This commit is contained in:
wwqgtxx 2023-10-10 19:43:26 +08:00
parent 7ed25ddc74
commit 6bcd91a801
13 changed files with 110 additions and 61 deletions

View file

@ -38,9 +38,27 @@ func WithSpecialProxy(specialProxy string) Addition {
func WithSrcAddr(addr net.Addr) Addition { func WithSrcAddr(addr net.Addr) Addition {
return func(metadata *C.Metadata) { return func(metadata *C.Metadata) {
if ip, port, err := parseAddr(addr); err == nil { if addrPort, err := parseAddr(addr); err == nil {
metadata.SrcIP = ip metadata.SrcIP = addrPort.Addr()
metadata.SrcPort = port 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()
} }
} }
} }

27
adapter/inbound/auth.go Normal file
View file

@ -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
}

View file

@ -13,16 +13,9 @@ func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Ad
metadata := parseSocksAddr(target) metadata := parseSocksAddr(target)
metadata.NetWork = C.TCP metadata.NetWork = C.TCP
metadata.Type = C.HTTP metadata.Type = C.HTTP
additions = append(additions, WithSrcAddr(source), WithInAddr(conn.LocalAddr()))
for _, addition := range additions { for _, addition := range additions {
addition.Apply(metadata) 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) return context.NewConnContext(conn, metadata)
} }

View file

@ -12,16 +12,9 @@ import (
func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) *context.ConnContext { func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) *context.ConnContext {
metadata := parseHTTPAddr(request) metadata := parseHTTPAddr(request)
metadata.Type = C.HTTPS metadata.Type = C.HTTPS
additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr()))
for _, addition := range additions { for _, addition := range additions {
addition.Apply(metadata) 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) return context.NewConnContext(conn, metadata)
} }

View file

@ -21,19 +21,13 @@ func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions
metadata := parseSocksAddr(target) metadata := parseSocksAddr(target)
metadata.NetWork = C.UDP metadata.NetWork = C.UDP
metadata.Type = source 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 { for _, addition := range additions {
addition.Apply(metadata) 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{ return &PacketAdapter{
packet, packet,

View file

@ -15,19 +15,11 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Ad
metadata := parseSocksAddr(target) metadata := parseSocksAddr(target)
metadata.NetWork = C.TCP metadata.NetWork = C.TCP
metadata.Type = source metadata.Type = source
additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr()))
for _, addition := range additions { for _, addition := range additions {
addition.Apply(metadata) 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) return context.NewConnContext(conn, metadata)
} }

View file

@ -63,21 +63,25 @@ func parseHTTPAddr(request *http.Request) *C.Metadata {
return 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 // Filter when net.Addr interface is nil
if addr == 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 { if rawAddr, ok := addr.(interface{ RawAddr() net.Addr }); ok {
ip, port, err := parseAddr(rawAddr.RawAddr()) if addrPort, err := parseAddr(rawAddr.RawAddr()); err == nil {
if err == nil { return addrPort, nil
return ip, port, err }
}
if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok {
if addrPort := addr.AddrPort(); addrPort.IsValid() {
return addrPort, nil
} }
} }
addrStr := addr.String() addrStr := addr.String()
host, port, err := net.SplitHostPort(addrStr) host, port, err := net.SplitHostPort(addrStr)
if err != nil { if err != nil {
return netip.Addr{}, 0, err return netip.AddrPort{}, err
} }
var uint16Port uint16 var uint16Port uint16
@ -86,5 +90,5 @@ func parseAddr(addr net.Addr) (netip.Addr, uint16, error) {
} }
ip, err := netip.ParseAddr(host) ip, err := netip.ParseAddr(host)
return ip, uint16Port, err return netip.AddrPortFrom(ip, uint16Port), err
} }

View file

@ -76,6 +76,7 @@ type Inbound struct {
ShadowSocksConfig string `json:"ss-config"` ShadowSocksConfig string `json:"ss-config"`
VmessConfig string `json:"vmess-config"` VmessConfig string `json:"vmess-config"`
Authentication []string `json:"authentication"` Authentication []string `json:"authentication"`
SkipAuthPrefixes []netip.Prefix `json:"skip-auth-prefixes"`
AllowLan bool `json:"allow-lan"` AllowLan bool `json:"allow-lan"`
BindAddress string `json:"bind-address"` BindAddress string `json:"bind-address"`
InboundTfo bool `json:"inbound-tfo"` InboundTfo bool `json:"inbound-tfo"`
@ -271,6 +272,7 @@ type RawConfig struct {
InboundTfo bool `yaml:"inbound-tfo"` InboundTfo bool `yaml:"inbound-tfo"`
InboundMPTCP bool `yaml:"inbound-mptcp"` InboundMPTCP bool `yaml:"inbound-mptcp"`
Authentication []string `yaml:"authentication"` Authentication []string `yaml:"authentication"`
SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes"`
AllowLan bool `yaml:"allow-lan"` AllowLan bool `yaml:"allow-lan"`
BindAddress string `yaml:"bind-address"` BindAddress string `yaml:"bind-address"`
Mode T.TunnelMode `yaml:"mode"` Mode T.TunnelMode `yaml:"mode"`
@ -620,6 +622,7 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
ShadowSocksConfig: cfg.ShadowSocksConfig, ShadowSocksConfig: cfg.ShadowSocksConfig,
VmessConfig: cfg.VmessConfig, VmessConfig: cfg.VmessConfig,
AllowLan: cfg.AllowLan, AllowLan: cfg.AllowLan,
SkipAuthPrefixes: cfg.SkipAuthPrefixes,
BindAddress: cfg.BindAddress, BindAddress: cfg.BindAddress,
InboundTfo: cfg.InboundTfo, InboundTfo: cfg.InboundTfo,
InboundMPTCP: cfg.InboundMPTCP, InboundMPTCP: cfg.InboundMPTCP,

View file

@ -8,6 +8,11 @@ mixed-port: 10801 # HTTP(S) 和 SOCKS 代理混合端口
allow-lan: true # 允许局域网连接 allow-lan: true # 允许局域网连接
bind-address: "*" # 绑定 IP 地址,仅作用于 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 # find-process-mode has 3 values:always, strict, off
# - always, 开启,强制匹配所有进程 # - always, 开启,强制匹配所有进程

View file

@ -140,6 +140,7 @@ func GetGeneral() *config.General {
ShadowSocksConfig: ports.ShadowSocksConfig, ShadowSocksConfig: ports.ShadowSocksConfig,
VmessConfig: ports.VmessConfig, VmessConfig: ports.VmessConfig,
Authentication: authenticator, Authentication: authenticator,
SkipAuthPrefixes: inbound.SkipAuthPrefixes(),
AllowLan: listener.AllowLan(), AllowLan: listener.AllowLan(),
BindAddress: listener.BindAddress(), BindAddress: listener.BindAddress(),
}, },
@ -164,6 +165,7 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList
allowLan := general.AllowLan allowLan := general.AllowLan
listener.SetAllowLan(allowLan) listener.SetAllowLan(allowLan)
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
bindAddress := general.BindAddress bindAddress := general.BindAddress
listener.SetBindAddress(bindAddress) listener.SetBindAddress(bindAddress)

View file

@ -2,9 +2,11 @@ package route
import ( import (
"net/http" "net/http"
"net/netip"
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/Dreamacro/clash/adapter/inbound"
"github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/component/resolver"
"github.com/Dreamacro/clash/config" "github.com/Dreamacro/clash/config"
@ -47,6 +49,7 @@ type configSchema struct {
TcptunConfig *string `json:"tcptun-config"` TcptunConfig *string `json:"tcptun-config"`
UdptunConfig *string `json:"udptun-config"` UdptunConfig *string `json:"udptun-config"`
AllowLan *bool `json:"allow-lan"` AllowLan *bool `json:"allow-lan"`
SkipAuthPrefixes *[]netip.Prefix `json:"skip-auth-prefixes"`
BindAddress *string `json:"bind-address"` BindAddress *string `json:"bind-address"`
Mode *tunnel.TunnelMode `json:"mode"` Mode *tunnel.TunnelMode `json:"mode"`
LogLevel *log.LogLevel `json:"log-level"` LogLevel *log.LogLevel `json:"log-level"`
@ -231,6 +234,10 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
P.SetAllowLan(*general.AllowLan) P.SetAllowLan(*general.AllowLan)
} }
if general.SkipAuthPrefixes != nil {
inbound.SetSkipAuthPrefixes(*general.SkipAuthPrefixes)
}
if general.BindAddress != nil { if general.BindAddress != nil {
P.SetBindAddress(*general.BindAddress) P.SetBindAddress(*general.BindAddress)
} }

View file

@ -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 { func authenticate(request *http.Request, cache *cache.LruCache[string, bool]) *http.Response {
authenticator := authStore.Authenticator() authenticator := authStore.Authenticator()
if inbound.SkipAuthRemoteAddr(N.NewCustomAddr("", request.RemoteAddr, nil)) {
authenticator = nil
}
if authenticator != nil { if authenticator != nil {
credential := parseBasicProxyAuthorization(request) credential := parseBasicProxyAuthorization(request)
if credential == "" { if credential == "" {

View file

@ -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) { 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 { if err != nil {
conn.Close() conn.Close()
return 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) { 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 { if err != nil {
conn.Close() conn.Close()
return return