1 Star 0 Fork 604

玩家7 / goproxy

forked from 狂奔的蜗牛. / goproxy 
Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
Clone or download
ssudp.go 4.42 KB
Copy Edit Raw Blame History
package sps
import (
"bytes"
"fmt"
"net"
"runtime/debug"
"time"
"github.com/snail007/goproxy/utils"
goaes "github.com/snail007/goproxy/utils/aes"
"github.com/snail007/goproxy/utils/socks"
)
func (s *SPS) RunSSUDP(addr string) (err error) {
a, _ := net.ResolveUDPAddr("udp", addr)
listener, err := net.ListenUDP("udp", a)
if err != nil {
s.log.Printf("ss udp bind error %s", err)
return
}
s.log.Printf("ss udp on %s", listener.LocalAddr())
s.udpRelatedPacketConns.Set(addr, listener)
go func() {
defer func() {
if e := recover(); e != nil {
s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack()))
}
}()
buf := utils.LeakyBuffer.Get()
defer utils.LeakyBuffer.Put(buf)
for {
n, srcAddr, err := listener.ReadFrom(buf)
if err != nil {
s.log.Printf("read from client error %s", err)
if utils.IsNetClosedErr(err) {
return
}
continue
}
var (
inconnRemoteAddr = srcAddr.String()
outUDPConn *net.UDPConn
outconn net.Conn
outconnLocalAddr string
destAddr *net.UDPAddr
clean = func(msg, err string) {
raddr := ""
if outUDPConn != nil {
raddr = outUDPConn.RemoteAddr().String()
outUDPConn.Close()
}
if msg != "" {
if raddr != "" {
s.log.Printf("%s , %s , %s -> %s", msg, err, inconnRemoteAddr, raddr)
} else {
s.log.Printf("%s , %s , from : %s", msg, err, inconnRemoteAddr)
}
}
s.userConns.Remove(inconnRemoteAddr)
if outconn != nil {
outconn.Close()
}
if outconnLocalAddr != "" {
s.userConns.Remove(outconnLocalAddr)
}
}
)
defer clean("", "")
raw := new(bytes.Buffer)
raw.Write([]byte{0x00, 0x00, 0x00})
raw.Write(s.localCipher.Decrypt(buf[:n]))
socksPacket := socks.NewPacketUDP()
err = socksPacket.Parse(raw.Bytes())
raw = nil
if err != nil {
s.log.Printf("udp parse error %s", err)
return
}
if v, ok := s.udpRelatedPacketConns.Get(inconnRemoteAddr); !ok {
//socks client
lbAddr := s.lb.Select(inconnRemoteAddr, *s.cfg.LoadBalanceOnlyHA)
outconn, err := s.GetParentConn(lbAddr)
if err != nil {
clean("connnect fail", fmt.Sprintf("%s", err))
return
}
client, err := s.HandshakeSocksParent(s.getParentAuth(lbAddr), &outconn, "udp", socksPacket.Addr(), socks.Auth{}, true)
if err != nil {
clean("handshake fail", fmt.Sprintf("%s", err))
return
}
outconnLocalAddr = outconn.LocalAddr().String()
s.userConns.Set(outconnLocalAddr, &outconn)
go func() {
defer func() {
if e := recover(); e != nil {
s.log.Printf("udp related parent tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
}
}()
buf := make([]byte, 1)
outconn.SetReadDeadline(time.Time{})
if _, err := outconn.Read(buf); err != nil {
clean("udp parent tcp conn disconnected", fmt.Sprintf("%s", err))
}
}()
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
localZeroAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
outUDPConn, err = net.DialUDP("udp", localZeroAddr, destAddr)
if err != nil {
s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr)
return
}
s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn)
utils.UDPCopy(listener, outUDPConn, srcAddr, time.Second*5, func(data []byte) []byte {
//forward to local
var v []byte
//convert parent data to raw
if len(s.udpParentKey) > 0 {
v, err = goaes.Decrypt(s.udpParentKey, data)
if err != nil {
s.log.Printf("udp outconn parse packet fail, %s", err.Error())
return []byte{}
}
} else {
v = data
}
return s.localCipher.Encrypt(v[3:])
}, func(err interface{}) {
s.udpRelatedPacketConns.Remove(srcAddr.String())
if err != nil {
s.log.Printf("udp out->local io copy crashed:\n%s\n%s", err, string(debug.Stack()))
}
})
} else {
outUDPConn = v.(*net.UDPConn)
}
//forward to parent
//p is raw, now convert it to parent
var v []byte
if len(s.udpParentKey) > 0 {
v, _ = goaes.Encrypt(s.udpParentKey, socksPacket.Bytes())
} else {
v = socksPacket.Bytes()
}
_, err = outUDPConn.Write(v)
socksPacket = socks.PacketUDP{}
if err != nil {
if utils.IsNetClosedErr(err) {
return
}
s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr)
}
}
}()
return
}

Comment ( 0 )

Sign in for post a comment

Go
1
https://gitee.com/daoguo/proxy.git
git@gitee.com:daoguo/proxy.git
daoguo
proxy
goproxy
198281b5ebac

Search