connection.go 2.3 KB

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