proxyport/app/forward/udp.go

125 lines
2.5 KiB
Go
Raw Permalink Normal View History

2024-09-30 16:37:53 +08:00
package forward
import (
"git.makemake.in/kzkzzzz/mycommon/mylog"
2024-10-10 10:53:08 +08:00
"log"
2024-09-30 16:37:53 +08:00
"math/rand"
"net"
"time"
)
var _ IForward = (*UDP)(nil)
type UDP struct {
forwardInfo *Info
conn *net.UDPConn
packetBufferSize int
messageTimeout time.Duration
}
func NewUDP(forwardInfo *Info) *UDP {
return &UDP{
forwardInfo: forwardInfo,
packetBufferSize: 2048,
messageTimeout: time.Second * 2,
}
}
func (u *UDP) Forward() error {
udpLocalAddr, err := net.ResolveUDPAddr("udp", u.forwardInfo.LocalAddr)
if err != nil {
return err
}
conn, err := net.ListenUDP("udp", udpLocalAddr)
if err != nil {
return err
}
u.conn = conn
2024-10-10 10:53:08 +08:00
log.Printf("[UDP] [%s] %s -> %s", u.forwardInfo.Name, u.forwardInfo.LocalAddr, u.forwardInfo.TargetAddr)
2024-09-30 16:37:53 +08:00
go func() {
err := u.handleConn(conn)
if err != nil {
mylog.Error(err)
}
}()
return nil
}
func (u *UDP) handleConn(conn *net.UDPConn) error {
defer func() {
mylog.Warnf("udp forward stop %s -> %+v", u.forwardInfo.LocalAddr, u.forwardInfo.TargetAddr)
}()
buffer := make([]byte, u.packetBufferSize) // 创建一个缓冲区
for {
// 接收数据
n, clientAddr, err := conn.ReadFromUDP(buffer)
if err != nil {
mylog.Error(err)
return err
}
targetAddr := u.forwardInfo.TargetAddr[rand.Intn(len(u.forwardInfo.TargetAddr))]
mylog.Debugf("udp forward %s -> %s", clientAddr.String(), targetAddr)
// 解析目标地址
//remoteAddr, err := net.ResolveUDPAddr("udp", targetAddr)
//if err != nil {
// mylog.Error(err)
// return err
//}
dialer := &net.Dialer{
Timeout: u.messageTimeout,
}
remoteRawConn, err := dialer.Dial("udp", targetAddr)
if err != nil {
mylog.Error(err)
continue
}
remoteRawConn.SetWriteDeadline(time.Now().Add(u.messageTimeout))
remoteRawConn.SetReadDeadline(time.Now().Add(u.messageTimeout))
remoteConn := remoteRawConn.(*net.UDPConn)
//remoteConn, err := net.DialUDP("udp", nil, remoteAddr)
//dial, err := reuseport.Dial("udp", "", targetAddr)
// 将数据转发到目标地址
_, err = remoteConn.Write(buffer[:n])
if err != nil {
mylog.Error(err)
continue
}
res := make([]byte, u.packetBufferSize)
resLen, _, err := remoteConn.ReadFromUDP(res)
if err != nil {
mylog.Error(err)
continue
}
// 将目标地址的响应返回给客户端
_, err = conn.WriteToUDP(res[:resLen], clientAddr)
if err != nil {
mylog.Error(err)
continue
}
}
}
func (u *UDP) Stop() {
if u.conn != nil {
u.conn.Close()
}
}