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
47220e06
Commit
47220e06
authored
Jan 05, 2019
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add more test cases
parent
0f824edc
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
577 additions
and
171 deletions
+577
-171
client.go
client.go
+20
-2
common_test.go
common_test.go
+27
-15
forward.go
forward.go
+2
-2
forward_test.go
forward_test.go
+6
-6
http.go
http.go
+8
-3
http2.go
http2.go
+9
-3
http2_test.go
http2_test.go
+41
-1
http_test.go
http_test.go
+75
-1
obfs_test.go
obfs_test.go
+53
-0
resolver.go
resolver.go
+4
-3
resolver_test.go
resolver_test.go
+55
-0
selector_test.go
selector_test.go
+150
-0
socks.go
socks.go
+46
-111
socks_test.go
socks_test.go
+4
-4
ss.go
ss.go
+22
-6
ss_test.go
ss_test.go
+55
-14
No files found.
client.go
View file @
47220e06
...
@@ -5,6 +5,8 @@ import (
...
@@ -5,6 +5,8 @@ import (
"net"
"net"
"net/url"
"net/url"
"time"
"time"
"github.com/ginuerzh/gosocks5"
)
)
// Client is a proxy client.
// Client is a proxy client.
...
@@ -236,8 +238,10 @@ func QUICConfigHandshakeOption(config *QUICConfig) HandshakeOption {
...
@@ -236,8 +238,10 @@ func QUICConfigHandshakeOption(config *QUICConfig) HandshakeOption {
// ConnectOptions describes the options for Connector.Connect.
// ConnectOptions describes the options for Connector.Connect.
type
ConnectOptions
struct
{
type
ConnectOptions
struct
{
Addr
string
Addr
string
Timeout
time
.
Duration
Timeout
time
.
Duration
User
*
url
.
Userinfo
Selector
gosocks5
.
Selector
}
}
// ConnectOption allows a common way to set ConnectOptions.
// ConnectOption allows a common way to set ConnectOptions.
...
@@ -256,3 +260,17 @@ func TimeoutConnectOption(timeout time.Duration) ConnectOption {
...
@@ -256,3 +260,17 @@ func TimeoutConnectOption(timeout time.Duration) ConnectOption {
opts
.
Timeout
=
timeout
opts
.
Timeout
=
timeout
}
}
}
}
// UserConnectOption specifies the user info for authentication.
func
UserConnectOption
(
user
*
url
.
Userinfo
)
ConnectOption
{
return
func
(
opts
*
ConnectOptions
)
{
opts
.
User
=
user
}
}
// SelectorConnectOption specifies the SOCKS5 client selector.
func
SelectorConnectOption
(
s
gosocks5
.
Selector
)
ConnectOption
{
return
func
(
opts
*
ConnectOptions
)
{
opts
.
Selector
=
s
}
}
common_test.go
View file @
47220e06
...
@@ -13,6 +13,8 @@ import (
...
@@ -13,6 +13,8 @@ import (
"net/url"
"net/url"
"sync"
"sync"
"time"
"time"
"github.com/go-log/log"
)
)
func
init
()
{
func
init
()
{
...
@@ -95,7 +97,7 @@ func httpRoundtrip(conn net.Conn, targetURL string, data []byte) (err error) {
...
@@ -95,7 +97,7 @@ func httpRoundtrip(conn net.Conn, targetURL string, data []byte) (err error) {
return
return
}
}
func
udpRoundtrip
(
client
*
Client
,
server
*
Server
,
host
string
,
data
[]
byte
)
(
err
error
)
{
func
udpRoundtrip
(
logger
log
.
Logger
,
client
*
Client
,
server
*
Server
,
host
string
,
data
[]
byte
)
(
err
error
)
{
conn
,
err
:=
proxyConn
(
client
,
server
)
conn
,
err
:=
proxyConn
(
client
,
server
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
...
@@ -107,15 +109,17 @@ func udpRoundtrip(client *Client, server *Server, host string, data []byte) (err
...
@@ -107,15 +109,17 @@ func udpRoundtrip(client *Client, server *Server, host string, data []byte) (err
return
return
}
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
3
*
time
.
Second
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
1
*
time
.
Second
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
if
_
,
err
=
conn
.
Write
(
data
);
err
!=
nil
{
if
_
,
err
=
conn
.
Write
(
data
);
err
!=
nil
{
logger
.
Logf
(
"write to %s via %s: %s"
,
host
,
server
.
Addr
(),
err
)
return
return
}
}
recv
:=
make
([]
byte
,
len
(
data
))
recv
:=
make
([]
byte
,
len
(
data
))
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
logger
.
Logf
(
"read from %s via %s: %s"
,
host
,
server
.
Addr
(),
err
)
return
return
}
}
...
@@ -143,7 +147,7 @@ func proxyRoundtrip(client *Client, server *Server, targetURL string, data []byt
...
@@ -143,7 +147,7 @@ func proxyRoundtrip(client *Client, server *Server, targetURL string, data []byt
return
return
}
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
5
00
*
time
.
Millisecond
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
10
00
*
time
.
Millisecond
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
return
httpRoundtrip
(
conn
,
targetURL
,
data
)
return
httpRoundtrip
(
conn
,
targetURL
,
data
)
...
@@ -167,12 +171,13 @@ type udpHandlerFunc func(w io.Writer, r *udpRequest)
...
@@ -167,12 +171,13 @@ type udpHandlerFunc func(w io.Writer, r *udpRequest)
// udpTestServer is a UDP server for test.
// udpTestServer is a UDP server for test.
type
udpTestServer
struct
{
type
udpTestServer
struct
{
ln
net
.
PacketConn
ln
net
.
PacketConn
handler
udpHandlerFunc
handler
udpHandlerFunc
wg
sync
.
WaitGroup
wg
sync
.
WaitGroup
mu
sync
.
Mutex
// guards closed and conns
mu
sync
.
Mutex
// guards closed and conns
closed
bool
closed
bool
exitChan
chan
struct
{}
startChan
chan
struct
{}
exitChan
chan
struct
{}
}
}
func
newUDPTestServer
(
handler
udpHandlerFunc
)
*
udpTestServer
{
func
newUDPTestServer
(
handler
udpHandlerFunc
)
*
udpTestServer
{
...
@@ -181,23 +186,30 @@ func newUDPTestServer(handler udpHandlerFunc) *udpTestServer {
...
@@ -181,23 +186,30 @@ func newUDPTestServer(handler udpHandlerFunc) *udpTestServer {
if
err
!=
nil
{
if
err
!=
nil
{
panic
(
fmt
.
Sprintf
(
"udptest: failed to listen on a port: %v"
,
err
))
panic
(
fmt
.
Sprintf
(
"udptest: failed to listen on a port: %v"
,
err
))
}
}
ln
.
SetReadBuffer
(
1024
*
1024
)
ln
.
SetWriteBuffer
(
1024
*
1024
)
return
&
udpTestServer
{
return
&
udpTestServer
{
ln
:
ln
,
ln
:
ln
,
handler
:
handler
,
handler
:
handler
,
exitChan
:
make
(
chan
struct
{}),
startChan
:
make
(
chan
struct
{}),
exitChan
:
make
(
chan
struct
{}),
}
}
}
}
func
(
s
*
udpTestServer
)
Start
()
{
func
(
s
*
udpTestServer
)
Start
()
{
go
s
.
serve
()
go
s
.
serve
()
<-
s
.
startChan
}
}
func
(
s
*
udpTestServer
)
serve
()
{
func
(
s
*
udpTestServer
)
serve
()
{
select
{
case
<-
s
.
startChan
:
return
default
:
close
(
s
.
startChan
)
}
for
{
for
{
data
:=
make
([]
byte
,
1024
)
data
:=
make
([]
byte
,
32
*
1024
)
n
,
raddr
,
err
:=
s
.
ln
.
ReadFrom
(
data
)
n
,
raddr
,
err
:=
s
.
ln
.
ReadFrom
(
data
)
if
err
!=
nil
{
if
err
!=
nil
{
break
break
...
...
forward.go
View file @
47220e06
...
@@ -787,7 +787,7 @@ func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
...
@@ -787,7 +787,7 @@ func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
HandshakeTimeout
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
HandshakeTimeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
conn
,
err
=
socks5Handshake
(
conn
,
l
.
chain
.
LastNode
()
.
User
)
conn
,
err
=
socks5Handshake
(
conn
,
nil
,
l
.
chain
.
LastNode
()
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -822,7 +822,7 @@ func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
...
@@ -822,7 +822,7 @@ func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
}
}
func
(
l
*
tcpRemoteForwardListener
)
waitConnectSOCKS5
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
func
(
l
*
tcpRemoteForwardListener
)
waitConnectSOCKS5
(
conn
net
.
Conn
)
(
net
.
Conn
,
error
)
{
conn
,
err
:=
socks5Handshake
(
conn
,
l
.
chain
.
LastNode
()
.
User
)
conn
,
err
:=
socks5Handshake
(
conn
,
nil
,
l
.
chain
.
LastNode
()
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
forward_test.go
View file @
47220e06
...
@@ -119,7 +119,7 @@ func BenchmarkTCPDirectForwardParallel(b *testing.B) {
...
@@ -119,7 +119,7 @@ func BenchmarkTCPDirectForwardParallel(b *testing.B) {
})
})
}
}
func
udpDirectForwardRoundtrip
(
host
string
,
data
[]
byte
)
error
{
func
udpDirectForwardRoundtrip
(
t
*
testing
.
T
,
host
string
,
data
[]
byte
)
error
{
ln
,
err
:=
UDPDirectForwardListener
(
"localhost:0"
,
0
)
ln
,
err
:=
UDPDirectForwardListener
(
"localhost:0"
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -138,7 +138,7 @@ func udpDirectForwardRoundtrip(host string, data []byte) error {
...
@@ -138,7 +138,7 @@ func udpDirectForwardRoundtrip(host string, data []byte) error {
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
return
udpRoundtrip
(
t
,
client
,
server
,
host
,
data
)
}
}
func
TestUDPDirectForward
(
t
*
testing
.
T
)
{
func
TestUDPDirectForward
(
t
*
testing
.
T
)
{
...
@@ -148,7 +148,7 @@ func TestUDPDirectForward(t *testing.T) {
...
@@ -148,7 +148,7 @@ func TestUDPDirectForward(t *testing.T) {
sendData
:=
make
([]
byte
,
128
)
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
rand
.
Read
(
sendData
)
err
:=
udpDirectForwardRoundtrip
(
udpSrv
.
Addr
(),
sendData
)
err
:=
udpDirectForwardRoundtrip
(
t
,
udpSrv
.
Addr
(),
sendData
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
(
err
)
t
.
Error
(
err
)
}
}
...
@@ -181,7 +181,7 @@ func BenchmarkUDPDirectForward(b *testing.B) {
...
@@ -181,7 +181,7 @@ func BenchmarkUDPDirectForward(b *testing.B) {
defer
server
.
Close
()
defer
server
.
Close
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
if
err
:=
udpRoundtrip
(
b
,
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
b
.
Error
(
err
)
}
}
}
}
...
@@ -215,7 +215,7 @@ func BenchmarkUDPDirectForwardParallel(b *testing.B) {
...
@@ -215,7 +215,7 @@ func BenchmarkUDPDirectForwardParallel(b *testing.B) {
b
.
RunParallel
(
func
(
pb
*
testing
.
PB
)
{
b
.
RunParallel
(
func
(
pb
*
testing
.
PB
)
{
for
pb
.
Next
()
{
for
pb
.
Next
()
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
if
err
:=
udpRoundtrip
(
b
,
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
b
.
Error
(
err
)
}
}
}
}
...
@@ -281,7 +281,7 @@ func udpRemoteForwardRoundtrip(t *testing.T, host string, data []byte) error {
...
@@ -281,7 +281,7 @@ func udpRemoteForwardRoundtrip(t *testing.T, host string, data []byte) error {
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
return
udpRoundtrip
(
t
,
client
,
server
,
host
,
data
)
}
}
func
TestUDPRemoteForward
(
t
*
testing
.
T
)
{
func
TestUDPRemoteForward
(
t
*
testing
.
T
)
{
...
...
http.go
View file @
47220e06
...
@@ -52,9 +52,14 @@ func (c *httpConnector) Connect(conn net.Conn, addr string, options ...ConnectOp
...
@@ -52,9 +52,14 @@ func (c *httpConnector) Connect(conn net.Conn, addr string, options ...ConnectOp
req
.
Header
.
Set
(
"User-Agent"
,
DefaultUserAgent
)
req
.
Header
.
Set
(
"User-Agent"
,
DefaultUserAgent
)
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
if
c
.
User
!=
nil
{
user
:=
opts
.
User
u
:=
c
.
User
.
Username
()
if
user
==
nil
{
p
,
_
:=
c
.
User
.
Password
()
user
=
c
.
User
}
if
user
!=
nil
{
u
:=
user
.
Username
()
p
,
_
:=
user
.
Password
()
req
.
Header
.
Set
(
"Proxy-Authorization"
,
req
.
Header
.
Set
(
"Proxy-Authorization"
,
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
u
+
":"
+
p
)))
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
u
+
":"
+
p
)))
}
}
...
...
http2.go
View file @
47220e06
...
@@ -58,9 +58,15 @@ func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectO
...
@@ -58,9 +58,15 @@ func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectO
}
}
// TODO: use the standard CONNECT method.
// TODO: use the standard CONNECT method.
req
.
Header
.
Set
(
"Gost-Target"
,
addr
)
req
.
Header
.
Set
(
"Gost-Target"
,
addr
)
if
c
.
User
!=
nil
{
u
:=
c
.
User
.
Username
()
user
:=
opts
.
User
p
,
_
:=
c
.
User
.
Password
()
if
user
==
nil
{
user
=
c
.
User
}
if
user
!=
nil
{
u
:=
user
.
Username
()
p
,
_
:=
user
.
Password
()
req
.
Header
.
Set
(
"Proxy-Authorization"
,
req
.
Header
.
Set
(
"Proxy-Authorization"
,
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
u
+
":"
+
p
)))
"Basic "
+
base64
.
StdEncoding
.
EncodeToString
([]
byte
(
u
+
":"
+
p
)))
}
}
...
...
http2_test.go
View file @
47220e06
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"crypto/tls"
"crypto/tls"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
"net"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
...
@@ -36,7 +37,7 @@ func http2ProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo
...
@@ -36,7 +37,7 @@ func http2ProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo
return
proxyRoundtrip
(
client
,
server
,
targetURL
,
data
)
return
proxyRoundtrip
(
client
,
server
,
targetURL
,
data
)
}
}
func
TestHTTP2Proxy
(
t
*
testing
.
T
)
{
func
TestHTTP2Proxy
Auth
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
defer
httpSrv
.
Close
()
...
@@ -1108,3 +1109,42 @@ func TestHTTP2ProxyWithFileProbeResist(t *testing.T) {
...
@@ -1108,3 +1109,42 @@ func TestHTTP2ProxyWithFileProbeResist(t *testing.T) {
t
.
Error
(
"data not equal"
)
t
.
Error
(
"data not equal"
)
}
}
}
}
func
TestHTTP2ProxyWithBypass
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
u
,
err
:=
url
.
Parse
(
httpSrv
.
URL
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
ln
,
err
:=
HTTP2Listener
(
""
,
nil
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
client
:=
&
Client
{
Connector
:
HTTP2Connector
(
nil
),
Transporter
:
HTTP2Transporter
(
nil
),
}
host
:=
u
.
Host
if
h
,
_
,
_
:=
net
.
SplitHostPort
(
u
.
Host
);
h
!=
""
{
host
=
h
}
server
:=
&
Server
{
Listener
:
ln
,
Handler
:
HTTP2Handler
(
BypassHandlerOption
(
NewBypassPatterns
(
false
,
host
)),
),
}
go
server
.
Run
()
defer
server
.
Close
()
if
err
=
proxyRoundtrip
(
client
,
server
,
httpSrv
.
URL
,
sendData
);
err
==
nil
{
t
.
Error
(
"should failed"
)
}
}
http_test.go
View file @
47220e06
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"crypto/rand"
"crypto/rand"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
"net"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
...
@@ -55,7 +56,7 @@ func httpProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo,
...
@@ -55,7 +56,7 @@ func httpProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Userinfo,
return
proxyRoundtrip
(
client
,
server
,
targetURL
,
data
)
return
proxyRoundtrip
(
client
,
server
,
targetURL
,
data
)
}
}
func
TestHTTPProxy
(
t
*
testing
.
T
)
{
func
TestHTTPProxy
Auth
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
defer
httpSrv
.
Close
()
...
@@ -82,6 +83,40 @@ func TestHTTPProxy(t *testing.T) {
...
@@ -82,6 +83,40 @@ func TestHTTPProxy(t *testing.T) {
}
}
}
}
func
TestHTTPProxyWithInvalidRequest
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
server
:=
&
Server
{
Listener
:
ln
,
Handler
:
HTTPHandler
(),
}
go
server
.
Run
()
defer
server
.
Close
()
r
,
err
:=
http
.
NewRequest
(
"GET"
,
"http://"
+
ln
.
Addr
()
.
String
(),
bytes
.
NewReader
(
sendData
))
if
err
!=
nil
{
t
.
Error
(
err
)
}
resp
,
err
:=
http
.
DefaultClient
.
Do
(
r
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusBadRequest
{
t
.
Error
(
"got status:"
,
resp
.
Status
)
}
}
func
BenchmarkHTTPProxy
(
b
*
testing
.
B
)
{
func
BenchmarkHTTPProxy
(
b
*
testing
.
B
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
defer
httpSrv
.
Close
()
...
@@ -302,3 +337,42 @@ func TestHTTPProxyWithFileProbeResist(t *testing.T) {
...
@@ -302,3 +337,42 @@ func TestHTTPProxyWithFileProbeResist(t *testing.T) {
t
.
Error
(
"data not equal, got:"
,
string
(
recv
))
t
.
Error
(
"data not equal, got:"
,
string
(
recv
))
}
}
}
}
func
TestHTTPProxyWithBypass
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
u
,
err
:=
url
.
Parse
(
httpSrv
.
URL
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
client
:=
&
Client
{
Connector
:
HTTPConnector
(
nil
),
Transporter
:
TCPTransporter
(),
}
host
:=
u
.
Host
if
h
,
_
,
_
:=
net
.
SplitHostPort
(
u
.
Host
);
h
!=
""
{
host
=
h
}
server
:=
&
Server
{
Listener
:
ln
,
Handler
:
HTTPHandler
(
BypassHandlerOption
(
NewBypassPatterns
(
false
,
host
)),
),
}
go
server
.
Run
()
defer
server
.
Close
()
if
err
=
proxyRoundtrip
(
client
,
server
,
httpSrv
.
URL
,
sendData
);
err
==
nil
{
t
.
Error
(
"should failed"
)
}
}
obfs_test.go
View file @
47220e06
...
@@ -369,3 +369,56 @@ func TestSNIOverObfsHTTP(t *testing.T) {
...
@@ -369,3 +369,56 @@ func TestSNIOverObfsHTTP(t *testing.T) {
})
})
}
}
}
}
func
httpOverObfs4Roundtrip
(
targetURL
string
,
data
[]
byte
,
clientInfo
*
url
.
Userinfo
,
serverInfo
[]
*
url
.
Userinfo
)
error
{
ln
,
err
:=
Obfs4Listener
(
""
)
if
err
!=
nil
{
return
err
}
client
:=
&
Client
{
Connector
:
HTTPConnector
(
clientInfo
),
Transporter
:
Obfs4Transporter
(),
}
server
:=
&
Server
{
Listener
:
ln
,
Handler
:
HTTPHandler
(
UsersHandlerOption
(
serverInfo
...
),
),
}
go
server
.
Run
()
defer
server
.
Close
()
return
proxyRoundtrip
(
client
,
server
,
targetURL
,
data
)
}
func
_TestHTTPOverObfs4
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
for
i
,
tc
:=
range
httpProxyTests
{
tc
:=
tc
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
err
:=
httpOverObfs4Roundtrip
(
httpSrv
.
URL
,
sendData
,
tc
.
cliUser
,
tc
.
srvUsers
)
if
err
==
nil
{
if
tc
.
errStr
!=
""
{
t
.
Errorf
(
"#%d should failed with error %s"
,
i
,
tc
.
errStr
)
}
}
else
{
if
tc
.
errStr
==
""
{
t
.
Errorf
(
"#%d got error %v"
,
i
,
err
)
}
if
err
.
Error
()
!=
tc
.
errStr
{
t
.
Errorf
(
"#%d got error %v, want %v"
,
i
,
err
,
tc
.
errStr
)
}
}
})
}
}
resolver.go
View file @
47220e06
...
@@ -238,7 +238,7 @@ type resolverCacheItem struct {
...
@@ -238,7 +238,7 @@ type resolverCacheItem struct {
}
}
func
(
r
*
resolver
)
loadCache
(
name
string
,
ttl
time
.
Duration
)
[]
net
.
IP
{
func
(
r
*
resolver
)
loadCache
(
name
string
,
ttl
time
.
Duration
)
[]
net
.
IP
{
if
ttl
<
0
{
if
name
==
""
||
ttl
<
0
{
return
nil
return
nil
}
}
...
@@ -248,7 +248,8 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
...
@@ -248,7 +248,8 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
ttl
=
item
.
ttl
ttl
=
item
.
ttl
}
}
if
item
==
nil
||
time
.
Since
(
time
.
Unix
(
item
.
ts
,
0
))
>
ttl
{
if
time
.
Since
(
time
.
Unix
(
item
.
ts
,
0
))
>
ttl
{
r
.
mCache
.
Delete
(
name
)
return
nil
return
nil
}
}
return
item
.
IPs
return
item
.
IPs
...
@@ -258,7 +259,7 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
...
@@ -258,7 +259,7 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
}
}
func
(
r
*
resolver
)
storeCache
(
name
string
,
ips
[]
net
.
IP
,
ttl
time
.
Duration
)
{
func
(
r
*
resolver
)
storeCache
(
name
string
,
ips
[]
net
.
IP
,
ttl
time
.
Duration
)
{
if
name
==
""
||
len
(
ips
)
==
0
{
if
name
==
""
||
len
(
ips
)
==
0
||
ttl
<
0
{
return
return
}
}
r
.
mCache
.
Store
(
name
,
&
resolverCacheItem
{
r
.
mCache
.
Store
(
name
,
&
resolverCacheItem
{
...
...
resolver_test.go
View file @
47220e06
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"bytes"
"bytes"
"fmt"
"fmt"
"io"
"io"
"net"
"testing"
"testing"
"time"
"time"
)
)
...
@@ -13,6 +14,8 @@ var dnsTests = []struct {
...
@@ -13,6 +14,8 @@ var dnsTests = []struct {
host
string
host
string
pass
bool
pass
bool
}{
}{
{
NameServer
{
Addr
:
"1.1.1.1"
},
"192.168.1.1"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1"
},
"github"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:53"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:53"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:53"
,
Protocol
:
"tcp"
},
"github.com"
,
true
},
{
NameServer
{
Addr
:
"1.1.1.1:53"
,
Protocol
:
"tcp"
},
"github.com"
,
true
},
...
@@ -47,6 +50,8 @@ func TestDNSResolver(t *testing.T) {
...
@@ -47,6 +50,8 @@ func TestDNSResolver(t *testing.T) {
}
}
t
.
Log
(
ns
)
t
.
Log
(
ns
)
r
:=
NewResolver
(
0
,
ns
)
r
:=
NewResolver
(
0
,
ns
)
resolv
:=
r
.
(
*
resolver
)
resolv
.
domain
=
"com"
err
:=
dnsResolverRoundtrip
(
t
,
r
,
tc
.
host
)
err
:=
dnsResolverRoundtrip
(
t
,
r
,
tc
.
host
)
if
err
!=
nil
{
if
err
!=
nil
{
if
tc
.
pass
{
if
tc
.
pass
{
...
@@ -61,6 +66,56 @@ func TestDNSResolver(t *testing.T) {
...
@@ -61,6 +66,56 @@ func TestDNSResolver(t *testing.T) {
}
}
}
}
var
resolverCacheTests
=
[]
struct
{
name
string
ips
[]
net
.
IP
ttl
time
.
Duration
result
[]
net
.
IP
}{
{
""
,
nil
,
0
,
nil
},
{
""
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
)},
0
,
nil
},
{
""
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
)},
10
*
time
.
Second
,
nil
},
{
"example.com"
,
nil
,
10
*
time
.
Second
,
nil
},
{
"example.com"
,
[]
net
.
IP
{},
10
*
time
.
Second
,
nil
},
{
"example.com"
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
)},
0
,
nil
},
{
"example.com"
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
)},
-
1
,
nil
},
{
"example.com"
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
)},
10
*
time
.
Second
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
)}},
{
"example.com"
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
),
net
.
IPv4
(
192
,
168
,
1
,
2
)},
10
*
time
.
Second
,
[]
net
.
IP
{
net
.
IPv4
(
192
,
168
,
1
,
1
),
net
.
IPv4
(
192
,
168
,
1
,
2
)}},
}
func
TestResolverCache
(
t
*
testing
.
T
)
{
isEqual
:=
func
(
a
,
b
[]
net
.
IP
)
bool
{
if
a
==
nil
&&
b
==
nil
{
return
true
}
if
a
==
nil
||
b
==
nil
||
len
(
a
)
!=
len
(
b
)
{
return
false
}
for
i
:=
range
a
{
if
!
a
[
i
]
.
Equal
(
b
[
i
])
{
return
false
}
}
return
true
}
for
i
,
tc
:=
range
resolverCacheTests
{
tc
:=
tc
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
r
:=
newResolver
(
tc
.
ttl
)
r
.
storeCache
(
tc
.
name
,
tc
.
ips
,
tc
.
ttl
)
ips
:=
r
.
loadCache
(
tc
.
name
,
tc
.
ttl
)
if
!
isEqual
(
tc
.
result
,
ips
)
{
t
.
Error
(
"unexpected cache value:"
,
tc
.
name
,
ips
,
tc
.
ttl
)
}
})
}
}
var
resolverReloadTests
=
[]
struct
{
var
resolverReloadTests
=
[]
struct
{
r
io
.
Reader
r
io
.
Reader
...
...
selector_test.go
0 → 100644
View file @
47220e06
package
gost
import
(
"testing"
"time"
)
func
TestRoundStrategy
(
t
*
testing
.
T
)
{
nodes
:=
[]
Node
{
Node
{
ID
:
1
},
Node
{
ID
:
2
},
Node
{
ID
:
3
},
}
s
:=
NewStrategy
(
"round"
)
t
.
Log
(
s
.
String
())
if
node
:=
s
.
Apply
(
nil
);
node
.
ID
>
0
{
t
.
Error
(
"unexpected node"
,
node
.
String
())
}
for
i
:=
0
;
i
<=
len
(
nodes
);
i
++
{
node
:=
s
.
Apply
(
nodes
)
if
node
.
ID
!=
nodes
[
i
%
len
(
nodes
)]
.
ID
{
t
.
Error
(
"unexpected node"
,
node
.
String
())
}
}
}
func
TestRandomStrategy
(
t
*
testing
.
T
)
{
nodes
:=
[]
Node
{
Node
{
ID
:
1
},
Node
{
ID
:
2
},
Node
{
ID
:
3
},
}
s
:=
NewStrategy
(
"random"
)
t
.
Log
(
s
.
String
())
if
node
:=
s
.
Apply
(
nil
);
node
.
ID
>
0
{
t
.
Error
(
"unexpected node"
,
node
.
String
())
}
for
i
:=
0
;
i
<=
len
(
nodes
);
i
++
{
node
:=
s
.
Apply
(
nodes
)
if
node
.
ID
==
0
{
t
.
Error
(
"unexpected node"
,
node
.
String
())
}
}
}
func
TestFIFOStrategy
(
t
*
testing
.
T
)
{
nodes
:=
[]
Node
{
Node
{
ID
:
1
},
Node
{
ID
:
2
},
Node
{
ID
:
3
},
}
s
:=
NewStrategy
(
"fifo"
)
t
.
Log
(
s
.
String
())
if
node
:=
s
.
Apply
(
nil
);
node
.
ID
>
0
{
t
.
Error
(
"unexpected node"
,
node
.
String
())
}
for
i
:=
0
;
i
<=
len
(
nodes
);
i
++
{
node
:=
s
.
Apply
(
nodes
)
if
node
.
ID
!=
1
{
t
.
Error
(
"unexpected node"
,
node
.
String
())
}
}
}
func
TestFailFilter
(
t
*
testing
.
T
)
{
nodes
:=
[]
Node
{
Node
{
ID
:
1
,
marker
:
&
failMarker
{}},
Node
{
ID
:
2
,
marker
:
&
failMarker
{}},
Node
{
ID
:
3
,
marker
:
&
failMarker
{}},
}
filter
:=
&
FailFilter
{}
t
.
Log
(
filter
.
String
())
isEqual
:=
func
(
a
,
b
[]
Node
)
bool
{
if
a
==
nil
&&
b
==
nil
{
return
true
}
if
a
==
nil
||
b
==
nil
||
len
(
a
)
!=
len
(
b
)
{
return
false
}
for
i
:=
range
a
{
if
a
[
i
]
.
ID
!=
b
[
i
]
.
ID
{
return
false
}
}
return
true
}
if
v
:=
filter
.
Filter
(
nil
);
v
!=
nil
{
t
.
Error
(
"unexpected node"
,
v
)
}
if
v
:=
filter
.
Filter
(
nodes
);
!
isEqual
(
v
,
nodes
)
{
t
.
Error
(
"unexpected node"
,
v
)
}
filter
.
MaxFails
=
1
if
v
:=
filter
.
Filter
(
nodes
);
!
isEqual
(
v
,
nodes
)
{
t
.
Error
(
"unexpected node"
,
v
)
}
nodes
[
0
]
.
MarkDead
()
if
v
:=
filter
.
Filter
(
nodes
);
!
isEqual
(
v
,
nodes
)
{
t
.
Error
(
"unexpected node"
,
v
)
}
filter
.
FailTimeout
=
5
*
time
.
Second
if
v
:=
filter
.
Filter
(
nodes
);
isEqual
(
v
,
nodes
)
{
t
.
Error
(
"unexpected node"
,
v
)
}
nodes
[
1
]
.
MarkDead
()
nodes
[
2
]
.
MarkDead
()
if
v
:=
filter
.
Filter
(
nodes
);
len
(
v
)
>
0
{
t
.
Error
(
"unexpected node"
,
v
)
}
for
i
:=
range
nodes
{
nodes
[
i
]
.
ResetDead
()
}
if
v
:=
filter
.
Filter
(
nodes
);
!
isEqual
(
v
,
nodes
)
{
t
.
Error
(
"unexpected node"
,
v
)
}
}
func
TestSelector
(
t
*
testing
.
T
)
{
nodes
:=
[]
Node
{
Node
{
ID
:
1
,
marker
:
&
failMarker
{}},
Node
{
ID
:
2
,
marker
:
&
failMarker
{}},
Node
{
ID
:
3
,
marker
:
&
failMarker
{}},
}
selector
:=
&
defaultSelector
{}
if
_
,
err
:=
selector
.
Select
(
nil
);
err
!=
ErrNoneAvailable
{
t
.
Error
(
"got unexpected error:"
,
err
)
}
if
node
,
_
:=
selector
.
Select
(
nodes
);
node
.
ID
!=
1
{
t
.
Error
(
"unexpected node:"
,
node
)
}
if
node
,
_
:=
selector
.
Select
(
nodes
,
WithStrategy
(
NewStrategy
(
""
)),
WithFilter
(
&
FailFilter
{
MaxFails
:
1
,
FailTimeout
:
3
*
time
.
Second
}),
);
node
.
ID
!=
1
{
t
.
Error
(
"unexpected node:"
,
node
)
}
}
socks.go
View file @
47220e06
...
@@ -218,18 +218,12 @@ func (c *socks5Connector) Connect(conn net.Conn, addr string, options ...Connect
...
@@ -218,18 +218,12 @@ func (c *socks5Connector) Connect(conn net.Conn, addr string, options ...Connect
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
selector
:=
&
clientSelector
{
user
:=
opts
.
User
TLSConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
if
user
==
nil
{
User
:
c
.
User
,
user
=
c
.
User
}
}
selector
.
AddMethod
(
cc
,
err
:=
socks5Handshake
(
conn
,
opts
.
Selector
,
user
)
gosocks5
.
MethodNoAuth
,
if
err
!=
nil
{
gosocks5
.
MethodUserPass
,
MethodTLS
,
)
cc
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
if
err
:=
cc
.
Handleshake
();
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
conn
=
cc
conn
=
cc
...
@@ -292,7 +286,11 @@ func (c *socks5BindConnector) Connect(conn net.Conn, addr string, options ...Con
...
@@ -292,7 +286,11 @@ func (c *socks5BindConnector) Connect(conn net.Conn, addr string, options ...Con
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
cc
,
err
:=
socks5Handshake
(
conn
,
c
.
User
)
user
:=
opts
.
User
if
user
==
nil
{
user
=
c
.
User
}
cc
,
err
:=
socks5Handshake
(
conn
,
opts
.
Selector
,
user
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -442,7 +440,7 @@ func (tr *socks5MuxBindTransporter) initSession(conn net.Conn, addr string, opts
...
@@ -442,7 +440,7 @@ func (tr *socks5MuxBindTransporter) initSession(conn net.Conn, addr string, opts
opts
=
&
HandshakeOptions
{}
opts
=
&
HandshakeOptions
{}
}
}
cc
,
err
:=
socks5Handshake
(
conn
,
opts
.
User
)
cc
,
err
:=
socks5Handshake
(
conn
,
nil
,
opts
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -522,7 +520,11 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
...
@@ -522,7 +520,11 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
cc
,
err
:=
socks5Handshake
(
conn
,
c
.
User
)
user
:=
opts
.
User
if
user
==
nil
{
user
=
c
.
User
}
cc
,
err
:=
socks5Handshake
(
conn
,
opts
.
Selector
,
user
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -597,7 +599,11 @@ func (c *socks5UDPTunConnector) Connect(conn net.Conn, addr string, options ...C
...
@@ -597,7 +599,11 @@ func (c *socks5UDPTunConnector) Connect(conn net.Conn, addr string, options ...C
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
cc
,
err
:=
socks5Handshake
(
conn
,
c
.
User
)
user
:=
opts
.
User
if
user
==
nil
{
user
=
c
.
User
}
cc
,
err
:=
socks5Handshake
(
conn
,
opts
.
Selector
,
user
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -642,68 +648,6 @@ func (c *socks5UDPTunConnector) Connect(conn net.Conn, addr string, options ...C
...
@@ -642,68 +648,6 @@ func (c *socks5UDPTunConnector) Connect(conn net.Conn, addr string, options ...C
return
&
udpTunnelConn
{
Conn
:
conn
,
raddr
:
taddr
.
String
()},
nil
return
&
udpTunnelConn
{
Conn
:
conn
,
raddr
:
taddr
.
String
()},
nil
}
}
func
(
c
*
socks5UDPTunConnector
)
tunnelClientUDP
(
pc
net
.
PacketConn
,
cc
net
.
Conn
)
(
err
error
)
{
errc
:=
make
(
chan
error
,
2
)
go
func
()
{
b
:=
mPool
.
Get
()
.
([]
byte
)
defer
mPool
.
Put
(
b
)
for
{
n
,
addr
,
err
:=
pc
.
ReadFrom
(
b
)
if
err
!=
nil
{
log
.
Logf
(
"[udp-tun] %s <- %s : %s"
,
cc
.
RemoteAddr
(),
addr
,
err
)
errc
<-
err
return
}
// pipe from peer to tunnel
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
)
errc
<-
err
return
}
if
Debug
{
log
.
Logf
(
"[udp-tun] %s <<< %s length: %d"
,
cc
.
RemoteAddr
(),
dgram
.
Header
.
Addr
,
len
(
dgram
.
Data
))
}
}
}()
go
func
()
{
for
{
dgram
,
err
:=
gosocks5
.
ReadUDPDatagram
(
cc
)
if
err
!=
nil
{
log
.
Logf
(
"[udp-tun] %s -> 0 : %s"
,
cc
.
RemoteAddr
(),
err
)
errc
<-
err
return
}
// pipe from tunnel to peer
addr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
dgram
.
Header
.
Addr
.
String
())
if
err
!=
nil
{
continue
// drop silently
}
if
_
,
err
:=
pc
.
WriteTo
(
dgram
.
Data
,
addr
);
err
!=
nil
{
log
.
Logf
(
"[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
))
}
}
}()
select
{
case
err
=
<-
errc
:
}
return
}
type
socks4Connector
struct
{}
type
socks4Connector
struct
{}
// SOCKS4Connector creates a Connector for SOCKS4 proxy client.
// SOCKS4Connector creates a Connector for SOCKS4 proxy client.
...
@@ -1186,7 +1130,7 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
...
@@ -1186,7 +1130,7 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
}
}
defer
cc
.
Close
()
defer
cc
.
Close
()
cc
,
err
=
socks5Handshake
(
cc
,
h
.
options
.
Chain
.
LastNode
()
.
User
)
cc
,
err
=
socks5Handshake
(
cc
,
nil
,
h
.
options
.
Chain
.
LastNode
()
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
return
return
...
@@ -1450,7 +1394,7 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
...
@@ -1450,7 +1394,7 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
}
}
defer
cc
.
Close
()
defer
cc
.
Close
()
cc
,
err
=
socks5Handshake
(
cc
,
h
.
options
.
Chain
.
LastNode
()
.
User
)
cc
,
err
=
socks5Handshake
(
cc
,
nil
,
h
.
options
.
Chain
.
LastNode
()
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
return
return
...
@@ -1844,7 +1788,7 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
...
@@ -1844,7 +1788,7 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
HandshakeTimeout
))
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
HandshakeTimeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
defer
conn
.
SetDeadline
(
time
.
Time
{})
cc
,
err
:=
socks5Handshake
(
conn
,
chain
.
LastNode
()
.
User
)
cc
,
err
:=
socks5Handshake
(
conn
,
nil
,
chain
.
LastNode
()
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
conn
.
Close
()
conn
.
Close
()
return
nil
,
err
return
nil
,
err
...
@@ -1877,16 +1821,20 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
...
@@ -1877,16 +1821,20 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
return
conn
,
nil
return
conn
,
nil
}
}
func
socks5Handshake
(
conn
net
.
Conn
,
user
*
url
.
Userinfo
)
(
net
.
Conn
,
error
)
{
func
socks5Handshake
(
conn
net
.
Conn
,
selector
gosocks5
.
Selector
,
user
*
url
.
Userinfo
)
(
net
.
Conn
,
error
)
{
selector
:=
&
clientSelector
{
if
selector
==
nil
{
TLSConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
cs
:=
&
clientSelector
{
User
:
user
,
TLSConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
User
:
user
,
}
cs
.
AddMethod
(
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
,
MethodTLS
,
)
selector
=
cs
}
}
selector
.
AddMethod
(
gosocks5
.
MethodNoAuth
,
gosocks5
.
MethodUserPass
,
MethodTLS
,
)
cc
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
cc
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
if
err
:=
cc
.
Handleshake
();
err
!=
nil
{
if
err
:=
cc
.
Handleshake
();
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -1996,24 +1944,20 @@ type socks5UDPConn struct {
...
@@ -1996,24 +1944,20 @@ type socks5UDPConn struct {
taddr
net
.
Addr
taddr
net
.
Addr
}
}
func
(
c
*
socks5UDPConn
)
Read
(
b
[]
byte
)
(
int
,
error
)
{
func
(
c
*
socks5UDPConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
n
,
_
,
err
=
c
.
ReadFrom
(
b
)
return
}
func
(
c
*
socks5UDPConn
)
ReadFrom
(
b
[]
byte
)
(
n
int
,
addr
net
.
Addr
,
err
error
)
{
data
:=
mPool
.
Get
()
.
([]
byte
)
data
:=
mPool
.
Get
()
.
([]
byte
)
defer
mPool
.
Put
(
data
)
defer
mPool
.
Put
(
data
)
n
,
err
:
=
c
.
UDPConn
.
Read
(
data
)
n
,
err
=
c
.
UDPConn
.
Read
(
data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
err
return
}
}
dg
,
err
:=
gosocks5
.
ReadUDPDatagram
(
bytes
.
NewReader
(
data
[
:
n
]))
dg
,
err
:=
gosocks5
.
ReadUDPDatagram
(
bytes
.
NewReader
(
data
[
:
n
]))
if
err
!=
nil
{
return
0
,
err
}
return
copy
(
b
,
dg
.
Data
),
nil
}
func
(
c
*
socks5UDPConn
)
ReadFrom
(
b
[]
byte
)
(
n
int
,
addr
net
.
Addr
,
err
error
)
{
dg
,
err
:=
gosocks5
.
ReadUDPDatagram
(
c
.
UDPConn
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
...
@@ -2025,16 +1969,7 @@ func (c *socks5UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
...
@@ -2025,16 +1969,7 @@ func (c *socks5UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
}
}
func
(
c
*
socks5UDPConn
)
Write
(
b
[]
byte
)
(
int
,
error
)
{
func
(
c
*
socks5UDPConn
)
Write
(
b
[]
byte
)
(
int
,
error
)
{
addr
,
err
:=
gosocks5
.
NewAddr
(
c
.
taddr
.
String
())
return
c
.
WriteTo
(
b
,
c
.
taddr
)
if
err
!=
nil
{
return
0
,
err
}
h
:=
gosocks5
.
NewUDPHeader
(
0
,
0
,
addr
)
dg
:=
gosocks5
.
NewUDPDatagram
(
h
,
b
)
if
err
=
dg
.
Write
(
c
.
UDPConn
);
err
!=
nil
{
return
0
,
err
}
return
len
(
b
),
nil
}
}
func
(
c
*
socks5UDPConn
)
WriteTo
(
b
[]
byte
,
addr
net
.
Addr
)
(
int
,
error
)
{
func
(
c
*
socks5UDPConn
)
WriteTo
(
b
[]
byte
,
addr
net
.
Addr
)
(
int
,
error
)
{
...
...
socks_test.go
View file @
47220e06
...
@@ -550,7 +550,7 @@ func socks5UDPRoundtrip(t *testing.T, host string, data []byte) (err error) {
...
@@ -550,7 +550,7 @@ func socks5UDPRoundtrip(t *testing.T, host string, data []byte) (err error) {
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
return
udpRoundtrip
(
t
,
client
,
server
,
host
,
data
)
}
}
func
TestSOCKS5UDP
(
t
*
testing
.
T
)
{
func
TestSOCKS5UDP
(
t
*
testing
.
T
)
{
...
@@ -593,7 +593,7 @@ func BenchmarkSOCKS5UDP(b *testing.B) {
...
@@ -593,7 +593,7 @@ func BenchmarkSOCKS5UDP(b *testing.B) {
defer
server
.
Close
()
defer
server
.
Close
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
if
err
:=
udpRoundtrip
(
b
,
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
b
.
Error
(
err
)
}
}
}
}
...
@@ -679,7 +679,7 @@ func socks5UDPTunRoundtrip(t *testing.T, host string, data []byte) (err error) {
...
@@ -679,7 +679,7 @@ func socks5UDPTunRoundtrip(t *testing.T, host string, data []byte) (err error) {
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
return
udpRoundtrip
(
t
,
client
,
server
,
host
,
data
)
}
}
func
TestSOCKS5UDPTun
(
t
*
testing
.
T
)
{
func
TestSOCKS5UDPTun
(
t
*
testing
.
T
)
{
...
@@ -721,7 +721,7 @@ func BenchmarkSOCKS5UDPTun(b *testing.B) {
...
@@ -721,7 +721,7 @@ func BenchmarkSOCKS5UDPTun(b *testing.B) {
defer
server
.
Close
()
defer
server
.
Close
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
if
err
:=
udpRoundtrip
(
b
,
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
b
.
Error
(
err
)
}
}
}
}
...
...
ss.go
View file @
47220e06
...
@@ -47,9 +47,13 @@ func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...Connect
...
@@ -47,9 +47,13 @@ func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...Connect
}
}
var
method
,
password
string
var
method
,
password
string
if
c
.
Cipher
!=
nil
{
cp
:=
opts
.
User
method
=
c
.
Cipher
.
Username
()
if
cp
==
nil
{
password
,
_
=
c
.
Cipher
.
Password
()
cp
=
c
.
Cipher
}
if
cp
!=
nil
{
method
=
cp
.
Username
()
password
,
_
=
cp
.
Password
()
}
}
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
...
@@ -446,6 +450,10 @@ func (h *shadowUDPdHandler) transportUDP(sc net.Conn, cc net.PacketConn) error {
...
@@ -446,6 +450,10 @@ func (h *shadowUDPdHandler) transportUDP(sc net.Conn, cc net.PacketConn) error {
b
:=
mPool
.
Get
()
.
([]
byte
)
b
:=
mPool
.
Get
()
.
([]
byte
)
defer
mPool
.
Put
(
b
)
defer
mPool
.
Put
(
b
)
b
[
0
]
=
0
b
[
1
]
=
0
b
[
2
]
=
0
n
,
err
:=
sc
.
Read
(
b
[
3
:
])
// add rsv and frag fields to make it the standard SOCKS5 UDP datagram
n
,
err
:=
sc
.
Read
(
b
[
3
:
])
// add rsv and frag fields to make it the standard SOCKS5 UDP datagram
if
err
!=
nil
{
if
err
!=
nil
{
// log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
// log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
...
@@ -535,10 +543,14 @@ type shadowUDPConn struct {
...
@@ -535,10 +543,14 @@ type shadowUDPConn struct {
func
(
c
*
shadowUDPConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
func
(
c
*
shadowUDPConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
n
=
len
(
b
)
// force byte length consistent
n
=
len
(
b
)
// force byte length consistent
if
len
(
c
.
header
)
>
0
{
buf
:=
bytes
.
Buffer
{}
b
=
append
(
c
.
header
,
b
...
)
if
_
,
err
=
buf
.
Write
(
c
.
header
);
err
!=
nil
{
return
}
if
_
,
err
=
buf
.
Write
(
b
);
err
!=
nil
{
return
}
}
_
,
err
=
c
.
PacketConn
.
WriteTo
(
b
,
c
.
raddr
)
_
,
err
=
c
.
PacketConn
.
WriteTo
(
b
uf
.
Bytes
()
,
c
.
raddr
)
return
return
}
}
...
@@ -546,6 +558,10 @@ func (c *shadowUDPConn) Read(b []byte) (n int, err error) {
...
@@ -546,6 +558,10 @@ func (c *shadowUDPConn) Read(b []byte) (n int, err error) {
buf
:=
mPool
.
Get
()
.
([]
byte
)
buf
:=
mPool
.
Get
()
.
([]
byte
)
defer
mPool
.
Put
(
buf
)
defer
mPool
.
Put
(
buf
)
buf
[
0
]
=
0
buf
[
1
]
=
0
buf
[
2
]
=
0
n
,
_
,
err
=
c
.
PacketConn
.
ReadFrom
(
buf
[
3
:
])
n
,
_
,
err
=
c
.
PacketConn
.
ReadFrom
(
buf
[
3
:
])
if
err
!=
nil
{
if
err
!=
nil
{
return
return
...
...
ss_test.go
View file @
47220e06
package
gost
package
gost
import
(
import
(
"bytes"
"crypto/rand"
"crypto/rand"
"fmt"
"fmt"
"net/http/httptest"
"net/http/httptest"
...
@@ -299,14 +300,15 @@ func BenchmarkSSProxyParallel(b *testing.B) {
...
@@ -299,14 +300,15 @@ func BenchmarkSSProxyParallel(b *testing.B) {
})
})
}
}
func
shadowUDPRoundtrip
(
t
*
testing
.
T
,
host
string
,
data
[]
byte
)
error
{
func
shadowUDPRoundtrip
(
t
*
testing
.
T
,
host
string
,
data
[]
byte
,
ln
,
err
:=
ShadowUDPListener
(
"localhost:0"
,
url
.
UserPassword
(
"chacha20-ietf"
,
"123456"
),
0
)
clientInfo
*
url
.
Userinfo
,
serverInfo
*
url
.
Userinfo
)
error
{
ln
,
err
:=
ShadowUDPListener
(
"localhost:0"
,
serverInfo
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
client
:=
&
Client
{
client
:=
&
Client
{
Connector
:
ShadowUDPConnector
(
url
.
UserPassword
(
"chacha20-ietf"
,
"123456"
)
),
Connector
:
ShadowUDPConnector
(
clientInfo
),
Transporter
:
UDPTransporter
(),
Transporter
:
UDPTransporter
(),
}
}
...
@@ -318,19 +320,35 @@ func shadowUDPRoundtrip(t *testing.T, host string, data []byte) error {
...
@@ -318,19 +320,35 @@ func shadowUDPRoundtrip(t *testing.T, host string, data []byte) error {
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
return
udpRoundtrip
(
t
,
client
,
server
,
host
,
data
)
}
}
func
_TestShadowUDP
(
t
*
testing
.
T
)
{
func
TestShadowUDP
(
t
*
testing
.
T
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
rand
.
Read
(
sendData
)
err
:=
shadowUDPRoundtrip
(
t
,
udpSrv
.
Addr
(),
sendData
)
if
err
!=
nil
{
for
i
,
tc
:=
range
ssTests
{
t
.
Error
(
err
)
tc
:=
tc
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
err
:=
shadowUDPRoundtrip
(
t
,
udpSrv
.
Addr
(),
sendData
,
tc
.
clientCipher
,
tc
.
serverCipher
,
)
if
err
==
nil
{
if
!
tc
.
pass
{
t
.
Errorf
(
"#%d should failed"
,
i
)
}
}
else
{
// t.Logf("#%d %v", i, err)
if
tc
.
pass
{
t
.
Errorf
(
"#%d got error: %v"
,
i
,
err
)
}
}
})
}
}
}
}
...
@@ -343,7 +361,7 @@ func BenchmarkShadowUDP(b *testing.B) {
...
@@ -343,7 +361,7 @@ func BenchmarkShadowUDP(b *testing.B) {
sendData
:=
make
([]
byte
,
128
)
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
rand
.
Read
(
sendData
)
ln
,
err
:=
ShadowUDPListener
(
"localhost:0"
,
url
.
UserPassword
(
"chacha20-ietf"
,
"123456"
),
1000
*
time
.
Millisecond
)
ln
,
err
:=
ShadowUDPListener
(
"localhost:0"
,
url
.
UserPassword
(
"chacha20-ietf"
,
"123456"
),
0
)
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Error
(
err
)
b
.
Error
(
err
)
}
}
...
@@ -361,9 +379,32 @@ func BenchmarkShadowUDP(b *testing.B) {
...
@@ -361,9 +379,32 @@ func BenchmarkShadowUDP(b *testing.B) {
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
conn
,
err
:=
proxyConn
(
client
,
server
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
defer
conn
.
Close
()
conn
,
err
=
client
.
Connect
(
conn
,
udpSrv
.
Addr
())
if
err
!=
nil
{
return
}
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
1
*
time
.
Second
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
if
_
,
err
=
conn
.
Write
(
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
b
.
Error
(
err
)
}
}
recv
:=
make
([]
byte
,
len
(
sendData
))
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
b
.
Error
(
err
)
}
if
!
bytes
.
Equal
(
sendData
,
recv
)
{
b
.
Error
(
"data not equal"
)
}
}
}
}
}
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