github.com/yaling888/clash@v1.53.0/listener/listener.go (about) 1 package listener 2 3 import ( 4 "fmt" 5 "net" 6 "reflect" 7 "strconv" 8 "strings" 9 "sync" 10 11 "github.com/phuslu/log" 12 "github.com/samber/lo" 13 14 "github.com/yaling888/clash/adapter/inbound" 15 "github.com/yaling888/clash/component/dialer" 16 "github.com/yaling888/clash/component/ebpf" 17 "github.com/yaling888/clash/component/iface" 18 "github.com/yaling888/clash/config" 19 C "github.com/yaling888/clash/constant" 20 A "github.com/yaling888/clash/listener/auth" 21 "github.com/yaling888/clash/listener/autoredir" 22 "github.com/yaling888/clash/listener/http" 23 "github.com/yaling888/clash/listener/mitm" 24 "github.com/yaling888/clash/listener/mixed" 25 "github.com/yaling888/clash/listener/redir" 26 "github.com/yaling888/clash/listener/socks" 27 "github.com/yaling888/clash/listener/tproxy" 28 "github.com/yaling888/clash/listener/tun" 29 "github.com/yaling888/clash/listener/tun/ipstack" 30 "github.com/yaling888/clash/listener/tun/ipstack/commons" 31 "github.com/yaling888/clash/listener/tunnel" 32 "github.com/yaling888/clash/tunnel/statistic" 33 ) 34 35 var ( 36 allowLan = false 37 bindAddress = "*" 38 39 tcpInbounds = map[string]C.Inbound{} 40 udpInbounds = map[string]C.Inbound{} 41 tcpListeners = map[string]C.Listener{} 42 udpListeners = map[string]C.Listener{} 43 44 tunStackListener ipstack.Stack 45 tcProgram *ebpf.TcEBpfProgram 46 autoRedirListener *autoredir.Listener 47 autoRedirProgram *ebpf.TcEBpfProgram 48 49 tunnelTCPListeners = map[string]*tunnel.Listener{} 50 tunnelUDPListeners = map[string]*tunnel.PacketConn{} 51 52 // lock for recreate function 53 inboundsMux sync.Mutex 54 tunMux sync.Mutex 55 tcMux sync.Mutex 56 autoRedirMux sync.Mutex 57 tunnelMux sync.Mutex 58 ) 59 60 var tcpListenerCreators = map[C.InboundType]tcpListenerCreator{ 61 C.InboundTypeHTTP: http.New, 62 C.InboundTypeSocks: socks.New, 63 C.InboundTypeSocks4: socks.New4, 64 C.InboundTypeSocks5: socks.New5, 65 C.InboundTypeRedir: redir.New, 66 C.InboundTypeTproxy: tproxy.New, 67 C.InboundTypeMixed: mixed.New, 68 C.InboundTypeMitm: mitm.New, 69 } 70 71 var udpListenerCreators = map[C.InboundType]udpListenerCreator{ 72 C.InboundTypeSocks: socks.NewUDP, 73 C.InboundTypeSocks5: socks.NewUDP, 74 C.InboundTypeRedir: tproxy.NewUDP, 75 C.InboundTypeTproxy: tproxy.NewUDP, 76 C.InboundTypeMixed: socks.NewUDP, 77 } 78 79 type ( 80 tcpListenerCreator func(addr string, tcpIn chan<- C.ConnContext) (C.Listener, error) 81 udpListenerCreator func(addr string, udpIn chan<- *inbound.PacketAdapter) (C.Listener, error) 82 ) 83 84 type Ports struct { 85 Port int `json:"port"` 86 SocksPort int `json:"socks-port"` 87 RedirPort int `json:"redir-port"` 88 TProxyPort int `json:"tproxy-port"` 89 MixedPort int `json:"mixed-port"` 90 MitmPort int `json:"mitm-port"` 91 } 92 93 func AllowLan() bool { 94 return allowLan 95 } 96 97 func BindAddress() string { 98 return bindAddress 99 } 100 101 func SetAllowLan(al bool) { 102 allowLan = al 103 } 104 105 func SetBindAddress(host string) { 106 bindAddress = host 107 } 108 109 func createListener(inbound C.Inbound, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 110 addr := inbound.BindAddress 111 if portIsZero(addr) { 112 log.Error().Str("addr", addr).Msgf("[Inbound] invalid %s address", inbound.Type) 113 return 114 } 115 116 inboundKey := inbound.Key() 117 tcpCreator := tcpListenerCreators[inbound.Type] 118 udpCreator := udpListenerCreators[inbound.Type] 119 120 if tcpCreator == nil && udpCreator == nil { 121 log.Error().Str("addr", addr).Msgf("[Inbound] server type %s is not supported", inbound.Type) 122 return 123 } 124 125 au := "none" 126 auLen := len(lo.FromPtr(inbound.Authentication)) 127 if auLen != 0 { 128 au = "local" 129 } else if A.Authenticator() != nil { 130 au = "global" 131 } 132 if inbound.Type == C.InboundTypeRedir || inbound.Type == C.InboundTypeTproxy { 133 au = "none" 134 } 135 136 if tcpCreator != nil { 137 tcpListener, err := tcpCreator(addr, tcpIn) 138 if err != nil { 139 log.Error().Err(err).Str("addr", addr).Msgf("[Inbound] %s tcp server start failed", inbound.Type) 140 return 141 } 142 143 if !inbound.IsFromPortCfg && auLen != 0 { 144 if tl, ok := tcpListener.(C.AuthenticatorListener); ok { 145 authUsers := config.ParseAuthentication(*inbound.Authentication) 146 tl.SetAuthenticator(authUsers) 147 } 148 } 149 150 tcpInbounds[inboundKey] = inbound 151 tcpListeners[inboundKey] = tcpListener 152 153 log.Info(). 154 Str("addr", addr). 155 Str("network", "tcp"). 156 Str("auth", au). 157 Msgf("[Inbound] %s proxy listening", inbound.Type) 158 } 159 160 if udpCreator != nil { 161 udpListener, err := udpCreator(addr, udpIn) 162 if err != nil { 163 log.Error().Err(err).Str("addr", addr).Msgf("[Inbound] %s udp server start failed", inbound.Type) 164 return 165 } 166 167 udpInbounds[inboundKey] = inbound 168 udpListeners[inboundKey] = udpListener 169 170 log.Info(). 171 Str("addr", addr). 172 Str("network", "udp"). 173 Str("auth", au). 174 Msgf("[Inbound] %s proxy listening", inbound.Type) 175 } 176 } 177 178 func closeListener(inbound C.Inbound) { 179 inboundKey := inbound.Key() 180 listener := tcpListeners[inboundKey] 181 if listener != nil { 182 if err := listener.Close(); err != nil { 183 log.Error().Err(err).Msgf("[Inbound] close tcp server `%s` failed", inbound.ToAlias()) 184 } 185 delete(tcpInbounds, inboundKey) 186 delete(tcpListeners, inboundKey) 187 log.Info(). 188 Str("addr", inbound.BindAddress). 189 Str("network", "tcp"). 190 Msgf("[Inbound] %s proxy is down", inbound.Type) 191 } 192 listener = udpListeners[inboundKey] 193 if listener != nil { 194 if err := listener.Close(); err != nil { 195 log.Error().Err(err).Msgf("[Inbound] close udp server `%s` failed", inbound.ToAlias()) 196 } 197 delete(udpInbounds, inboundKey) 198 delete(udpListeners, inboundKey) 199 log.Info(). 200 Str("addr", inbound.BindAddress). 201 Str("network", "udp"). 202 Msgf("[Inbound] %s proxy is down", inbound.Type) 203 } 204 } 205 206 func getNeedCloseAndCreateInbound(originInbounds []C.Inbound, newInbounds []C.Inbound) ([]C.Inbound, []C.Inbound) { 207 var ( 208 needClose []C.Inbound 209 needCreate []C.Inbound 210 needCloseMap = make(map[string]C.Inbound) 211 ) 212 for _, m := range originInbounds { 213 needCloseMap[m.Key()] = m 214 } 215 for _, m := range newInbounds { 216 key := m.Key() 217 if c, ok := needCloseMap[key]; ok { 218 if !reflect.DeepEqual(m.Authentication, c.Authentication) { 219 needCreate = append(needCreate, m) 220 } else { 221 delete(needCloseMap, key) 222 } 223 } else { 224 needCreate = append(needCreate, m) 225 } 226 } 227 for _, m := range needCloseMap { 228 needClose = append(needClose, m) 229 } 230 return needClose, needCreate 231 } 232 233 // ReCreateListeners only recreate inbound config listener 234 func ReCreateListeners(inbounds []C.Inbound, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 235 inboundsMux.Lock() 236 defer inboundsMux.Unlock() 237 newInbounds := append([]C.Inbound{}, inbounds...) 238 for _, m := range getInbounds() { 239 if m.IsFromPortCfg { 240 newInbounds = append(newInbounds, m) 241 } 242 } 243 reCreateListeners(newInbounds, tcpIn, udpIn) 244 } 245 246 // ReCreatePortsListeners only recreate ports config listener 247 func ReCreatePortsListeners(ports Ports, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 248 inboundsMux.Lock() 249 defer inboundsMux.Unlock() 250 newInbounds := addPortInbound([]C.Inbound{}, C.InboundTypeHTTP, ports.Port) 251 newInbounds = addPortInbound(newInbounds, C.InboundTypeSocks, ports.SocksPort) 252 newInbounds = addPortInbound(newInbounds, C.InboundTypeRedir, ports.RedirPort) 253 newInbounds = addPortInbound(newInbounds, C.InboundTypeTproxy, ports.TProxyPort) 254 newInbounds = addPortInbound(newInbounds, C.InboundTypeMixed, ports.MixedPort) 255 newInbounds = addPortInbound(newInbounds, C.InboundTypeMitm, ports.MitmPort) 256 newInbounds = append(newInbounds, GetInbounds()...) 257 reCreateListeners(newInbounds, tcpIn, udpIn) 258 } 259 260 func addPortInbound(inbounds []C.Inbound, inboundType C.InboundType, port int) []C.Inbound { 261 if port != 0 { 262 inbounds = append(inbounds, C.Inbound{ 263 Type: inboundType, 264 BindAddress: genAddr(bindAddress, port, allowLan), 265 IsFromPortCfg: true, 266 }) 267 } 268 return inbounds 269 } 270 271 func reCreateListeners(inbounds []C.Inbound, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 272 needClose, needCreate := getNeedCloseAndCreateInbound(getInbounds(), inbounds) 273 for _, m := range needClose { 274 closeListener(m) 275 } 276 for _, m := range needCreate { 277 createListener(m, tcpIn, udpIn) 278 } 279 C.SetProxyInbound(tcpInbounds) 280 } 281 282 func ReCreateTun(tunConf *C.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 283 tunMux.Lock() 284 defer tunMux.Unlock() 285 286 if C.IsNoGVisor { 287 tunConf.Stack = C.TunSystem 288 } 289 290 tunConf.DNSHijack = lo.UniqBy(tunConf.DNSHijack, func(item C.DNSUrl) string { 291 return item.String() 292 }) 293 294 if tunStackListener != nil { 295 if !hasTunConfigChange(tunConf) { 296 return 297 } 298 299 if tunConf.StopRouteListener && !tunConf.Enable { 300 commons.SetTunStatus(C.TunDisabled) 301 } 302 303 _ = tunStackListener.Close() 304 tunStackListener = nil 305 } 306 307 C.SetLastTunConf(tunConf) 308 309 if !tunConf.Enable { 310 return 311 } 312 313 callback := &tunChangeCallback{ 314 tunConf: *tunConf, 315 tcpIn: tcpIn, 316 udpIn: udpIn, 317 } 318 319 if tunConf.AutoDetectInterface { 320 outboundInterface, err := commons.GetAutoDetectInterface() 321 if err != nil { 322 log.Info().Err(err).Msg("[Tun] auto detect interface failed") 323 } 324 if outboundInterface != "" && outboundInterface != dialer.DefaultInterface.Load() { 325 dialer.DefaultInterface.Store(outboundInterface) 326 iface.FlushCache() 327 commons.UpdateWireGuardBind() 328 log.Info(). 329 Str("name", outboundInterface). 330 Msg("[TUN] default interface has overwrite by auto detect interface") 331 } 332 } 333 334 var err error 335 tunStackListener, err = tun.New(tunConf, tcpIn, udpIn, callback) 336 if err != nil { 337 log.Error().Err(err).Msg("[Inbound] tun server start failed") 338 } 339 } 340 341 func ReCreateRedirToTun(ifaceNames []string) { 342 tcMux.Lock() 343 defer tcMux.Unlock() 344 345 nicArr := lo.Uniq(ifaceNames) 346 347 if tcProgram != nil { 348 tcProgram.Close() 349 tcProgram = nil 350 } 351 352 if len(nicArr) == 0 { 353 return 354 } 355 356 lastTunConf := C.GetLastTunConf() 357 if lastTunConf == nil || !lastTunConf.Enable { 358 return 359 } 360 361 program, err := ebpf.NewTcEBpfProgram(nicArr, lastTunConf.Device) 362 if err != nil { 363 log.Error().Err(err).Msg("[Inbound] attach tc ebpf program failed") 364 return 365 } 366 tcProgram = program 367 368 log.Info().Strs("interfaces", tcProgram.RawNICs()).Msg("[Inbound] attached tc ebpf program") 369 } 370 371 func ReCreateAutoRedir(ifaceNames []string, defaultInterface string, tcpIn chan<- C.ConnContext, _ chan<- *inbound.PacketAdapter) { 372 autoRedirMux.Lock() 373 defer autoRedirMux.Unlock() 374 375 var err error 376 defer func(err error) { 377 if err != nil { 378 if autoRedirListener != nil { 379 _ = autoRedirListener.Close() 380 autoRedirListener = nil 381 } 382 if autoRedirProgram != nil { 383 autoRedirProgram.Close() 384 autoRedirProgram = nil 385 } 386 log.Error().Err(err).Msg("[Inbound] auto redirect server start failed") 387 } 388 }(err) 389 390 nicArr := lo.Uniq(ifaceNames) 391 defaultRouteInterfaceName := defaultInterface 392 393 if autoRedirListener != nil && autoRedirProgram != nil { 394 if defaultRouteInterfaceName == "" { 395 defaultRouteInterfaceName, _ = commons.GetAutoDetectInterface() 396 } 397 if autoRedirProgram.RawInterface() == defaultRouteInterfaceName && 398 len(autoRedirProgram.RawNICs()) == len(nicArr) && 399 lo.Every(autoRedirProgram.RawNICs(), nicArr) { 400 return 401 } 402 _ = autoRedirListener.Close() 403 autoRedirProgram.Close() 404 autoRedirListener = nil 405 autoRedirProgram = nil 406 } 407 408 if len(nicArr) == 0 { 409 return 410 } 411 412 if defaultRouteInterfaceName == "" { 413 defaultRouteInterfaceName, err = commons.GetAutoDetectInterface() 414 if err != nil { 415 return 416 } 417 } 418 419 addr := genAddr("*", C.TcpAutoRedirPort, true) 420 421 autoRedirListener, err = autoredir.New(addr, tcpIn) 422 if err != nil { 423 return 424 } 425 426 autoRedirProgram, err = ebpf.NewRedirEBpfProgram(nicArr, autoRedirListener.TCPAddr().Port(), 427 defaultRouteInterfaceName) 428 if err != nil { 429 return 430 } 431 432 autoRedirListener.SetLookupFunc(autoRedirProgram.Lookup) 433 434 log.Info(). 435 Str("addr", autoRedirListener.Address()). 436 Strs("interfaces", autoRedirProgram.RawNICs()). 437 Msg("[Inbound] auto redirect proxy listening, attached tc ebpf program") 438 } 439 440 func PatchTunnel(tunnels []config.Tunnel, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) { 441 tunnelMux.Lock() 442 defer tunnelMux.Unlock() 443 444 type addrProxy struct { 445 network string 446 addr string 447 target string 448 proxy string 449 } 450 451 tcpOld := lo.Map( 452 lo.Keys(tunnelTCPListeners), 453 func(key string, _ int) addrProxy { 454 parts := strings.Split(key, "/") 455 return addrProxy{ 456 network: "tcp", 457 addr: parts[0], 458 target: parts[1], 459 proxy: parts[2], 460 } 461 }, 462 ) 463 udpOld := lo.Map( 464 lo.Keys(tunnelUDPListeners), 465 func(key string, _ int) addrProxy { 466 parts := strings.Split(key, "/") 467 return addrProxy{ 468 network: "udp", 469 addr: parts[0], 470 target: parts[1], 471 proxy: parts[2], 472 } 473 }, 474 ) 475 oldElm := lo.Union(tcpOld, udpOld) 476 477 newElm := lo.FlatMap( 478 tunnels, 479 func(tunnel config.Tunnel, _ int) []addrProxy { 480 return lo.Map( 481 tunnel.Network, 482 func(network string, _ int) addrProxy { 483 return addrProxy{ 484 network: network, 485 addr: tunnel.Address, 486 target: tunnel.Target, 487 proxy: tunnel.Proxy, 488 } 489 }, 490 ) 491 }, 492 ) 493 494 needClose, needCreate := lo.Difference(oldElm, newElm) 495 496 for _, elm := range needClose { 497 key := fmt.Sprintf("%s/%s/%s", elm.addr, elm.target, elm.proxy) 498 if elm.network == "tcp" { 499 _ = tunnelTCPListeners[key].Close() 500 delete(tunnelTCPListeners, key) 501 } else { 502 _ = tunnelUDPListeners[key].Close() 503 delete(tunnelUDPListeners, key) 504 } 505 } 506 507 for _, elm := range needCreate { 508 key := fmt.Sprintf("%s/%s/%s", elm.addr, elm.target, elm.proxy) 509 if elm.network == "tcp" { 510 l, err := tunnel.New(elm.addr, elm.target, elm.proxy, tcpIn) 511 if err != nil { 512 log.Error().Err(err).Str("target", elm.target).Msg("[Inbound] tunnel server start failed") 513 continue 514 } 515 tunnelTCPListeners[key] = l 516 log.Info(). 517 Str("addr", tunnelTCPListeners[key].Address()). 518 Str("network", elm.network). 519 Str("target", elm.target). 520 Str("proxy", elm.proxy). 521 Msg("[Inbound] tunnel proxy listening") 522 } else { 523 l, err := tunnel.NewUDP(elm.addr, elm.target, elm.proxy, udpIn) 524 if err != nil { 525 log.Error().Err(err).Str("target", elm.target).Msg("[Inbound] tunnel server start failed") 526 continue 527 } 528 tunnelUDPListeners[key] = l 529 log.Info(). 530 Str("addr", tunnelUDPListeners[key].Address()). 531 Str("network", elm.network). 532 Str("target", elm.target). 533 Str("proxy", elm.proxy). 534 Msg("[Inbound] tunnel proxy listening") 535 } 536 } 537 } 538 539 func GetInbounds() []C.Inbound { 540 return lo.Filter(getInbounds(), func(inbound C.Inbound, _ int) bool { 541 return !inbound.IsFromPortCfg 542 }) 543 } 544 545 // GetInbounds return inbounds of proxy servers 546 func getInbounds() []C.Inbound { 547 var inbounds []C.Inbound 548 for _, tcp := range tcpInbounds { 549 inbounds = append(inbounds, tcp) 550 } 551 for _, udp := range udpInbounds { 552 if _, ok := tcpInbounds[udp.Key()]; !ok { 553 inbounds = append(inbounds, udp) 554 } 555 } 556 return inbounds 557 } 558 559 // GetPorts return the ports of proxy servers 560 func GetPorts() *Ports { 561 ports := &Ports{} 562 for _, m := range getInbounds() { 563 fillPort(m, ports) 564 } 565 return ports 566 } 567 568 func fillPort(inbound C.Inbound, ports *Ports) { 569 if inbound.IsFromPortCfg { 570 port := getPort(inbound.BindAddress) 571 switch inbound.Type { 572 case C.InboundTypeHTTP: 573 ports.Port = port 574 case C.InboundTypeSocks: 575 ports.SocksPort = port 576 case C.InboundTypeTproxy: 577 ports.TProxyPort = port 578 case C.InboundTypeRedir: 579 ports.RedirPort = port 580 case C.InboundTypeMixed: 581 ports.MixedPort = port 582 case C.InboundTypeMitm: 583 ports.MitmPort = port 584 default: 585 // do nothing 586 } 587 } 588 } 589 590 func portIsZero(addr string) bool { 591 _, port, err := net.SplitHostPort(addr) 592 if port == "0" || port == "" || err != nil { 593 return true 594 } 595 return false 596 } 597 598 func genAddr(host string, port int, allowLan bool) string { 599 if allowLan { 600 if host == "*" { 601 return fmt.Sprintf(":%d", port) 602 } 603 return fmt.Sprintf("%s:%d", host, port) 604 } 605 606 return fmt.Sprintf("127.0.0.1:%d", port) 607 } 608 609 func getPort(addr string) int { 610 _, portStr, err := net.SplitHostPort(addr) 611 if err != nil { 612 return 0 613 } 614 port, err := strconv.ParseUint(portStr, 10, 16) 615 if err != nil { 616 return 0 617 } 618 return int(port) 619 } 620 621 func hasTunConfigChange(tunConf *C.Tun) bool { 622 lastTunConf := C.GetLastTunConf() 623 if lastTunConf == nil { 624 return true 625 } 626 627 if lastTunConf.Enable != tunConf.Enable || 628 lastTunConf.Stack != tunConf.Stack || 629 !lo.Every(lastTunConf.DNSHijack, tunConf.DNSHijack) || 630 lastTunConf.AutoRoute != tunConf.AutoRoute || 631 lastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface || 632 !reflect.DeepEqual(lastTunConf.TunAddressPrefix, tunConf.TunAddressPrefix) { 633 return true 634 } 635 636 return false 637 } 638 639 type tunChangeCallback struct { 640 tunConf C.Tun 641 tcpIn chan<- C.ConnContext 642 udpIn chan<- *inbound.PacketAdapter 643 } 644 645 func (t *tunChangeCallback) Pause() { 646 conf := t.tunConf 647 conf.Enable = false 648 conf.StopRouteListener = false 649 ReCreateTun(&conf, t.tcpIn, t.udpIn) 650 ReCreateRedirToTun([]string{}) 651 } 652 653 func (t *tunChangeCallback) Resume() { 654 conf := t.tunConf 655 conf.Enable = true 656 conf.StopRouteListener = false 657 ReCreateTun(&conf, t.tcpIn, t.udpIn) 658 ReCreateRedirToTun(conf.RedirectToTun) 659 statistic.DefaultManager.Cleanup() 660 } 661 662 func Cleanup() { 663 if tcProgram != nil { 664 tcProgram.Close() 665 } 666 if autoRedirProgram != nil { 667 autoRedirProgram.Close() 668 } 669 if tunStackListener != nil { 670 commons.SetTunStatus(C.TunDisabled) 671 _ = tunStackListener.Close() 672 } 673 }