Chore: cleanup code
This commit is contained in:
parent
e1fe8ce3b2
commit
ae6cc1d67d
@ -30,10 +30,8 @@ type LoadBalance struct {
|
||||
var errStrategy = errors.New("unsupported strategy")
|
||||
|
||||
func parseStrategy(config map[string]any) string {
|
||||
if elm, ok := config["strategy"]; ok {
|
||||
if strategy, ok := elm.(string); ok {
|
||||
return strategy
|
||||
}
|
||||
if strategy, ok := config["strategy"].(string); ok {
|
||||
return strategy
|
||||
}
|
||||
return "consistent-hashing"
|
||||
}
|
||||
|
@ -125,10 +125,8 @@ func parseURLTestOption(config map[string]any) []urlTestOption {
|
||||
opts := []urlTestOption{}
|
||||
|
||||
// tolerance
|
||||
if elm, ok := config["tolerance"]; ok {
|
||||
if tolerance, ok := elm.(int); ok {
|
||||
opts = append(opts, urlTestWithTolerance(uint16(tolerance)))
|
||||
}
|
||||
if tolerance, ok := config["tolerance"].(int); ok {
|
||||
opts = append(opts, urlTestWithTolerance(uint16(tolerance)))
|
||||
}
|
||||
|
||||
return opts
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
func ParseProxy(mapping map[string]any, forceCertVerify bool) (C.Proxy, error) {
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "proxy", WeaklyTypedInput: true})
|
||||
proxyType, existType := mapping["type"]
|
||||
proxyType, existType := mapping["type"].(string)
|
||||
if !existType {
|
||||
return nil, fmt.Errorf("missing type")
|
||||
}
|
||||
@ -19,7 +19,7 @@ func ParseProxy(mapping map[string]any, forceCertVerify bool) (C.Proxy, error) {
|
||||
proxy C.ProxyAdapter
|
||||
err error
|
||||
)
|
||||
switch proxyType.(string) {
|
||||
switch proxyType {
|
||||
case "ss":
|
||||
ssOption := &outbound.ShadowSocksOption{}
|
||||
err = decoder.Decode(mapping, ssOption)
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"crypto/md5"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
types "github.com/Dreamacro/clash/constant/provider"
|
||||
@ -14,6 +15,8 @@ import (
|
||||
var (
|
||||
fileMode os.FileMode = 0o666
|
||||
dirMode os.FileMode = 0o755
|
||||
|
||||
commentRegx = regexp.MustCompile(`(.*#.*\n)`)
|
||||
)
|
||||
|
||||
type parser[V any] func([]byte) (V, error)
|
||||
@ -168,6 +171,18 @@ func safeWrite(path string, buf []byte) error {
|
||||
return os.WriteFile(path, buf, fileMode)
|
||||
}
|
||||
|
||||
func removeComment(buf []byte) []byte {
|
||||
arr := commentRegx.FindAllSubmatch(buf, -1)
|
||||
for _, subs := range arr {
|
||||
sub := subs[0]
|
||||
if !bytes.HasPrefix(bytes.TrimLeft(sub, " "), []byte("#")) {
|
||||
continue
|
||||
}
|
||||
buf = bytes.Replace(buf, sub, []byte(""), 1)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func newFetcher[V any](name string, interval time.Duration, vehicle types.Vehicle, parser parser[V], onUpdate func(V)) *fetcher[V] {
|
||||
var ticker *time.Ticker
|
||||
if interval != 0 {
|
||||
|
@ -321,12 +321,13 @@ func proxiesParseAndFilter(filter string, filterReg *regexp.Regexp, forceCertVer
|
||||
|
||||
proxies := []C.Proxy{}
|
||||
for idx, mapping := range schema.Proxies {
|
||||
if name, ok := mapping["name"]; ok && len(filter) > 0 && !filterReg.MatchString(name.(string)) {
|
||||
name, ok := mapping["name"].(string)
|
||||
if ok && len(filter) > 0 && !filterReg.MatchString(name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if prefixName != "" {
|
||||
mapping["name"] = prefixName + mapping["name"].(string)
|
||||
mapping["name"] = prefixName + name
|
||||
}
|
||||
|
||||
proxy, err := adapter.ParseProxy(mapping, forceCertVerify)
|
||||
|
@ -103,7 +103,7 @@ func (h *HTTPVehicle) Read() ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
return removeComment(buf), nil
|
||||
}
|
||||
|
||||
func NewHTTPVehicle(url string, path string, header http.Header) *HTTPVehicle {
|
||||
|
@ -2,6 +2,7 @@ package cert
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"sync"
|
||||
|
||||
"github.com/Dreamacro/clash/component/trie"
|
||||
)
|
||||
@ -9,10 +10,14 @@ import (
|
||||
// DomainTrieCertsStorage cache wildcard certificates
|
||||
type DomainTrieCertsStorage struct {
|
||||
certsCache *trie.DomainTrie[*tls.Certificate]
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// Get gets the certificate from the storage
|
||||
func (c *DomainTrieCertsStorage) Get(key string) (*tls.Certificate, bool) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
ca := c.certsCache.Search(key)
|
||||
if ca == nil {
|
||||
return nil, false
|
||||
@ -22,7 +27,9 @@ func (c *DomainTrieCertsStorage) Get(key string) (*tls.Certificate, bool) {
|
||||
|
||||
// Set saves the certificate to the storage
|
||||
func (c *DomainTrieCertsStorage) Set(key string, cert *tls.Certificate) {
|
||||
c.lock.Lock()
|
||||
_ = c.certsCache.Insert(key, cert)
|
||||
c.lock.Unlock()
|
||||
}
|
||||
|
||||
func NewDomainTrieCertsStorage() *DomainTrieCertsStorage {
|
||||
|
@ -29,13 +29,13 @@ func bindMarkToControl(mark int, chain controlFn) controlFn {
|
||||
return
|
||||
}
|
||||
|
||||
return c.Control(func(fd uintptr) {
|
||||
switch network {
|
||||
case "tcp4", "udp4":
|
||||
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
case "tcp6", "udp6":
|
||||
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
}
|
||||
var innerErr error
|
||||
err = c.Control(func(fd uintptr) {
|
||||
innerErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
|
||||
})
|
||||
if err == nil && innerErr != nil {
|
||||
err = innerErr
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,7 @@ package process
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -23,52 +19,3 @@ const (
|
||||
func FindProcessName(network string, srcIP netip.Addr, srcPort int) (string, error) {
|
||||
return findProcessName(network, srcIP, srcPort)
|
||||
}
|
||||
|
||||
func ShouldFindProcess(metadata *C.Metadata) bool {
|
||||
if metadata.Process != "" {
|
||||
return false
|
||||
}
|
||||
if metadata.SrcIP.IsUnspecified() {
|
||||
return true
|
||||
}
|
||||
for _, ip := range localIPs {
|
||||
if ip == metadata.SrcIP {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AppendLocalIPs(ip ...netip.Addr) {
|
||||
localIPs = append(ip, localIPs...)
|
||||
}
|
||||
|
||||
func getLocalIPs() []netip.Addr {
|
||||
var ips []netip.Addr
|
||||
|
||||
netInterfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
ips = append(ips, netip.AddrFrom4([4]byte{127, 0, 0, 1}), nnip.IpToAddr(net.IPv6loopback))
|
||||
return ips
|
||||
}
|
||||
|
||||
for i := 0; i < len(netInterfaces); i++ {
|
||||
if (netInterfaces[i].Flags & net.FlagUp) != 0 {
|
||||
adds, _ := netInterfaces[i].Addrs()
|
||||
|
||||
for _, address := range adds {
|
||||
if ipNet, ok := address.(*net.IPNet); ok {
|
||||
ips = append(ips, nnip.IpToAddr(ipNet.IP))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ips
|
||||
}
|
||||
|
||||
var localIPs []netip.Addr
|
||||
|
||||
func init() {
|
||||
localIPs = getLocalIPs()
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -63,10 +61,10 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
|
||||
switch {
|
||||
case flag&0x1 > 0 && isIPv4:
|
||||
// ipv4
|
||||
srcIP = nnip.IpToAddr(buf[inp+76 : inp+80])
|
||||
srcIP, _ = netip.AddrFromSlice(buf[inp+76 : inp+80])
|
||||
case flag&0x2 > 0 && !isIPv4:
|
||||
// ipv6
|
||||
srcIP = nnip.IpToAddr(buf[inp+64 : inp+80])
|
||||
srcIP, _ = netip.AddrFromSlice(buf[inp+64 : inp+80])
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
@ -135,10 +134,10 @@ func (s *searcher) Search(buf []byte, ip netip.Addr, port uint16, isTCP bool) (u
|
||||
switch {
|
||||
case flag&0x1 > 0 && isIPv4:
|
||||
// ipv4
|
||||
srcIP = nnip.IpToAddr(buf[inp+s.ip : inp+s.ip+4])
|
||||
srcIP, _ = netip.AddrFromSlice(buf[inp+s.ip : inp+s.ip+4])
|
||||
case flag&0x2 > 0 && !isIPv4:
|
||||
// ipv6
|
||||
srcIP = nnip.IpToAddr(buf[inp+s.ip-12 : inp+s.ip+4])
|
||||
srcIP, _ = netip.AddrFromSlice(buf[inp+s.ip-12 : inp+s.ip+4])
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@ -132,7 +131,7 @@ func (s *searcher) Search(b []byte, ip netip.Addr, port uint16) (uint32, error)
|
||||
continue
|
||||
}
|
||||
|
||||
srcIP := nnip.IpToAddr(row[s.ip : s.ip+s.ipSize])
|
||||
srcIP, _ := netip.AddrFromSlice(row[s.ip : s.ip+s.ipSize])
|
||||
// windows binds an unbound udp socket to 0.0.0.0/[::] while first sendto
|
||||
if ip != srcIP && (!srcIP.IsUnspecified() || s.tcpState != -1) {
|
||||
continue
|
||||
|
@ -99,12 +99,13 @@ type Profile struct {
|
||||
|
||||
// Tun config
|
||||
type Tun struct {
|
||||
Enable bool `yaml:"enable" json:"enable"`
|
||||
Device string `yaml:"device" json:"device"`
|
||||
Stack C.TUNStack `yaml:"stack" json:"stack"`
|
||||
DNSHijack []C.DNSUrl `yaml:"dns-hijack" json:"dns-hijack"`
|
||||
AutoRoute bool `yaml:"auto-route" json:"auto-route"`
|
||||
AutoDetectInterface bool `yaml:"auto-detect-interface" json:"auto-detect-interface"`
|
||||
Enable bool `yaml:"enable" json:"enable"`
|
||||
Device string `yaml:"device" json:"device"`
|
||||
Stack C.TUNStack `yaml:"stack" json:"stack"`
|
||||
DNSHijack []C.DNSUrl `yaml:"dns-hijack" json:"dns-hijack"`
|
||||
AutoRoute bool `yaml:"auto-route" json:"auto-route"`
|
||||
AutoDetectInterface bool `yaml:"auto-detect-interface" json:"auto-detect-interface"`
|
||||
TunAddressPrefix *netip.Prefix `yaml:"_" json:"_"`
|
||||
}
|
||||
|
||||
// IPTables config
|
||||
@ -415,11 +416,11 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
||||
|
||||
// keep the original order of ProxyGroups in config file
|
||||
for idx, mapping := range groupsConfig {
|
||||
groupName, existName := mapping["name"]
|
||||
groupName, existName := mapping["name"].(string)
|
||||
if !existName {
|
||||
return nil, nil, fmt.Errorf("proxy group %d: missing name", idx)
|
||||
}
|
||||
proxyList = append(proxyList, groupName.(string))
|
||||
proxyList = append(proxyList, groupName)
|
||||
}
|
||||
|
||||
// check if any loop exists and sort the ProxyGroups
|
||||
|
@ -82,7 +82,7 @@ func ApplyConfig(cfg *config.Config, force bool) {
|
||||
updateHosts(cfg.Hosts)
|
||||
updateMitm(cfg.Mitm)
|
||||
updateProfile(cfg)
|
||||
updateDNS(cfg.DNS, cfg.General.Tun)
|
||||
updateDNS(cfg.DNS, &cfg.General.Tun)
|
||||
updateGeneral(cfg.General, force)
|
||||
updateIPTables(cfg)
|
||||
updateExperimental(cfg)
|
||||
@ -121,7 +121,7 @@ func GetGeneral() *config.General {
|
||||
|
||||
func updateExperimental(_ *config.Config) {}
|
||||
|
||||
func updateDNS(c *config.DNS, t config.Tun) {
|
||||
func updateDNS(c *config.DNS, t *config.Tun) {
|
||||
cfg := dns.Config{
|
||||
Main: c.NameServer,
|
||||
Fallback: c.Fallback,
|
||||
@ -179,7 +179,7 @@ func updateDNS(c *config.DNS, t config.Tun) {
|
||||
}
|
||||
|
||||
if cfg.Pool != nil {
|
||||
P.SetTunAddressPrefix(cfg.Pool.IPNet())
|
||||
t.TunAddressPrefix = cfg.Pool.IPNet()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
allowLan = false
|
||||
bindAddress = "*"
|
||||
lastTunConf *config.Tun
|
||||
lastTunAddressPrefix *netip.Prefix
|
||||
tunAddressPrefix *netip.Prefix
|
||||
allowLan = false
|
||||
bindAddress = "*"
|
||||
lastTunConf *config.Tun
|
||||
|
||||
socksListener *socks.Listener
|
||||
socksUDPListener *socks.UDPListener
|
||||
@ -109,10 +107,6 @@ func SetBindAddress(host string) {
|
||||
bindAddress = host
|
||||
}
|
||||
|
||||
func SetTunAddressPrefix(tunAddress *netip.Prefix) {
|
||||
tunAddressPrefix = tunAddress
|
||||
}
|
||||
|
||||
func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) {
|
||||
httpMux.Lock()
|
||||
defer httpMux.Unlock()
|
||||
@ -363,14 +357,10 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
|
||||
}
|
||||
}()
|
||||
|
||||
if tunAddressPrefix == nil {
|
||||
tunAddressPrefix = lastTunAddressPrefix
|
||||
}
|
||||
|
||||
tunConf.DNSHijack = C.RemoveDuplicateDNSUrl(tunConf.DNSHijack)
|
||||
|
||||
if tunStackListener != nil {
|
||||
if !hasTunConfigChange(tunConf, tunAddressPrefix) {
|
||||
if !hasTunConfigChange(tunConf) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -379,7 +369,6 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
|
||||
}
|
||||
|
||||
lastTunConf = tunConf
|
||||
lastTunAddressPrefix = tunAddressPrefix
|
||||
|
||||
if !tunConf.Enable {
|
||||
return
|
||||
@ -391,7 +380,7 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
|
||||
udpIn: udpIn,
|
||||
}
|
||||
|
||||
tunStackListener, err = tun.New(tunConf, tunAddressPrefix, tcpIn, udpIn, callback)
|
||||
tunStackListener, err = tun.New(tunConf, tcpIn, udpIn, callback)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -535,7 +524,7 @@ func genAddr(host string, port int, allowLan bool) string {
|
||||
return fmt.Sprintf("127.0.0.1:%d", port)
|
||||
}
|
||||
|
||||
func hasTunConfigChange(tunConf *config.Tun, tunAddressPrefix *netip.Prefix) bool {
|
||||
func hasTunConfigChange(tunConf *config.Tun) bool {
|
||||
if lastTunConf == nil {
|
||||
return true
|
||||
}
|
||||
@ -558,11 +547,11 @@ func hasTunConfigChange(tunConf *config.Tun, tunAddressPrefix *netip.Prefix) boo
|
||||
return true
|
||||
}
|
||||
|
||||
if (tunAddressPrefix != nil && lastTunAddressPrefix == nil) || (tunAddressPrefix == nil && lastTunAddressPrefix != nil) {
|
||||
if (lastTunConf.TunAddressPrefix != nil && tunConf.TunAddressPrefix == nil) || (lastTunConf.TunAddressPrefix == nil && tunConf.TunAddressPrefix != nil) {
|
||||
return true
|
||||
}
|
||||
|
||||
if tunAddressPrefix != nil && lastTunAddressPrefix != nil && *tunAddressPrefix != *lastTunAddressPrefix {
|
||||
if lastTunConf.TunAddressPrefix != nil && tunConf.TunAddressPrefix != nil && *lastTunConf.TunAddressPrefix != *tunConf.TunAddressPrefix {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,11 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if rAddr.Addr().Is4() {
|
||||
// try to unmap 4in6 address
|
||||
lAddr = netip.AddrPortFrom(lAddr.Addr().Unmap(), lAddr.Port())
|
||||
}
|
||||
handlePacketConn(in, buf[:n], lAddr, rAddr)
|
||||
}
|
||||
}()
|
||||
|
@ -41,6 +41,10 @@ func (f *FD) Name() string {
|
||||
return strconv.Itoa(f.fd)
|
||||
}
|
||||
|
||||
func (f *FD) MTU() uint32 {
|
||||
return f.mtu
|
||||
}
|
||||
|
||||
func (f *FD) Close() error {
|
||||
err := unix.Close(f.fd)
|
||||
if f.file != nil {
|
||||
|
@ -4,8 +4,48 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/Dreamacro/clash/listener/tun/device"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
func Open(name string, mtu uint32) (device.Device, error) {
|
||||
type FD struct {
|
||||
stack.LinkEndpoint
|
||||
}
|
||||
|
||||
func Open(_ string, _ uint32) (device.Device, error) {
|
||||
return nil, errors.New("not supported")
|
||||
}
|
||||
|
||||
func (f *FD) Name() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f *FD) Type() string {
|
||||
return Driver
|
||||
}
|
||||
|
||||
func (f *FD) Read(_ []byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (f *FD) Write(_ []byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (f *FD) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FD) UseEndpoint() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FD) UseIOBased() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FD) MTU() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ device.Device = (*FD)(nil)
|
||||
|
@ -59,10 +59,13 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get mtu: %w", err)
|
||||
}
|
||||
t.mtu = uint32(tunMTU)
|
||||
|
||||
if t.mtu == 0 {
|
||||
t.mtu = uint32(tunMTU)
|
||||
}
|
||||
|
||||
if t.offset > 0 {
|
||||
t.cache = make([]byte, 65535)
|
||||
t.cache = make([]byte, int(t.mtu)+t.offset)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
@ -108,6 +111,10 @@ func (t *TUN) Name() string {
|
||||
return name
|
||||
}
|
||||
|
||||
func (t *TUN) MTU() uint32 {
|
||||
return t.mtu
|
||||
}
|
||||
|
||||
func (t *TUN) UseEndpoint() error {
|
||||
ep, err := iobased.New(t, t.mtu, t.offset)
|
||||
if err != nil {
|
||||
|
@ -5,8 +5,10 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
dev "github.com/Dreamacro/clash/listener/tun/device"
|
||||
"github.com/Dreamacro/clash/listener/tun/device/fdbased"
|
||||
"github.com/Dreamacro/clash/listener/tun/device/tun"
|
||||
"github.com/Dreamacro/clash/listener/tun/ipstack/system/mars/tcpip"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
)
|
||||
|
||||
func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *UDP, error) {
|
||||
@ -19,10 +21,27 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
t dev.Device
|
||||
mtu uint32
|
||||
ok bool
|
||||
)
|
||||
if t, ok = device.(*tun.TUN); ok {
|
||||
mtu = t.MTU()
|
||||
} else if t, ok = device.(*fdbased.FD); ok {
|
||||
mtu = t.MTU()
|
||||
}
|
||||
|
||||
bufferSize := int(mtu)
|
||||
|
||||
if bufferSize == 0 {
|
||||
bufferSize = 64 * 1024
|
||||
}
|
||||
|
||||
tab := newTable()
|
||||
udp := &UDP{
|
||||
device: device,
|
||||
buf: [0xffff]byte{},
|
||||
buf: make([]byte, bufferSize),
|
||||
}
|
||||
tcp := &TCP{
|
||||
listener: listener,
|
||||
@ -38,7 +57,7 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
|
||||
_ = udp.Close()
|
||||
}()
|
||||
|
||||
buf := make([]byte, 0xffff)
|
||||
buf := make([]byte, bufferSize)
|
||||
|
||||
for {
|
||||
n, err := device.Read(buf)
|
||||
@ -133,11 +152,7 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
|
||||
continue
|
||||
}
|
||||
|
||||
port, err = tab.newConn(tup)
|
||||
if err != nil {
|
||||
log.Warnln("[STACK] drop tcp packet by system stack: %v", err)
|
||||
continue
|
||||
}
|
||||
port = tab.newConn(tup)
|
||||
}
|
||||
|
||||
ip.SetSourceIP(portal)
|
||||
@ -156,7 +171,7 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
|
||||
continue
|
||||
}
|
||||
|
||||
go udp.handleUDPPacket(ip, u)
|
||||
udp.handleUDPPacket(ip, u)
|
||||
case tcpip.ICMP:
|
||||
i := tcpip.ICMPPacket(ip.Payload())
|
||||
|
||||
|
@ -1,13 +1,9 @@
|
||||
package nat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"sync"
|
||||
|
||||
"github.com/Dreamacro/clash/common/generics/list"
|
||||
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -31,8 +27,6 @@ type table struct {
|
||||
tuples map[tuple]*list.Element[*binding]
|
||||
ports [portLength]*list.Element[*binding]
|
||||
available *list.List[*binding]
|
||||
mux sync.Mutex
|
||||
count uint16
|
||||
}
|
||||
|
||||
func (t *table) tupleOf(port uint16) tuple {
|
||||
@ -49,64 +43,27 @@ func (t *table) tupleOf(port uint16) tuple {
|
||||
}
|
||||
|
||||
func (t *table) portOf(tuple tuple) uint16 {
|
||||
t.mux.Lock()
|
||||
elm := t.tuples[tuple]
|
||||
if elm == nil {
|
||||
t.mux.Unlock()
|
||||
return 0
|
||||
}
|
||||
t.mux.Unlock()
|
||||
|
||||
t.available.MoveToFront(elm)
|
||||
|
||||
return portBegin + elm.Value.offset
|
||||
}
|
||||
|
||||
func (t *table) newConn(tuple tuple) (uint16, error) {
|
||||
t.mux.Lock()
|
||||
elm, err := t.availableConn()
|
||||
if err != nil {
|
||||
t.mux.Unlock()
|
||||
return 0, err
|
||||
}
|
||||
func (t *table) newConn(tuple tuple) uint16 {
|
||||
elm := t.available.Back()
|
||||
b := elm.Value
|
||||
|
||||
elm.Value.tuple = tuple
|
||||
delete(t.tuples, b.tuple)
|
||||
t.tuples[tuple] = elm
|
||||
t.mux.Unlock()
|
||||
b.tuple = tuple
|
||||
|
||||
return portBegin + elm.Value.offset, nil
|
||||
}
|
||||
t.available.MoveToFront(elm)
|
||||
|
||||
func (t *table) availableConn() (*list.Element[*binding], error) {
|
||||
var elm *list.Element[*binding]
|
||||
|
||||
for i := 0; i < portLength; i++ {
|
||||
elm = t.available.Back()
|
||||
t.available.MoveToFront(elm)
|
||||
|
||||
offset := elm.Value.offset
|
||||
tup := t.ports[offset].Value.tuple
|
||||
if t.tuples[tup] != nil && tup.SourceAddr.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
if t.count == portLength { // resize
|
||||
tuples := make(map[tuple]*list.Element[*binding], portLength)
|
||||
maps.Copy(tuples, t.tuples)
|
||||
t.tuples = tuples
|
||||
t.count = 1
|
||||
}
|
||||
return elm, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("too many open files, limits [%d, %d]", portLength, len(t.tuples))
|
||||
}
|
||||
|
||||
func (t *table) closeConn(tuple tuple) {
|
||||
t.mux.Lock()
|
||||
delete(t.tuples, tuple)
|
||||
t.count++
|
||||
t.mux.Unlock()
|
||||
return portBegin + b.offset
|
||||
}
|
||||
|
||||
func newTable() *table {
|
||||
@ -114,7 +71,6 @@ func newTable() *table {
|
||||
tuples: make(map[tuple]*list.Element[*binding], portLength),
|
||||
ports: [portLength]*list.Element[*binding]{},
|
||||
available: list.New[*binding](),
|
||||
count: 1,
|
||||
}
|
||||
|
||||
for idx := range result.ports {
|
||||
|
@ -16,8 +16,6 @@ type conn struct {
|
||||
net.Conn
|
||||
|
||||
tuple tuple
|
||||
|
||||
close func()
|
||||
}
|
||||
|
||||
func (t *TCP) Accept() (net.Conn, error) {
|
||||
@ -41,9 +39,6 @@ func (t *TCP) Accept() (net.Conn, error) {
|
||||
return &conn{
|
||||
Conn: c,
|
||||
tuple: tup,
|
||||
close: func() {
|
||||
t.table.closeConn(tup)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -60,7 +55,6 @@ func (t *TCP) SetDeadline(time time.Time) error {
|
||||
}
|
||||
|
||||
func (c *conn) Close() error {
|
||||
c.close()
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ type UDP struct {
|
||||
queueLock sync.Mutex
|
||||
queue []*call
|
||||
bufLock sync.Mutex
|
||||
buf [0xffff]byte
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (u *UDP) ReadFrom(buf []byte) (int, netip.AddrPort, netip.AddrPort, error) {
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/inbound"
|
||||
"github.com/Dreamacro/clash/common/cmd"
|
||||
"github.com/Dreamacro/clash/component/process"
|
||||
"github.com/Dreamacro/clash/config"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/listener/tun/device"
|
||||
@ -24,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
// New TunAdapter
|
||||
func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter, tunChangeCallback C.TUNChangeCallback) (ipstack.Stack, error) {
|
||||
func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter, tunChangeCallback C.TUNChangeCallback) (ipstack.Stack, error) {
|
||||
var (
|
||||
tunAddress = netip.Prefix{}
|
||||
devName = tunConf.Device
|
||||
@ -48,16 +47,14 @@ func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.Con
|
||||
devName = generateDeviceName()
|
||||
}
|
||||
|
||||
if tunAddressPrefix != nil {
|
||||
tunAddress = *tunAddressPrefix
|
||||
if tunConf.TunAddressPrefix != nil {
|
||||
tunAddress = *tunConf.TunAddressPrefix
|
||||
}
|
||||
|
||||
if !tunAddress.IsValid() || !tunAddress.Addr().Is4() {
|
||||
tunAddress = netip.MustParsePrefix("198.18.0.1/16")
|
||||
}
|
||||
|
||||
process.AppendLocalIPs(tunAddress.Masked().Addr().Next())
|
||||
|
||||
// open tun device
|
||||
tunDevice, err = parseDevice(devName, uint32(mtu))
|
||||
if err != nil {
|
||||
|
@ -394,7 +394,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
||||
resolved = true
|
||||
}
|
||||
|
||||
if !processFound && rule.ShouldFindProcess() && P.ShouldFindProcess(metadata) {
|
||||
if !processFound && rule.ShouldFindProcess() {
|
||||
processFound = true
|
||||
|
||||
srcPort, err := strconv.ParseUint(metadata.SrcPort, 10, 16)
|
||||
|
Reference in New Issue
Block a user