2018-07-25 16:04:59 +00:00
package tunnel
import (
2020-06-12 15:39:03 +00:00
"errors"
2018-09-16 16:15:58 +00:00
"net"
2022-07-05 13:09:29 +00:00
"net/netip"
2018-09-21 03:33:29 +00:00
"time"
2018-07-25 16:04:59 +00:00
2023-01-16 02:50:31 +00:00
N "github.com/Dreamacro/clash/common/net"
2019-12-28 10:44:01 +00:00
C "github.com/Dreamacro/clash/constant"
2023-02-18 05:16:07 +00:00
"github.com/Dreamacro/clash/log"
2018-07-25 16:04:59 +00:00
)
2020-06-12 15:39:03 +00:00
func handleUDPToRemote ( packet C . UDPPacket , pc C . PacketConn , metadata * C . Metadata ) error {
addr := metadata . UDPAddr ( )
if addr == nil {
return errors . New ( "udp addr invalid" )
}
2021-02-26 02:40:55 +00:00
if _ , err := pc . WriteTo ( packet . Data ( ) , addr ) ; err != nil {
return err
}
// reset timeout
2022-07-05 13:09:29 +00:00
_ = pc . SetReadDeadline ( time . Now ( ) . Add ( udpTimeout ) )
2021-02-26 02:40:55 +00:00
return nil
2019-07-25 09:47:39 +00:00
}
2019-04-23 15:29:36 +00:00
2023-06-03 13:40:09 +00:00
func handleUDPToLocal ( writeBack C . WriteBack , pc N . EnhancePacketConn , key string , oAddrPort netip . AddrPort , fAddr netip . Addr ) {
2022-07-05 13:09:29 +00:00
defer func ( ) {
_ = pc . Close ( )
2023-02-17 08:31:15 +00:00
closeAllLocalCoon ( key )
2022-07-05 13:09:29 +00:00
natTable . Delete ( key )
} ( )
2019-04-23 15:29:36 +00:00
for {
2022-07-05 13:09:29 +00:00
_ = pc . SetReadDeadline ( time . Now ( ) . Add ( udpTimeout ) )
2023-05-11 05:47:51 +00:00
data , put , from , err := pc . WaitReadFrom ( )
2019-04-23 15:29:36 +00:00
if err != nil {
2019-07-25 09:47:39 +00:00
return
2019-04-23 15:29:36 +00:00
}
2023-05-27 05:43:41 +00:00
fromUDPAddr , isUDPAddr := from . ( * net . UDPAddr )
2023-07-16 02:35:10 +00:00
if ! isUDPAddr {
fromUDPAddr = net . UDPAddrFromAddrPort ( oAddrPort ) // oAddrPort was Unmapped
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 )
} else if fromUDPAddr == nil {
fromUDPAddr = net . UDPAddrFromAddrPort ( oAddrPort ) // oAddrPort was Unmapped
log . Warnln ( "server return a nil *net.UDPAddr, force replace to (%s), this may be caused by a wrongly implemented server" , oAddrPort )
} else {
2023-05-27 05:43:41 +00:00
_fromUDPAddr := * fromUDPAddr
fromUDPAddr = & _fromUDPAddr // make a copy
if fromAddr , ok := netip . AddrFromSlice ( fromUDPAddr . IP ) ; ok {
fromAddr = fromAddr . Unmap ( )
if fAddr . IsValid ( ) && ( oAddrPort . Addr ( ) == fromAddr ) { // oAddrPort was Unmapped
fromAddr = fAddr . Unmap ( )
}
fromUDPAddr . IP = fromAddr . AsSlice ( )
if fromAddr . Is4 ( ) {
fromUDPAddr . Zone = "" // only ipv6 can have the zone
}
2022-07-05 13:09:29 +00:00
}
2020-03-10 12:36:24 +00:00
}
2023-06-03 13:40:09 +00:00
_ , err = writeBack . WriteBack ( data , fromUDPAddr )
2023-05-15 11:06:58 +00:00
if put != nil {
put ( )
}
2019-07-25 09:47:39 +00:00
if err != nil {
return
2019-04-23 15:29:36 +00:00
}
}
2019-07-25 09:47:39 +00:00
}
2019-04-23 15:29:36 +00:00
2023-02-17 08:31:15 +00:00
func closeAllLocalCoon ( lAddr string ) {
2023-09-02 08:54:35 +00:00
natTable . RangeForLocalConn ( lAddr , func ( key string , value * net . UDPConn ) bool {
conn := value
2023-02-17 08:31:15 +00:00
conn . Close ( )
log . Debugln ( "Closing TProxy local conn... lAddr=%s rAddr=%s" , lAddr , key )
return true
} )
}
2021-01-23 06:49:46 +00:00
func handleSocket ( ctx C . ConnContext , outbound net . Conn ) {
2023-01-16 02:50:31 +00:00
N . Relay ( ctx . Conn ( ) , outbound )
2022-03-16 10:17:28 +00:00
}