Merge remote-tracking branch 'github_https/dev' into dev
This commit is contained in:
@ -88,7 +88,7 @@ func (s *MuxBridge) StopService() {
|
||||
(*(*s.sc).Listener).Close()
|
||||
}
|
||||
for _, g := range s.clientControlConns.Items() {
|
||||
for _, session := range g.(utils.ConcurrentMap).Items() {
|
||||
for _, session := range g.(*utils.ConcurrentMap).Items() {
|
||||
(session.(*smux.Session)).Close()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package socks
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -9,14 +8,12 @@ import (
|
||||
logger "log"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/services"
|
||||
"github.com/snail007/goproxy/services/kcpcfg"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
goaes "github.com/snail007/goproxy/utils/aes"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
"github.com/snail007/goproxy/utils/socks"
|
||||
"golang.org/x/crypto/ssh"
|
||||
@ -359,281 +356,7 @@ func (s *Socks) socksConnCallback(inConn net.Conn) {
|
||||
}
|
||||
|
||||
}
|
||||
func (s *Socks) ParentUDPKey() (key []byte) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "tcp":
|
||||
if *s.cfg.ParentKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) LocalUDPKey() (key []byte) {
|
||||
switch *s.cfg.LocalType {
|
||||
case "tcp":
|
||||
if *s.cfg.LocalKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
inconnRemoteAddr := (*inConn).RemoteAddr().String()
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
udpListener, err := net.ListenUDP("udp", localAddr)
|
||||
if err != nil {
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.log.Printf("udp bind fail , %s", err)
|
||||
return
|
||||
}
|
||||
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
_, port, _ := net.SplitHostPort(udpListener.LocalAddr().String())
|
||||
if len(*s.cfg.LocalIPS) > 0 {
|
||||
host = (*s.cfg.LocalIPS)[0]
|
||||
}
|
||||
s.log.Printf("proxy udp on %s , for %s", net.JoinHostPort(host, port), inconnRemoteAddr)
|
||||
request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port))
|
||||
s.userConns.Set(inconnRemoteAddr, inConn)
|
||||
var (
|
||||
outUDPConn *net.UDPConn
|
||||
outconn net.Conn
|
||||
outconnLocalAddr string
|
||||
isClosedErr = func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "use of closed network connection")
|
||||
}
|
||||
destAddr *net.UDPAddr
|
||||
)
|
||||
var 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)
|
||||
}
|
||||
}
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.userConns.Remove(inconnRemoteAddr)
|
||||
if outconn != nil {
|
||||
outconn.Close()
|
||||
}
|
||||
if outconnLocalAddr != "" {
|
||||
s.userConns.Remove(outconnLocalAddr)
|
||||
}
|
||||
}
|
||||
defer clean("", "")
|
||||
go func() {
|
||||
buf := make([]byte, 1)
|
||||
(*inConn).SetReadDeadline(time.Time{})
|
||||
if _, err := (*inConn).Read(buf); err != nil {
|
||||
clean("udp related tcp conn disconnected with read", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
(*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5))
|
||||
if _, err := (*inConn).Write([]byte{0x00}); err != nil {
|
||||
clean("udp related tcp conn disconnected with write", err.Error())
|
||||
return
|
||||
}
|
||||
(*inConn).SetWriteDeadline(time.Time{})
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
useProxy := true
|
||||
if *s.cfg.Parent != "" {
|
||||
dstHost, _, _ := net.SplitHostPort(request.Addr())
|
||||
if utils.IsIternalIP(dstHost, *s.cfg.Always) {
|
||||
useProxy = false
|
||||
} else {
|
||||
var isInMap bool
|
||||
useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr())
|
||||
if !isInMap {
|
||||
s.checker.Add(request.Addr(), s.Resolve(request.Addr()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
useProxy = false
|
||||
}
|
||||
if useProxy {
|
||||
//parent proxy
|
||||
outconn, err := s.getOutConn(nil, nil, "", false)
|
||||
if err != nil {
|
||||
clean("connnect fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
client := socks.NewClientConn(&outconn, "udp", request.Addr(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil)
|
||||
if err = client.Handshake(); err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
//outconnRemoteAddr := outconn.RemoteAddr().String()
|
||||
outconnLocalAddr = outconn.LocalAddr().String()
|
||||
s.userConns.Set(outconnLocalAddr, &outconn)
|
||||
go func() {
|
||||
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))
|
||||
}
|
||||
}()
|
||||
//forward to parent udp
|
||||
//s.log.Printf("parent udp address %s", client.UDPAddr)
|
||||
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
|
||||
}
|
||||
s.log.Printf("use proxy %v : udp %s", useProxy, request.Addr())
|
||||
//relay
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
p := socks.NewPacketUDP()
|
||||
//convert data to raw
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
var v []byte
|
||||
v, err = goaes.Decrypt(s.udpLocalKey, buf[:n])
|
||||
if err == nil {
|
||||
err = p.Parse(v)
|
||||
}
|
||||
} else {
|
||||
err = p.Parse(buf[:n])
|
||||
}
|
||||
//err = p.Parse(buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
port, _ := strconv.Atoi(p.Port())
|
||||
|
||||
if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok {
|
||||
if destAddr == nil {
|
||||
destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port}
|
||||
}
|
||||
outUDPConn, err = net.DialUDP("udp", localAddr, destAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
}
|
||||
s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn)
|
||||
go func() {
|
||||
defer s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
//out->local io copy
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, err := outUDPConn.Read(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
//var dlen = n
|
||||
if useProxy {
|
||||
//forward to local
|
||||
var v []byte
|
||||
//convert parent data to raw
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, err = goaes.Decrypt(s.udpParentKey, buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp outconn parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
v = buf[:n]
|
||||
}
|
||||
//now v is raw, try convert v to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
// _, err = udpListener.WriteTo(buf[:n], srcAddr)
|
||||
} else {
|
||||
rp := socks.NewPacketUDP()
|
||||
rp.Build(destAddr.String(), buf[:n])
|
||||
v := rp.Bytes()
|
||||
//dlen = len(v)
|
||||
//rp.Bytes() v is raw, try convert to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
outUDPConn = v.(*net.UDPConn)
|
||||
}
|
||||
//local->out io copy
|
||||
if useProxy {
|
||||
//forward to parent
|
||||
//p is raw, now convert it to parent
|
||||
var v []byte
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes())
|
||||
} else {
|
||||
v = p.Bytes()
|
||||
}
|
||||
_, err = outUDPConn.Write(v)
|
||||
// _, err = outUDPConn.Write(p.Bytes())
|
||||
} else {
|
||||
_, err = outUDPConn.Write(p.Data())
|
||||
}
|
||||
if err != nil {
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
func (s *Socks) proxyTCP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
var outConn net.Conn
|
||||
var err interface{}
|
||||
|
||||
315
services/socks/udp.go
Normal file
315
services/socks/udp.go
Normal file
@ -0,0 +1,315 @@
|
||||
package socks
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/utils"
|
||||
goaes "github.com/snail007/goproxy/utils/aes"
|
||||
"github.com/snail007/goproxy/utils/socks"
|
||||
)
|
||||
|
||||
func (s *Socks) ParentUDPKey() (key []byte) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "tcp":
|
||||
if *s.cfg.ParentKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) LocalUDPKey() (key []byte) {
|
||||
switch *s.cfg.LocalType {
|
||||
case "tcp":
|
||||
if *s.cfg.LocalKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Socks) proxyUDP(inConn *net.Conn, methodReq socks.MethodsRequest, request socks.Request) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
inconnRemoteAddr := (*inConn).RemoteAddr().String()
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
udpListener, err := net.ListenUDP("udp", localAddr)
|
||||
if err != nil {
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.log.Printf("udp bind fail , %s", err)
|
||||
return
|
||||
}
|
||||
host, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
_, port, _ := net.SplitHostPort(udpListener.LocalAddr().String())
|
||||
if len(*s.cfg.LocalIPS) > 0 {
|
||||
host = (*s.cfg.LocalIPS)[0]
|
||||
}
|
||||
s.log.Printf("proxy udp on %s , for %s", net.JoinHostPort(host, port), inconnRemoteAddr)
|
||||
request.UDPReply(socks.REP_SUCCESS, net.JoinHostPort(host, port))
|
||||
s.userConns.Set(inconnRemoteAddr, inConn)
|
||||
var (
|
||||
outUDPConn *net.UDPConn
|
||||
outconn net.Conn
|
||||
outconnLocalAddr string
|
||||
isClosedErr = func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "use of closed network connection")
|
||||
}
|
||||
destAddr *net.UDPAddr
|
||||
)
|
||||
var 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)
|
||||
}
|
||||
}
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.userConns.Remove(inconnRemoteAddr)
|
||||
if outconn != nil {
|
||||
outconn.Close()
|
||||
}
|
||||
if outconnLocalAddr != "" {
|
||||
s.userConns.Remove(outconnLocalAddr)
|
||||
}
|
||||
}
|
||||
defer clean("", "")
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
(*inConn).SetReadDeadline(time.Time{})
|
||||
if _, err := (*inConn).Read(buf); err != nil {
|
||||
clean("udp related tcp conn disconnected with read", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn write crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
(*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5))
|
||||
if _, err := (*inConn).Write([]byte{0x00}); err != nil {
|
||||
clean("udp related tcp conn disconnected with write", err.Error())
|
||||
return
|
||||
}
|
||||
(*inConn).SetWriteDeadline(time.Time{})
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
useProxy := true
|
||||
if *s.cfg.Parent != "" {
|
||||
dstHost, _, _ := net.SplitHostPort(request.Addr())
|
||||
if utils.IsIternalIP(dstHost, *s.cfg.Always) {
|
||||
useProxy = false
|
||||
} else {
|
||||
var isInMap bool
|
||||
useProxy, isInMap, _, _ = s.checker.IsBlocked(request.Addr())
|
||||
if !isInMap {
|
||||
s.checker.Add(request.Addr(), s.Resolve(request.Addr()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
useProxy = false
|
||||
}
|
||||
if useProxy {
|
||||
//parent proxy
|
||||
outconn, err := s.getOutConn(nil, nil, "", false)
|
||||
if err != nil {
|
||||
clean("connnect fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
client := socks.NewClientConn(&outconn, "udp", request.Addr(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil)
|
||||
if err = client.Handshake(); err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
//outconnRemoteAddr := outconn.RemoteAddr().String()
|
||||
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))
|
||||
}
|
||||
}()
|
||||
//forward to parent udp
|
||||
//s.log.Printf("parent udp address %s", client.UDPAddr)
|
||||
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
|
||||
}
|
||||
s.log.Printf("use proxy %v : udp %s", useProxy, request.Addr())
|
||||
//relay
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
p := socks.NewPacketUDP()
|
||||
//convert data to raw
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
var v []byte
|
||||
v, err = goaes.Decrypt(s.udpLocalKey, buf[:n])
|
||||
if err == nil {
|
||||
err = p.Parse(v)
|
||||
}
|
||||
} else {
|
||||
err = p.Parse(buf[:n])
|
||||
}
|
||||
//err = p.Parse(buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
port, _ := strconv.Atoi(p.Port())
|
||||
|
||||
if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok {
|
||||
if destAddr == nil {
|
||||
destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port}
|
||||
}
|
||||
outUDPConn, err = net.DialUDP("udp", localAddr, destAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
}
|
||||
s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp out->local io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
defer s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
//out->local io copy
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, err := outUDPConn.Read(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
//var dlen = n
|
||||
if useProxy {
|
||||
//forward to local
|
||||
var v []byte
|
||||
//convert parent data to raw
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, err = goaes.Decrypt(s.udpParentKey, buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp outconn parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
v = buf[:n]
|
||||
}
|
||||
//now v is raw, try convert v to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
// _, err = udpListener.WriteTo(buf[:n], srcAddr)
|
||||
} else {
|
||||
rp := socks.NewPacketUDP()
|
||||
rp.Build(destAddr.String(), buf[:n])
|
||||
v := rp.Bytes()
|
||||
//dlen = len(v)
|
||||
//rp.Bytes() v is raw, try convert to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
outUDPConn = v.(*net.UDPConn)
|
||||
}
|
||||
//local->out io copy
|
||||
if useProxy {
|
||||
//forward to parent
|
||||
//p is raw, now convert it to parent
|
||||
var v []byte
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes())
|
||||
} else {
|
||||
v = p.Bytes()
|
||||
}
|
||||
_, err = outUDPConn.Write(v)
|
||||
// _, err = outUDPConn.Write(p.Bytes())
|
||||
} else {
|
||||
_, err = outUDPConn.Write(p.Data())
|
||||
}
|
||||
if err != nil {
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
302
services/sps/socksudp.go
Normal file
302
services/sps/socksudp.go
Normal file
@ -0,0 +1,302 @@
|
||||
package sps
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/utils"
|
||||
goaes "github.com/snail007/goproxy/utils/aes"
|
||||
"github.com/snail007/goproxy/utils/conncrypt"
|
||||
"github.com/snail007/goproxy/utils/socks"
|
||||
)
|
||||
|
||||
func (s *SPS) ParentUDPKey() (key []byte) {
|
||||
switch *s.cfg.ParentType {
|
||||
case "tcp":
|
||||
if *s.cfg.ParentKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.ParentKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) LocalUDPKey() (key []byte) {
|
||||
switch *s.cfg.LocalType {
|
||||
case "tcp":
|
||||
if *s.cfg.LocalKey != "" {
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.LocalKey)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
case "tls":
|
||||
return s.cfg.KeyBytes[:24]
|
||||
case "kcp":
|
||||
v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key)))
|
||||
return []byte(v)[:24]
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *SPS) proxyUDP(inConn *net.Conn, serverConn *socks.ServerConn) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp local->out io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
if *s.cfg.ParentType == "ssh" {
|
||||
utils.CloseConn(inConn)
|
||||
return
|
||||
}
|
||||
inconnRemoteAddr := (*inConn).RemoteAddr().String()
|
||||
localAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
udpListener := serverConn.UDPConnListener
|
||||
s.log.Printf("proxy udp on %s , for %s", udpListener.LocalAddr(), inconnRemoteAddr)
|
||||
s.userConns.Set(inconnRemoteAddr, inConn)
|
||||
var (
|
||||
outUDPConn *net.UDPConn
|
||||
outconn net.Conn
|
||||
outconnLocalAddr string
|
||||
isClosedErr = func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "use of closed network connection")
|
||||
}
|
||||
destAddr *net.UDPAddr
|
||||
)
|
||||
var 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)
|
||||
}
|
||||
}
|
||||
(*inConn).Close()
|
||||
udpListener.Close()
|
||||
s.userConns.Remove(inconnRemoteAddr)
|
||||
if outconn != nil {
|
||||
outconn.Close()
|
||||
}
|
||||
if outconnLocalAddr != "" {
|
||||
s.userConns.Remove(outconnLocalAddr)
|
||||
}
|
||||
}
|
||||
defer clean("", "")
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn read crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
buf := make([]byte, 1)
|
||||
(*inConn).SetReadDeadline(time.Time{})
|
||||
if _, err := (*inConn).Read(buf); err != nil {
|
||||
clean("udp related tcp conn disconnected with read", err.Error())
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp related client tcp conn write crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
(*inConn).SetWriteDeadline(time.Now().Add(time.Second * 5))
|
||||
if _, err := (*inConn).Write([]byte{0x00}); err != nil {
|
||||
clean("udp related tcp conn disconnected with write", err.Error())
|
||||
return
|
||||
}
|
||||
(*inConn).SetWriteDeadline(time.Time{})
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
//parent proxy
|
||||
outconn, err := s.outPool.Get()
|
||||
//outconn, err := s.GetParentConn(nil, nil, "", false)
|
||||
if err != nil {
|
||||
clean("connnect fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
if *s.cfg.ParentCompress {
|
||||
outconn = utils.NewCompConn(outconn)
|
||||
}
|
||||
if *s.cfg.ParentKey != "" {
|
||||
outconn = conncrypt.New(outconn, &conncrypt.Config{
|
||||
Password: *s.cfg.ParentKey,
|
||||
})
|
||||
}
|
||||
|
||||
//client := socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil)
|
||||
|
||||
s.log.Printf("connect %s for udp", serverConn.Target())
|
||||
//socks client
|
||||
var client *socks.ClientConn
|
||||
auth := serverConn.AuthData()
|
||||
if *s.cfg.ParentAuth != "" {
|
||||
a := strings.Split(*s.cfg.ParentAuth, ":")
|
||||
if len(a) != 2 {
|
||||
err = fmt.Errorf("parent auth data format error")
|
||||
return
|
||||
}
|
||||
client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), &socks.Auth{User: a[0], Password: a[1]}, nil)
|
||||
} else {
|
||||
if !s.IsBasicAuth() && auth.Password != "" && auth.User != "" {
|
||||
client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), &auth, nil)
|
||||
} else {
|
||||
client = socks.NewClientConn(&outconn, "udp", serverConn.Target(), time.Millisecond*time.Duration(*s.cfg.Timeout), nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if err = client.Handshake(); err != nil {
|
||||
clean("handshake fail", fmt.Sprintf("%s", err))
|
||||
return
|
||||
}
|
||||
|
||||
//outconnRemoteAddr := outconn.RemoteAddr().String()
|
||||
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))
|
||||
}
|
||||
}()
|
||||
//forward to parent udp
|
||||
//s.log.Printf("parent udp address %s", client.UDPAddr)
|
||||
destAddr, _ = net.ResolveUDPAddr("udp", client.UDPAddr)
|
||||
//relay
|
||||
for {
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
n, srcAddr, err := udpListener.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener read fail, %s", err.Error())
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
p := socks.NewPacketUDP()
|
||||
//convert data to raw
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
var v []byte
|
||||
v, err = goaes.Decrypt(s.udpLocalKey, buf[:n])
|
||||
if err == nil {
|
||||
err = p.Parse(v)
|
||||
}
|
||||
} else {
|
||||
err = p.Parse(buf[:n])
|
||||
}
|
||||
//err = p.Parse(buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp listener parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
port, _ := strconv.Atoi(p.Port())
|
||||
|
||||
if v, ok := s.udpRelatedPacketConns.Get(srcAddr.String()); !ok {
|
||||
if destAddr == nil {
|
||||
destAddr = &net.UDPAddr{IP: net.ParseIP(p.Host()), Port: port}
|
||||
}
|
||||
outUDPConn, err = net.DialUDP("udp", localAddr, destAddr)
|
||||
if err != nil {
|
||||
s.log.Printf("create out udp conn fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
}
|
||||
s.udpRelatedPacketConns.Set(srcAddr.String(), outUDPConn)
|
||||
go func() {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
s.log.Printf("udp out->local io copy crashed:\n%s\n%s", e, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
defer s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
//out->local io copy
|
||||
buf := utils.LeakyBuffer.Get()
|
||||
defer utils.LeakyBuffer.Put(buf)
|
||||
for {
|
||||
n, err := outUDPConn.Read(buf)
|
||||
if err != nil {
|
||||
s.log.Printf("read out udp data fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
//var dlen = n
|
||||
//forward to local
|
||||
var v []byte
|
||||
//convert parent data to raw
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, err = goaes.Decrypt(s.udpParentKey, buf[:n])
|
||||
if err != nil {
|
||||
s.log.Printf("udp outconn parse packet fail, %s", err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
v = buf[:n]
|
||||
}
|
||||
//now v is raw, try convert v to local
|
||||
if len(s.udpLocalKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpLocalKey, v)
|
||||
}
|
||||
_, err = udpListener.WriteTo(v, srcAddr)
|
||||
// _, err = udpListener.WriteTo(buf[:n], srcAddr)
|
||||
|
||||
if err != nil {
|
||||
s.udpRelatedPacketConns.Remove(srcAddr.String())
|
||||
s.log.Printf("write out data to local fail , %s , from : %s", err, srcAddr)
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to local success , len %d, for : %s", dlen, srcAddr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
outUDPConn = v.(*net.UDPConn)
|
||||
}
|
||||
//local->out io copy
|
||||
//forward to parent
|
||||
//p is raw, now convert it to parent
|
||||
var v []byte
|
||||
if len(s.udpParentKey) > 0 {
|
||||
v, _ = goaes.Encrypt(s.udpParentKey, p.Bytes())
|
||||
} else {
|
||||
v = p.Bytes()
|
||||
}
|
||||
_, err = outUDPConn.Write(v)
|
||||
// _, err = outUDPConn.Write(p.Bytes())
|
||||
if err != nil {
|
||||
if isClosedErr(err) {
|
||||
return
|
||||
}
|
||||
s.log.Printf("send out udp data fail , %s , from : %s", err, srcAddr)
|
||||
continue
|
||||
} else {
|
||||
//s.log.Printf("send udp data to remote success , len %d, for : %s", len(p.Data()), srcAddr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -53,22 +53,26 @@ type SPSArgs struct {
|
||||
DisableSocks5 *bool
|
||||
}
|
||||
type SPS struct {
|
||||
outPool utils.OutConn
|
||||
cfg SPSArgs
|
||||
domainResolver utils.DomainResolver
|
||||
basicAuth utils.BasicAuth
|
||||
serverChannels []*utils.ServerChannel
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
outPool utils.OutConn
|
||||
cfg SPSArgs
|
||||
domainResolver utils.DomainResolver
|
||||
basicAuth utils.BasicAuth
|
||||
serverChannels []*utils.ServerChannel
|
||||
userConns utils.ConcurrentMap
|
||||
log *logger.Logger
|
||||
udpRelatedPacketConns utils.ConcurrentMap
|
||||
udpLocalKey []byte
|
||||
udpParentKey []byte
|
||||
}
|
||||
|
||||
func NewSPS() services.Service {
|
||||
return &SPS{
|
||||
outPool: utils.OutConn{},
|
||||
cfg: SPSArgs{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
serverChannels: []*utils.ServerChannel{},
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
outPool: utils.OutConn{},
|
||||
cfg: SPSArgs{},
|
||||
basicAuth: utils.BasicAuth{},
|
||||
serverChannels: []*utils.ServerChannel{},
|
||||
userConns: utils.NewConcurrentMap(),
|
||||
udpRelatedPacketConns: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (s *SPS) CheckArgs() (err error) {
|
||||
@ -93,6 +97,8 @@ func (s *SPS) CheckArgs() (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
s.udpLocalKey = s.LocalUDPKey()
|
||||
s.udpParentKey = s.ParentUDPKey()
|
||||
return
|
||||
}
|
||||
func (s *SPS) InitService() (err error) {
|
||||
@ -210,6 +216,11 @@ func (s *SPS) callback(inConn net.Conn) {
|
||||
}
|
||||
}
|
||||
func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
|
||||
enableUDP := *s.cfg.ParentServiceType == "socks"
|
||||
udpIP, _, _ := net.SplitHostPort((*inConn).LocalAddr().String())
|
||||
if len(*s.cfg.LocalIPS) > 0 {
|
||||
udpIP = (*s.cfg.LocalIPS)[0]
|
||||
}
|
||||
bInConn := utils.NewBufferedConn(*inConn)
|
||||
//important
|
||||
//action read will regist read event to system,
|
||||
@ -243,15 +254,19 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
|
||||
//socks5 server
|
||||
var serverConn *socks.ServerConn
|
||||
if s.IsBasicAuth() {
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, "", nil)
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, enableUDP, udpIP, nil)
|
||||
} else {
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, "", nil)
|
||||
serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, enableUDP, udpIP, nil)
|
||||
}
|
||||
if err = serverConn.Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
address = serverConn.Target()
|
||||
auth = serverConn.AuthData()
|
||||
if serverConn.IsUDP() {
|
||||
s.proxyUDP(inConn, serverConn)
|
||||
return
|
||||
}
|
||||
} else if utils.IsHTTP(h) || isSNI != "" {
|
||||
if *s.cfg.DisableHTTP {
|
||||
(*inConn).Close()
|
||||
|
||||
@ -2,10 +2,11 @@ package socks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/snail007/goproxy/utils"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/snail007/goproxy/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -54,26 +55,27 @@ type ServerConn struct {
|
||||
methods []uint8
|
||||
method uint8
|
||||
//request
|
||||
cmd uint8
|
||||
reserve uint8
|
||||
addressType uint8
|
||||
dstAddr string
|
||||
dstPort string
|
||||
dstHost string
|
||||
udpAddress string
|
||||
cmd uint8
|
||||
reserve uint8
|
||||
addressType uint8
|
||||
dstAddr string
|
||||
dstPort string
|
||||
dstHost string
|
||||
UDPConnListener *net.UDPConn
|
||||
enableUDP bool
|
||||
udpIP string
|
||||
}
|
||||
|
||||
func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, udpAddress string, header []byte) *ServerConn {
|
||||
if udpAddress == "" {
|
||||
udpAddress = "0.0.0.0:16666"
|
||||
}
|
||||
func NewServerConn(conn *net.Conn, timeout time.Duration, auth *utils.BasicAuth, enableUDP bool, udpHost string, header []byte) *ServerConn {
|
||||
|
||||
s := &ServerConn{
|
||||
conn: conn,
|
||||
timeout: timeout,
|
||||
auth: auth,
|
||||
header: header,
|
||||
ver: VERSION_V5,
|
||||
udpAddress: udpAddress,
|
||||
conn: conn,
|
||||
timeout: timeout,
|
||||
auth: auth,
|
||||
header: header,
|
||||
ver: VERSION_V5,
|
||||
enableUDP: enableUDP,
|
||||
udpIP: udpHost,
|
||||
}
|
||||
return s
|
||||
|
||||
@ -84,6 +86,12 @@ func (s *ServerConn) Close() {
|
||||
func (s *ServerConn) AuthData() Auth {
|
||||
return Auth{s.user, s.password}
|
||||
}
|
||||
func (s *ServerConn) IsUDP() bool {
|
||||
return s.cmd == CMD_ASSOCIATE
|
||||
}
|
||||
func (s *ServerConn) IsTCP() bool {
|
||||
return s.cmd == CMD_CONNECT
|
||||
}
|
||||
func (s *ServerConn) Method() uint8 {
|
||||
return s.method
|
||||
}
|
||||
@ -205,11 +213,29 @@ func (s *ServerConn) Handshake() (err error) {
|
||||
return
|
||||
}
|
||||
case CMD_ASSOCIATE:
|
||||
err = request.UDPReply(REP_SUCCESS, s.udpAddress)
|
||||
if !s.enableUDP {
|
||||
request.UDPReply(REP_UNKNOWN, "0.0.0.0:0")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("UDPReply REP_UNKNOWN to %s fail,ERR: %s", remoteAddr, err)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("cmd associate not supported, form: %s", remoteAddr)
|
||||
return
|
||||
}
|
||||
a, _ := net.ResolveUDPAddr("udp", ":0")
|
||||
s.UDPConnListener, err = net.ListenUDP("udp", a)
|
||||
if err != nil {
|
||||
request.UDPReply(REP_UNKNOWN, "0.0.0.0:0")
|
||||
err = fmt.Errorf("udp bind fail,ERR: %s , for %s", err, remoteAddr)
|
||||
return
|
||||
}
|
||||
_, port, _ := net.SplitHostPort(s.UDPConnListener.LocalAddr().String())
|
||||
err = request.UDPReply(REP_SUCCESS, net.JoinHostPort(s.udpIP, port))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("UDPReply REP_SUCCESS to %s fail,ERR: %s", remoteAddr, err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//fill socks info
|
||||
|
||||
Reference in New Issue
Block a user