github.com/kelleygo/clashcore@v1.0.2/tunnel/connection.go (about) 1 package tunnel 2 3 import ( 4 "errors" 5 "net" 6 "net/netip" 7 "time" 8 9 N "github.com/kelleygo/clashcore/common/net" 10 C "github.com/kelleygo/clashcore/constant" 11 "github.com/kelleygo/clashcore/log" 12 ) 13 14 func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata) error { 15 addr := metadata.UDPAddr() 16 if addr == nil { 17 return errors.New("udp addr invalid") 18 } 19 20 if _, err := pc.WriteTo(packet.Data(), addr); err != nil { 21 return err 22 } 23 // reset timeout 24 _ = pc.SetReadDeadline(time.Now().Add(udpTimeout)) 25 26 return nil 27 } 28 29 func handleUDPToLocal(writeBack C.WriteBack, pc N.EnhancePacketConn, key string, oAddrPort netip.AddrPort, fAddr netip.Addr) { 30 defer func() { 31 _ = pc.Close() 32 closeAllLocalCoon(key) 33 natTable.Delete(key) 34 }() 35 36 for { 37 _ = pc.SetReadDeadline(time.Now().Add(udpTimeout)) 38 data, put, from, err := pc.WaitReadFrom() 39 if err != nil { 40 return 41 } 42 43 fromUDPAddr, isUDPAddr := from.(*net.UDPAddr) 44 if !isUDPAddr { 45 fromUDPAddr = net.UDPAddrFromAddrPort(oAddrPort) // oAddrPort was Unmapped 46 log.Warnln("server return a [%T](%s) which isn't a *net.UDPAddr, force replace to (%s), this may be caused by a wrongly implemented server", from, from, oAddrPort) 47 } else if fromUDPAddr == nil { 48 fromUDPAddr = net.UDPAddrFromAddrPort(oAddrPort) // oAddrPort was Unmapped 49 log.Warnln("server return a nil *net.UDPAddr, force replace to (%s), this may be caused by a wrongly implemented server", oAddrPort) 50 } else { 51 _fromUDPAddr := *fromUDPAddr 52 fromUDPAddr = &_fromUDPAddr // make a copy 53 if fromAddr, ok := netip.AddrFromSlice(fromUDPAddr.IP); ok { 54 fromAddr = fromAddr.Unmap() 55 if fAddr.IsValid() && (oAddrPort.Addr() == fromAddr) { // oAddrPort was Unmapped 56 fromAddr = fAddr.Unmap() 57 } 58 fromUDPAddr.IP = fromAddr.AsSlice() 59 if fromAddr.Is4() { 60 fromUDPAddr.Zone = "" // only ipv6 can have the zone 61 } 62 } 63 } 64 65 _, err = writeBack.WriteBack(data, fromUDPAddr) 66 if put != nil { 67 put() 68 } 69 if err != nil { 70 return 71 } 72 } 73 } 74 75 func closeAllLocalCoon(lAddr string) { 76 natTable.RangeForLocalConn(lAddr, func(key string, value *net.UDPConn) bool { 77 conn := value 78 79 conn.Close() 80 log.Debugln("Closing TProxy local conn... lAddr=%s rAddr=%s", lAddr, key) 81 return true 82 }) 83 } 84 85 func handleSocket(inbound, outbound net.Conn) { 86 N.Relay(inbound, outbound) 87 }