Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
G
gost
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
gost
Commits
94dcfcab
Commit
94dcfcab
authored
Feb 08, 2020
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rudp: fix panic
parent
abe40434
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
80 additions
and
57 deletions
+80
-57
cmd/gost/route.go
cmd/gost/route.go
+17
-15
forward.go
forward.go
+3
-15
node.go
node.go
+5
-2
resolver.go
resolver.go
+37
-7
socks.go
socks.go
+18
-18
No files found.
cmd/gost/route.go
View file @
94dcfcab
...
...
@@ -9,7 +9,6 @@ import (
"net/url"
"os"
"strings"
"time"
"github.com/ginuerzh/gost"
"github.com/go-log/log"
...
...
@@ -136,6 +135,8 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
wsOpts
.
UserAgent
=
node
.
Get
(
"agent"
)
wsOpts
.
Path
=
node
.
Get
(
"path"
)
timeout
:=
node
.
GetDuration
(
"timeout"
)
var
host
string
var
tr
gost
.
Transporter
...
...
@@ -175,8 +176,8 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
config
:=
&
gost
.
QUICConfig
{
TLSConfig
:
tlsCfg
,
KeepAlive
:
node
.
GetBool
(
"keepalive"
),
Timeout
:
time
.
Duration
(
node
.
GetInt
(
"timeout"
))
*
time
.
Second
,
IdleTimeout
:
time
.
Duration
(
node
.
GetInt
(
"idle"
))
*
time
.
Second
,
Timeout
:
time
out
,
IdleTimeout
:
node
.
GetDuration
(
"idle"
)
,
}
if
cipher
:=
node
.
Get
(
"cipher"
);
cipher
!=
""
{
...
...
@@ -232,9 +233,8 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
connector
=
gost
.
AutoConnector
(
node
.
User
)
}
timeout
:=
node
.
GetInt
(
"timeout"
)
node
.
DialOptions
=
append
(
node
.
DialOptions
,
gost
.
TimeoutDialOption
(
time
.
Duration
(
timeout
)
*
time
.
Second
),
gost
.
TimeoutDialOption
(
time
out
),
)
node
.
ConnectOptions
=
[]
gost
.
ConnectOption
{
...
...
@@ -250,8 +250,8 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
gost
.
HostHandshakeOption
(
host
),
gost
.
UserHandshakeOption
(
node
.
User
),
gost
.
TLSConfigHandshakeOption
(
tlsCfg
),
gost
.
IntervalHandshakeOption
(
time
.
Duration
(
node
.
GetInt
(
"ping"
))
*
time
.
Second
),
gost
.
TimeoutHandshakeOption
(
time
.
Duration
(
timeout
)
*
time
.
Second
),
gost
.
IntervalHandshakeOption
(
node
.
GetDuration
(
"ping"
)
),
gost
.
TimeoutHandshakeOption
(
time
out
),
gost
.
RetryHandshakeOption
(
node
.
GetInt
(
"retry"
)),
}
node
.
Client
=
&
gost
.
Client
{
...
...
@@ -339,10 +339,8 @@ func (r *route) GenRouters() ([]router, error) {
wsOpts
.
WriteBufferSize
=
node
.
GetInt
(
"wbuf"
)
wsOpts
.
Path
=
node
.
Get
(
"path"
)
ttl
,
err
:=
time
.
ParseDuration
(
node
.
Get
(
"ttl"
))
if
err
!=
nil
{
ttl
=
time
.
Duration
(
node
.
GetInt
(
"ttl"
))
*
time
.
Second
}
ttl
:=
node
.
GetDuration
(
"ttl"
)
timeout
:=
node
.
GetDuration
(
"timeout"
)
tunRoutes
:=
parseIPRoutes
(
node
.
Get
(
"route"
))
gw
:=
net
.
ParseIP
(
node
.
Get
(
"gw"
))
// default gateway
...
...
@@ -393,8 +391,8 @@ func (r *route) GenRouters() ([]router, error) {
config
:=
&
gost
.
QUICConfig
{
TLSConfig
:
tlsCfg
,
KeepAlive
:
node
.
GetBool
(
"keepalive"
),
Timeout
:
time
.
Duration
(
node
.
GetInt
(
"timeout"
))
*
time
.
Second
,
IdleTimeout
:
time
.
Duration
(
node
.
GetInt
(
"idle"
))
*
time
.
Second
,
Timeout
:
time
out
,
IdleTimeout
:
node
.
GetDuration
(
"idle"
)
,
}
if
cipher
:=
node
.
Get
(
"cipher"
);
cipher
!=
""
{
sum
:=
sha256
.
Sum256
([]
byte
(
cipher
))
...
...
@@ -555,7 +553,11 @@ func (r *route) GenRouters() ([]router, error) {
resolver
:=
parseResolver
(
node
.
Get
(
"dns"
))
if
resolver
!=
nil
{
resolver
.
Init
(
gost
.
ChainResolverOption
(
chain
))
resolver
.
Init
(
gost
.
ChainResolverOption
(
chain
),
gost
.
TimeoutResolverOption
(
timeout
),
gost
.
TTLResolverOption
(
ttl
),
)
}
handler
.
Init
(
...
...
@@ -573,7 +575,7 @@ func (r *route) GenRouters() ([]router, error) {
gost
.
ResolverHandlerOption
(
resolver
),
gost
.
HostsHandlerOption
(
hosts
),
gost
.
RetryHandlerOption
(
node
.
GetInt
(
"retry"
)),
// override the global retry option.
gost
.
TimeoutHandlerOption
(
time
.
Duration
(
node
.
GetInt
(
"timeout"
))
*
time
.
Second
),
gost
.
TimeoutHandlerOption
(
time
out
),
gost
.
ProbeResistHandlerOption
(
node
.
Get
(
"probe_resist"
)),
gost
.
KnockingHandlerOption
(
node
.
Get
(
"knock"
)),
gost
.
NodeHandlerOption
(
node
),
...
...
forward.go
View file @
94dcfcab
...
...
@@ -334,7 +334,6 @@ type tcpRemoteForwardListener struct {
sessionMux
sync
.
Mutex
closed
chan
struct
{}
closeMux
sync
.
Mutex
errChan
chan
error
}
// TCPRemoteForwardListener creates a Listener for TCP remote port forwarding server.
...
...
@@ -349,7 +348,6 @@ func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
chain
:
chain
,
connChan
:
make
(
chan
net
.
Conn
,
1024
),
closed
:
make
(
chan
struct
{}),
errChan
:
make
(
chan
error
),
}
if
!
ln
.
isChainValid
()
{
...
...
@@ -365,7 +363,7 @@ func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
func
(
l
*
tcpRemoteForwardListener
)
isChainValid
()
bool
{
lastNode
:=
l
.
chain
.
LastNode
()
if
(
lastNode
.
Protocol
==
"forward"
&&
lastNode
.
Transport
==
"ssh"
)
||
lastNode
.
Protocol
==
"socks5"
{
lastNode
.
Protocol
==
"socks5"
||
lastNode
.
Protocol
==
""
{
return
true
}
return
false
...
...
@@ -431,7 +429,7 @@ func (l *tcpRemoteForwardListener) accept() (conn net.Conn, err error) {
return
l
.
chain
.
Dial
(
l
.
addr
.
String
())
}
if
lastNode
.
Protocol
==
"socks5"
{
if
lastNode
.
Protocol
==
"socks5"
||
lastNode
.
Protocol
==
""
{
if
lastNode
.
GetBool
(
"mbind"
)
{
return
l
.
muxAccept
()
// multiplexing support for binding.
}
...
...
@@ -588,11 +586,9 @@ type udpRemoteForwardListener struct {
connMap
*
udpConnMap
connChan
chan
net
.
Conn
ln
*
net
.
UDPConn
errChan
chan
error
ttl
time
.
Duration
closed
chan
struct
{}
closeMux
sync
.
Mutex
once
sync
.
Once
config
*
UDPListenConfig
}
...
...
@@ -617,15 +613,12 @@ func UDPRemoteForwardListener(addr string, chain *Chain, cfg *UDPListenConfig) (
chain
:
chain
,
connMap
:
new
(
udpConnMap
),
connChan
:
make
(
chan
net
.
Conn
,
backlog
),
errChan
:
make
(
chan
error
,
1
),
closed
:
make
(
chan
struct
{}),
config
:
cfg
,
}
go
ln
.
listenLoop
()
err
=
<-
ln
.
errChan
return
ln
,
err
}
...
...
@@ -699,7 +692,7 @@ func (l *udpRemoteForwardListener) connect() (conn net.PacketConn, err error) {
}
lastNode
:=
l
.
chain
.
LastNode
()
if
lastNode
.
Protocol
==
"socks5"
{
if
lastNode
.
Protocol
==
"socks5"
||
lastNode
.
Protocol
==
""
{
var
cc
net
.
Conn
cc
,
err
=
getSocks5UDPTunnel
(
l
.
chain
,
l
.
addr
)
if
err
!=
nil
{
...
...
@@ -716,11 +709,6 @@ func (l *udpRemoteForwardListener) connect() (conn net.PacketConn, err error) {
}
}
l
.
once
.
Do
(
func
()
{
l
.
errChan
<-
err
close
(
l
.
errChan
)
})
if
err
!=
nil
{
if
tempDelay
==
0
{
tempDelay
=
1000
*
time
.
Millisecond
...
...
node.go
View file @
94dcfcab
...
...
@@ -157,13 +157,16 @@ func (node *Node) GetBool(key string) bool {
// GetInt converts node parameter value to int.
func
(
node
*
Node
)
GetInt
(
key
string
)
int
{
n
,
_
:=
strconv
.
Atoi
(
node
.
Values
.
Get
(
key
))
n
,
_
:=
strconv
.
Atoi
(
node
.
Get
(
key
))
return
n
}
// GetDuration converts node parameter value to time.Duration.
func
(
node
*
Node
)
GetDuration
(
key
string
)
time
.
Duration
{
d
,
_
:=
time
.
ParseDuration
(
node
.
Values
.
Get
(
key
))
d
,
err
:=
time
.
ParseDuration
(
node
.
Get
(
key
))
if
err
!=
nil
{
d
=
time
.
Duration
(
node
.
GetInt
(
key
))
*
time
.
Second
}
return
d
}
...
...
resolver.go
View file @
94dcfcab
...
...
@@ -119,7 +119,9 @@ func (ns *NameServer) String() string {
}
type
resolverOptions
struct
{
chain
*
Chain
chain
*
Chain
timeout
time
.
Duration
ttl
time
.
Duration
}
// ResolverOption allows a common way to set Resolver options.
...
...
@@ -132,6 +134,20 @@ func ChainResolverOption(chain *Chain) ResolverOption {
}
}
// TimeoutResolverOption sets the timeout for Resolver.
func
TimeoutResolverOption
(
timeout
time
.
Duration
)
ResolverOption
{
return
func
(
opts
*
resolverOptions
)
{
opts
.
timeout
=
timeout
}
}
// TTLResolverOption sets the timeout for Resolver.
func
TTLResolverOption
(
ttl
time
.
Duration
)
ResolverOption
{
return
func
(
opts
*
resolverOptions
)
{
opts
.
ttl
=
ttl
}
}
// Resolver is a name resolver for domain name.
// It contains a list of name servers.
type
Resolver
interface
{
...
...
@@ -191,10 +207,17 @@ func (r *resolver) Init(opts ...ResolverOption) error {
}
timeout
:=
r
.
timeout
if
r
.
options
.
timeout
!=
0
{
timeout
=
r
.
options
.
timeout
}
if
timeout
<=
0
{
timeout
=
DefaultResolverTimeout
}
if
r
.
options
.
ttl
!=
0
{
r
.
ttl
=
r
.
options
.
ttl
}
var
nss
[]
NameServer
for
_
,
ns
:=
range
r
.
servers
{
if
err
:=
ns
.
Init
(
// init all name servers
...
...
@@ -279,7 +302,7 @@ func (r *resolver) resolve(ex Exchanger, host string) (ips []net.IP, err error)
}
func
(
r
*
resolver
)
resolveIPs
(
ctx
context
.
Context
,
ex
Exchanger
,
mq
*
dns
.
Msg
)
(
ips
[]
net
.
IP
,
err
error
)
{
mr
,
err
:=
r
.
exchangeMsg
(
ctx
,
ex
,
mq
)
mr
,
_
,
err
:=
r
.
exchangeMsg
(
ctx
,
ex
,
mq
)
if
err
!=
nil
{
return
}
...
...
@@ -302,12 +325,20 @@ func (r *resolver) Exchange(ctx context.Context, query []byte) (reply []byte, er
return
}
var
qs
string
if
len
(
mq
.
Question
)
>
0
{
qs
=
mq
.
Question
[
0
]
.
String
()
}
var
mr
*
dns
.
Msg
for
_
,
ns
:=
range
r
.
copyServers
()
{
mr
,
err
=
r
.
exchangeMsg
(
ctx
,
ns
.
exchanger
,
mq
)
var
cache
bool
mr
,
cache
,
err
=
r
.
exchangeMsg
(
ctx
,
ns
.
exchanger
,
mq
)
log
.
Logf
(
"[dns] exchange message %d via %s (cache hit: %v): %s"
,
mq
.
Id
,
ns
.
String
(),
cache
,
qs
)
if
err
==
nil
{
break
}
log
.
Logf
(
"[dns] exchange message %d via %s: %s"
,
mq
.
Id
,
ns
.
String
(),
err
)
}
if
err
!=
nil
{
return
...
...
@@ -315,12 +346,13 @@ func (r *resolver) Exchange(ctx context.Context, query []byte) (reply []byte, er
return
mr
.
Pack
()
}
func
(
r
*
resolver
)
exchangeMsg
(
ctx
context
.
Context
,
ex
Exchanger
,
mq
*
dns
.
Msg
)
(
mr
*
dns
.
Msg
,
err
error
)
{
func
(
r
*
resolver
)
exchangeMsg
(
ctx
context
.
Context
,
ex
Exchanger
,
mq
*
dns
.
Msg
)
(
mr
*
dns
.
Msg
,
cache
bool
,
err
error
)
{
// Only cache for single question.
if
len
(
mq
.
Question
)
==
1
{
key
:=
newResolverCacheKey
(
&
mq
.
Question
[
0
])
mr
=
r
.
cache
.
loadCache
(
key
)
if
mr
!=
nil
{
cache
=
true
mr
.
Id
=
mq
.
Id
return
}
...
...
@@ -340,9 +372,7 @@ func (r *resolver) exchangeMsg(ctx context.Context, ex Exchanger, mq *dns.Msg) (
}
mr
=
&
dns
.
Msg
{}
if
err
=
mr
.
Unpack
(
reply
);
err
!=
nil
{
return
nil
,
err
}
err
=
mr
.
Unpack
(
reply
)
return
}
...
...
socks.go
View file @
94dcfcab
...
...
@@ -1400,14 +1400,14 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
addr
:=
req
.
Addr
.
String
()
if
!
Can
(
"rudp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
log
.
Logf
(
"[socks5
-udp]
Unauthorized to udp bind to %s"
,
addr
)
log
.
Logf
(
"[socks5
] udp-tun
Unauthorized to udp bind to %s"
,
addr
)
return
}
bindAddr
,
_
:=
net
.
ResolveUDPAddr
(
"udp"
,
addr
)
uc
,
err
:=
net
.
ListenUDP
(
"udp"
,
bindAddr
)
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-udp]
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
log
.
Logf
(
"[socks5
] udp-tun
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
return
}
defer
uc
.
Close
()
...
...
@@ -1416,32 +1416,32 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
socksAddr
.
Host
,
_
,
_
=
net
.
SplitHostPort
(
conn
.
LocalAddr
()
.
String
())
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Succeeded
,
socksAddr
)
if
err
:=
reply
.
Write
(
conn
);
err
!=
nil
{
log
.
Logf
(
"[socks5
-udp]
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
log
.
Logf
(
"[socks5
] udp-tun
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
return
}
if
Debug
{
log
.
Logf
(
"[socks5
-udp]
%s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
socksAddr
,
reply
)
log
.
Logf
(
"[socks5
] udp-tun
%s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
socksAddr
,
reply
)
}
log
.
Logf
(
"[socks5
-udp]
%s <-> %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
log
.
Logf
(
"[socks5
] udp-tun
%s <-> %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
h
.
tunnelServerUDP
(
conn
,
uc
)
log
.
Logf
(
"[socks5
-udp]
%s >-< %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
log
.
Logf
(
"[socks5
] udp-tun
%s >-< %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
return
}
cc
,
err
:=
h
.
options
.
Chain
.
Conn
()
// connection error
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-udp]
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
log
.
Logf
(
"[socks5
] udp-tun
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
reply
.
Write
(
conn
)
log
.
Logf
(
"[socks5
-udp]
%s -> %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
reply
)
log
.
Logf
(
"[socks5
] udp-tun
%s -> %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
reply
)
return
}
defer
cc
.
Close
()
cc
,
err
=
socks5Handshake
(
cc
,
userSocks5HandshakeOption
(
h
.
options
.
Chain
.
LastNode
()
.
User
))
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-udp]
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
log
.
Logf
(
"[socks5
] udp-tun
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
return
}
// tunnel <-> tunnel, direct forwarding
...
...
@@ -1449,9 +1449,9 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
// so we don't need to authenticate it, as it's as explicit as whitelisting
req
.
Write
(
cc
)
log
.
Logf
(
"[socks5
-udp] %s <-> %s [tun]
"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
log
.
Logf
(
"[socks5
] udp-tun %s <-> %s
"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
transport
(
conn
,
cc
)
log
.
Logf
(
"[socks5
-udp] %s >-< %s [tun]
"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
log
.
Logf
(
"[socks5
] udp-tun %s >-< %s
"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
}
func
(
h
*
socks5Handler
)
tunnelServerUDP
(
cc
net
.
Conn
,
pc
net
.
PacketConn
)
(
err
error
)
{
...
...
@@ -1469,7 +1469,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err
return
}
if
h
.
options
.
Bypass
.
Contains
(
addr
.
String
())
{
log
.
Log
(
"[
udp-tun] [bypass]
read from"
,
addr
)
log
.
Log
(
"[
socks5] udp-tun bypass
read from"
,
addr
)
continue
// bypass
}
...
...
@@ -1477,12 +1477,12 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
uint16
(
n
),
0
,
toSocksAddr
(
addr
)),
b
[
:
n
])
if
err
:=
dgram
.
Write
(
cc
);
err
!=
nil
{
log
.
Logf
(
"[
udp-tun]
%s <- %s : %s"
,
cc
.
RemoteAddr
(),
dgram
.
Header
.
Addr
,
err
)
log
.
Logf
(
"[
socks5] udp-tun
%s <- %s : %s"
,
cc
.
RemoteAddr
(),
dgram
.
Header
.
Addr
,
err
)
errc
<-
err
return
}
if
Debug
{
log
.
Logf
(
"[
udp-tun]
%s <<< %s length: %d"
,
cc
.
RemoteAddr
(),
dgram
.
Header
.
Addr
,
len
(
dgram
.
Data
))
log
.
Logf
(
"[
socks5] udp-tun
%s <<< %s length: %d"
,
cc
.
RemoteAddr
(),
dgram
.
Header
.
Addr
,
len
(
dgram
.
Data
))
}
}
}()
...
...
@@ -1502,16 +1502,16 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err
continue
// drop silently
}
if
h
.
options
.
Bypass
.
Contains
(
addr
.
String
())
{
log
.
Log
(
"[
udp-tun] [bypass]
write to"
,
addr
)
log
.
Log
(
"[
socks5] udp-tun bypass
write to"
,
addr
)
continue
// bypass
}
if
_
,
err
:=
pc
.
WriteTo
(
dgram
.
Data
,
addr
);
err
!=
nil
{
log
.
Logf
(
"[
udp-tun]
%s -> %s : %s"
,
cc
.
RemoteAddr
(),
addr
,
err
)
log
.
Logf
(
"[
socks5] udp-tun
%s -> %s : %s"
,
cc
.
RemoteAddr
(),
addr
,
err
)
errc
<-
err
return
}
if
Debug
{
log
.
Logf
(
"[
udp-tun]
%s >>> %s length: %d"
,
cc
.
RemoteAddr
(),
addr
,
len
(
dgram
.
Data
))
log
.
Logf
(
"[
socks5] udp-tun
%s >>> %s length: %d"
,
cc
.
RemoteAddr
(),
addr
,
len
(
dgram
.
Data
))
}
}
}()
...
...
@@ -1895,7 +1895,7 @@ func getSocks5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
if
err
!=
nil
{
c
.
Close
()
}
return
conn
,
nil
return
conn
,
err
}
type
socks5UDPTunnelConn
struct
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment