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
445889c4
Commit
445889c4
authored
Dec 31, 2018
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add more test cases for socks5
parent
72d7850c
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1168 additions
and
417 deletions
+1168
-417
.travis.yml
.travis.yml
+2
-2
bypass_test.go
bypass_test.go
+11
-4
cmd/gost/.config/dns.txt
cmd/gost/.config/dns.txt
+5
-3
cmd/gost/cfg.go
cmd/gost/cfg.go
+2
-5
common_test.go
common_test.go
+126
-8
forward.go
forward.go
+0
-11
forward_test.go
forward_test.go
+0
-34
gost.go
gost.go
+47
-0
handler_test.go
handler_test.go
+16
-11
hosts_test.go
hosts_test.go
+10
-1
http2.go
http2.go
+3
-33
http_test.go
http_test.go
+0
-81
kcp.go
kcp.go
+5
-0
mux.go
mux.go
+6
-0
obfs.go
obfs.go
+1
-1
quic_test.go
quic_test.go
+55
-0
resolver.go
resolver.go
+33
-33
resolver_test.go
resolver_test.go
+8
-14
socks.go
socks.go
+344
-43
socks_test.go
socks_test.go
+348
-0
ss_test.go
ss_test.go
+18
-14
tls.go
tls.go
+12
-11
ws.go
ws.go
+116
-108
No files found.
.travis.yml
View file @
445889c4
...
@@ -5,8 +5,8 @@ go:
...
@@ -5,8 +5,8 @@ go:
install
:
true
install
:
true
script
:
script
:
-
env GO111MODULE=on
go test -race -v -coverprofile=coverage.txt -covermode=atomic
-
go test -race -v -coverprofile=coverage.txt -covermode=atomic
-
cd cmd/gost &&
env GO111MODULE=on
go build
-
cd cmd/gost && go build
after_success
:
after_success
:
-
bash <(curl -s https://codecov.io/bash)
-
bash <(curl -s https://codecov.io/bash)
bypass_test.go
View file @
445889c4
...
@@ -2,6 +2,7 @@ package gost
...
@@ -2,6 +2,7 @@ package gost
import
(
import
(
"bytes"
"bytes"
"fmt"
"io"
"io"
"testing"
"testing"
"time"
"time"
...
@@ -158,10 +159,13 @@ var bypassContainTests = []struct {
...
@@ -158,10 +159,13 @@ var bypassContainTests = []struct {
func
TestBypassContains
(
t
*
testing
.
T
)
{
func
TestBypassContains
(
t
*
testing
.
T
)
{
for
i
,
tc
:=
range
bypassContainTests
{
for
i
,
tc
:=
range
bypassContainTests
{
tc
:=
tc
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
bp
:=
NewBypassPatterns
(
tc
.
reversed
,
tc
.
patterns
...
)
bp
:=
NewBypassPatterns
(
tc
.
reversed
,
tc
.
patterns
...
)
if
bp
.
Contains
(
tc
.
addr
)
!=
tc
.
bypassed
{
if
bp
.
Contains
(
tc
.
addr
)
!=
tc
.
bypassed
{
t
.
Errorf
(
"#%d test failed: %v, %s"
,
i
,
tc
.
patterns
,
tc
.
addr
)
t
.
Errorf
(
"#%d test failed: %v, %s"
,
i
,
tc
.
patterns
,
tc
.
addr
)
}
}
})
}
}
}
}
...
@@ -244,6 +248,9 @@ func TestByapssReload(t *testing.T) {
...
@@ -244,6 +248,9 @@ func TestByapssReload(t *testing.T) {
}
}
if
tc
.
stopped
{
if
tc
.
stopped
{
bp
.
Stop
()
bp
.
Stop
()
if
bp
.
Period
()
>=
0
{
t
.
Errorf
(
"period of the stopped reloader should be minus value"
)
}
}
}
if
bp
.
Stopped
()
!=
tc
.
stopped
{
if
bp
.
Stopped
()
!=
tc
.
stopped
{
t
.
Errorf
(
"#%d test failed: stopped value should be %v, got %v"
,
t
.
Errorf
(
"#%d test failed: stopped value should be %v, got %v"
,
...
...
cmd/gost/.config/dns.txt
View file @
445889c4
# resolver timeout, default 30s.
# resolver timeout, default 30s.
timeout 10s
timeout 10s
# resolver cache TTL, default 60s, minus value means that cache is disabled.
# resolver cache TTL,
ttl 300s
# minus value means that cache is disabled,
# default to the TTL in DNS server response.
# ttl 300s
# period for live reloading
# period for live reloading
reload 10s
reload 10s
# ip[:port] [protocol] [hostname]
# ip[:port] [protocol] [hostname]
https://1.0.0.1/dns-query
1.1.1.1:853 tls cloudflare-dns.com
1.1.1.1:853 tls cloudflare-dns.com
https://1.0.0.1/dns-query https
8.8.8.8
8.8.8.8
8.8.8.8 tcp
8.8.8.8 tcp
1.1.1.1 udp
1.1.1.1 udp
...
...
cmd/gost/cfg.go
View file @
445889c4
...
@@ -10,7 +10,6 @@ import (
...
@@ -10,7 +10,6 @@ import (
"net/url"
"net/url"
"os"
"os"
"strings"
"strings"
"time"
"github.com/ginuerzh/gost"
"github.com/ginuerzh/gost"
)
)
...
@@ -196,8 +195,6 @@ func parseResolver(cfg string) gost.Resolver {
...
@@ -196,8 +195,6 @@ func parseResolver(cfg string) gost.Resolver {
if
cfg
==
""
{
if
cfg
==
""
{
return
nil
return
nil
}
}
timeout
:=
30
*
time
.
Second
ttl
:=
60
*
time
.
Second
var
nss
[]
gost
.
NameServer
var
nss
[]
gost
.
NameServer
f
,
err
:=
os
.
Open
(
cfg
)
f
,
err
:=
os
.
Open
(
cfg
)
...
@@ -237,11 +234,11 @@ func parseResolver(cfg string) gost.Resolver {
...
@@ -237,11 +234,11 @@ func parseResolver(cfg string) gost.Resolver {
}
}
}
}
}
}
return
gost
.
NewResolver
(
timeout
,
ttl
,
nss
...
)
return
gost
.
NewResolver
(
0
,
nss
...
)
}
}
defer
f
.
Close
()
defer
f
.
Close
()
resolver
:=
gost
.
NewResolver
(
timeout
,
ttl
)
resolver
:=
gost
.
NewResolver
(
0
)
resolver
.
Reload
(
f
)
resolver
.
Reload
(
f
)
go
gost
.
PeriodReload
(
resolver
,
cfg
)
go
gost
.
PeriodReload
(
resolver
,
cfg
)
...
...
common_test.go
View file @
445889c4
package
gost
package
gost
import
(
import
(
"bufio"
"bytes"
"bytes"
"crypto/tls"
"crypto/tls"
"errors"
"fmt"
"fmt"
"io"
"io"
"io/ioutil"
"net"
"net"
"net/http"
"net/http"
"net/url"
"sync"
"sync"
"time"
"time"
)
)
...
@@ -37,6 +41,110 @@ var (
...
@@ -37,6 +41,110 @@ var (
})
})
)
)
// proxyConn obtains a connection to the proxy server.
func
proxyConn
(
client
*
Client
,
server
*
Server
)
(
net
.
Conn
,
error
)
{
conn
,
err
:=
client
.
Dial
(
server
.
Addr
()
.
String
())
if
err
!=
nil
{
return
nil
,
err
}
cc
,
err
:=
client
.
Handshake
(
conn
,
AddrHandshakeOption
(
server
.
Addr
()
.
String
()))
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
return
cc
,
nil
}
// httpRoundtrip does a HTTP request-response roundtrip, and checks the data received.
func
httpRoundtrip
(
conn
net
.
Conn
,
targetURL
string
,
data
[]
byte
)
(
err
error
)
{
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
targetURL
,
bytes
.
NewReader
(
data
),
)
if
err
!=
nil
{
return
}
if
err
=
req
.
Write
(
conn
);
err
!=
nil
{
return
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
if
err
!=
nil
{
return
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
errors
.
New
(
resp
.
Status
)
}
recv
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
}
if
!
bytes
.
Equal
(
data
,
recv
)
{
return
fmt
.
Errorf
(
"data not equal"
)
}
return
}
func
udpRoundtrip
(
client
*
Client
,
server
*
Server
,
host
string
,
data
[]
byte
)
(
err
error
)
{
conn
,
err
:=
proxyConn
(
client
,
server
)
if
err
!=
nil
{
return
}
defer
conn
.
Close
()
conn
,
err
=
client
.
Connect
(
conn
,
host
)
if
err
!=
nil
{
return
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
3
*
time
.
Second
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
if
_
,
err
=
conn
.
Write
(
data
);
err
!=
nil
{
return
}
recv
:=
make
([]
byte
,
len
(
data
))
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
return
}
if
!
bytes
.
Equal
(
data
,
recv
)
{
return
fmt
.
Errorf
(
"data not equal"
)
}
return
}
func
proxyRoundtrip
(
client
*
Client
,
server
*
Server
,
targetURL
string
,
data
[]
byte
)
(
err
error
)
{
conn
,
err
:=
proxyConn
(
client
,
server
)
if
err
!=
nil
{
return
err
}
defer
conn
.
Close
()
u
,
err
:=
url
.
Parse
(
targetURL
)
if
err
!=
nil
{
return
}
conn
,
err
=
client
.
Connect
(
conn
,
u
.
Host
)
if
err
!=
nil
{
return
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
500
*
time
.
Millisecond
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
return
httpRoundtrip
(
conn
,
targetURL
,
data
)
}
type
udpRequest
struct
{
type
udpRequest
struct
{
Body
io
.
Reader
Body
io
.
Reader
RemoteAddr
string
RemoteAddr
string
...
@@ -60,6 +168,7 @@ type udpTestServer struct {
...
@@ -60,6 +168,7 @@ type udpTestServer struct {
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
{}
}
}
func
newUDPTestServer
(
handler
udpHandlerFunc
)
*
udpTestServer
{
func
newUDPTestServer
(
handler
udpHandlerFunc
)
*
udpTestServer
{
...
@@ -68,9 +177,13 @@ func newUDPTestServer(handler udpHandlerFunc) *udpTestServer {
...
@@ -68,9 +177,13 @@ 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
{}),
}
}
}
}
...
@@ -83,7 +196,7 @@ func (s *udpTestServer) serve() {
...
@@ -83,7 +196,7 @@ func (s *udpTestServer) serve() {
data
:=
make
([]
byte
,
1024
)
data
:=
make
([]
byte
,
1024
)
n
,
raddr
,
err
:=
s
.
ln
.
ReadFrom
(
data
)
n
,
raddr
,
err
:=
s
.
ln
.
ReadFrom
(
data
)
if
err
!=
nil
{
if
err
!=
nil
{
return
break
}
}
if
s
.
handler
!=
nil
{
if
s
.
handler
!=
nil
{
s
.
wg
.
Add
(
1
)
s
.
wg
.
Add
(
1
)
...
@@ -101,6 +214,9 @@ func (s *udpTestServer) serve() {
...
@@ -101,6 +214,9 @@ func (s *udpTestServer) serve() {
}()
}()
}
}
}
}
// signal the listener has been exited.
close
(
s
.
exitChan
)
}
}
func
(
s
*
udpTestServer
)
Addr
()
string
{
func
(
s
*
udpTestServer
)
Addr
()
string
{
...
@@ -119,6 +235,8 @@ func (s *udpTestServer) Close() error {
...
@@ -119,6 +235,8 @@ func (s *udpTestServer) Close() error {
s
.
closed
=
true
s
.
closed
=
true
s
.
mu
.
Unlock
()
s
.
mu
.
Unlock
()
<-
s
.
exitChan
s
.
wg
.
Wait
()
s
.
wg
.
Wait
()
return
err
return
err
...
...
forward.go
View file @
445889c4
...
@@ -662,10 +662,6 @@ func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
...
@@ -662,10 +662,6 @@ func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
go
ln
.
listenLoop
()
go
ln
.
listenLoop
()
// if err = <-ln.errChan; err != nil {
// ln.Close()
// }
return
ln
,
err
return
ln
,
err
}
}
...
@@ -680,17 +676,10 @@ func (l *tcpRemoteForwardListener) isChainValid() bool {
...
@@ -680,17 +676,10 @@ func (l *tcpRemoteForwardListener) isChainValid() bool {
func
(
l
*
tcpRemoteForwardListener
)
listenLoop
()
{
func
(
l
*
tcpRemoteForwardListener
)
listenLoop
()
{
var
tempDelay
time
.
Duration
var
tempDelay
time
.
Duration
// var once sync.Once
for
{
for
{
conn
,
err
:=
l
.
accept
()
conn
,
err
:=
l
.
accept
()
// once.Do(func() {
// l.errChan <- err
// log.Log("once.Do error:", err)
// close(l.errChan)
// })
select
{
select
{
case
<-
l
.
closed
:
case
<-
l
.
closed
:
if
conn
!=
nil
{
if
conn
!=
nil
{
...
...
forward_test.go
View file @
445889c4
package
gost
package
gost
import
(
import
(
"bytes"
"crypto/rand"
"crypto/rand"
"fmt"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"testing"
"testing"
"time"
)
)
func
tcpDirectForwardRoundtrip
(
targetURL
string
,
data
[]
byte
)
error
{
func
tcpDirectForwardRoundtrip
(
targetURL
string
,
data
[]
byte
)
error
{
...
@@ -122,37 +119,6 @@ func BenchmarkTCPDirectForwardParallel(b *testing.B) {
...
@@ -122,37 +119,6 @@ func BenchmarkTCPDirectForwardParallel(b *testing.B) {
})
})
}
}
func
udpRoundtrip
(
client
*
Client
,
server
*
Server
,
host
string
,
data
[]
byte
)
(
err
error
)
{
conn
,
err
:=
proxyConn
(
client
,
server
)
if
err
!=
nil
{
return
}
defer
conn
.
Close
()
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
1
*
time
.
Second
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
conn
,
err
=
client
.
Connect
(
conn
,
host
)
if
err
!=
nil
{
return
}
if
_
,
err
=
conn
.
Write
(
data
);
err
!=
nil
{
return
}
recv
:=
make
([]
byte
,
len
(
data
))
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
return
}
if
!
bytes
.
Equal
(
data
,
recv
)
{
return
fmt
.
Errorf
(
"data not equal"
)
}
return
}
func
udpDirectForwardRoundtrip
(
host
string
,
data
[]
byte
)
error
{
func
udpDirectForwardRoundtrip
(
host
string
,
data
[]
byte
)
error
{
ln
,
err
:=
UDPDirectForwardListener
(
"localhost:0"
,
0
)
ln
,
err
:=
UDPDirectForwardListener
(
"localhost:0"
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
gost.go
View file @
445889c4
...
@@ -7,8 +7,10 @@ import (
...
@@ -7,8 +7,10 @@ import (
"crypto/x509"
"crypto/x509"
"crypto/x509/pkix"
"crypto/x509/pkix"
"encoding/pem"
"encoding/pem"
"errors"
"io"
"io"
"math/big"
"math/big"
"net"
"sync"
"sync"
"time"
"time"
...
@@ -137,3 +139,48 @@ func (rw *readWriter) Read(p []byte) (n int, err error) {
...
@@ -137,3 +139,48 @@ func (rw *readWriter) Read(p []byte) (n int, err error) {
func
(
rw
*
readWriter
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
func
(
rw
*
readWriter
)
Write
(
p
[]
byte
)
(
n
int
,
err
error
)
{
return
rw
.
w
.
Write
(
p
)
return
rw
.
w
.
Write
(
p
)
}
}
var
(
nopClientConn
=
&
nopConn
{}
)
// a nop connection implements net.Conn,
// it does nothing.
type
nopConn
struct
{}
func
(
c
*
nopConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
0
,
&
net
.
OpError
{
Op
:
"read"
,
Net
:
"nop"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"read not supported"
)}
}
func
(
c
*
nopConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
0
,
&
net
.
OpError
{
Op
:
"write"
,
Net
:
"nop"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"write not supported"
)}
}
func
(
c
*
nopConn
)
Close
()
error
{
return
nil
}
func
(
c
*
nopConn
)
LocalAddr
()
net
.
Addr
{
return
nil
}
func
(
c
*
nopConn
)
RemoteAddr
()
net
.
Addr
{
return
nil
}
func
(
c
*
nopConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"nop"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
nopConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"nop"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
nopConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"nop"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
// Accepter represents a network endpoint that can accept connection from peer.
type
Accepter
interface
{
Accept
()
(
net
.
Conn
,
error
)
}
handler_test.go
View file @
445889c4
...
@@ -18,7 +18,6 @@ func autoHTTPProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Useri
...
@@ -18,7 +18,6 @@ func autoHTTPProxyRoundtrip(targetURL string, data []byte, clientInfo *url.Useri
Connector
:
HTTPConnector
(
clientInfo
),
Connector
:
HTTPConnector
(
clientInfo
),
Transporter
:
TCPTransporter
(),
Transporter
:
TCPTransporter
(),
}
}
server
:=
&
Server
{
server
:=
&
Server
{
Listener
:
ln
,
Listener
:
ln
,
Handler
:
AutoHandler
(
Handler
:
AutoHandler
(
...
@@ -111,7 +110,7 @@ func TestAutoSOCKS5Proxy(t *testing.T) {
...
@@ -111,7 +110,7 @@ func TestAutoSOCKS5Proxy(t *testing.T) {
}
}
}
}
func
autoSOCKS4ProxyRoundtrip
(
targetURL
string
,
data
[]
byte
)
error
{
func
autoSOCKS4ProxyRoundtrip
(
targetURL
string
,
data
[]
byte
,
options
...
HandlerOption
)
error
{
ln
,
err
:=
TCPListener
(
""
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -124,7 +123,7 @@ func autoSOCKS4ProxyRoundtrip(targetURL string, data []byte) error {
...
@@ -124,7 +123,7 @@ func autoSOCKS4ProxyRoundtrip(targetURL string, data []byte) error {
server
:=
&
Server
{
server
:=
&
Server
{
Listener
:
ln
,
Listener
:
ln
,
Handler
:
AutoHandler
(),
Handler
:
AutoHandler
(
options
...
),
}
}
go
server
.
Run
()
go
server
.
Run
()
defer
server
.
Close
()
defer
server
.
Close
()
...
@@ -139,14 +138,17 @@ func TestAutoSOCKS4Proxy(t *testing.T) {
...
@@ -139,14 +138,17 @@ func TestAutoSOCKS4Proxy(t *testing.T) {
sendData
:=
make
([]
byte
,
128
)
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
rand
.
Read
(
sendData
)
err
:=
autoSOCKS4ProxyRoundtrip
(
httpSrv
.
URL
,
sendData
)
if
err
:=
autoSOCKS4ProxyRoundtrip
(
httpSrv
.
URL
,
sendData
);
err
!=
nil
{
// t.Logf("#%d %v", i, err)
if
err
!=
nil
{
t
.
Errorf
(
"got error: %v"
,
err
)
t
.
Errorf
(
"got error: %v"
,
err
)
}
}
if
err
:=
autoSOCKS4ProxyRoundtrip
(
httpSrv
.
URL
,
sendData
,
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)));
err
==
nil
{
t
.
Errorf
(
"authentication required auto handler for SOCKS4 should failed"
)
}
}
}
func
autoSocks4aProxyRoundtrip
(
targetURL
string
,
data
[]
byte
)
error
{
func
autoSocks4aProxyRoundtrip
(
targetURL
string
,
data
[]
byte
,
options
...
HandlerOption
)
error
{
ln
,
err
:=
TCPListener
(
""
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -159,7 +161,7 @@ func autoSocks4aProxyRoundtrip(targetURL string, data []byte) error {
...
@@ -159,7 +161,7 @@ func autoSocks4aProxyRoundtrip(targetURL string, data []byte) error {
server
:=
&
Server
{
server
:=
&
Server
{
Listener
:
ln
,
Listener
:
ln
,
Handler
:
AutoHandler
(),
Handler
:
AutoHandler
(
options
...
),
}
}
go
server
.
Run
()
go
server
.
Run
()
...
@@ -175,11 +177,14 @@ func TestAutoSOCKS4AProxy(t *testing.T) {
...
@@ -175,11 +177,14 @@ func TestAutoSOCKS4AProxy(t *testing.T) {
sendData
:=
make
([]
byte
,
128
)
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
rand
.
Read
(
sendData
)
err
:=
autoSocks4aProxyRoundtrip
(
httpSrv
.
URL
,
sendData
)
if
err
:=
autoSocks4aProxyRoundtrip
(
httpSrv
.
URL
,
sendData
);
err
!=
nil
{
// t.Logf("#%d %v", i, err)
if
err
!=
nil
{
t
.
Errorf
(
"got error: %v"
,
err
)
t
.
Errorf
(
"got error: %v"
,
err
)
}
}
if
err
:=
autoSocks4aProxyRoundtrip
(
httpSrv
.
URL
,
sendData
,
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)));
err
==
nil
{
t
.
Errorf
(
"authentication required auto handler for SOCKS4A should failed"
)
}
}
}
func
autoSSProxyRoundtrip
(
targetURL
string
,
data
[]
byte
,
clientInfo
*
url
.
Userinfo
,
serverInfo
*
url
.
Userinfo
)
error
{
func
autoSSProxyRoundtrip
(
targetURL
string
,
data
[]
byte
,
clientInfo
*
url
.
Userinfo
,
serverInfo
*
url
.
Userinfo
)
error
{
...
...
hosts_test.go
View file @
445889c4
...
@@ -28,7 +28,8 @@ var hostsLookupTests = []struct {
...
@@ -28,7 +28,8 @@ var hostsLookupTests = []struct {
func
TestHostsLookup
(
t
*
testing
.
T
)
{
func
TestHostsLookup
(
t
*
testing
.
T
)
{
for
i
,
tc
:=
range
hostsLookupTests
{
for
i
,
tc
:=
range
hostsLookupTests
{
hosts
:=
NewHosts
(
tc
.
hosts
...
)
hosts
:=
NewHosts
()
hosts
.
AddHost
(
tc
.
hosts
...
)
ip
:=
hosts
.
Lookup
(
tc
.
host
)
ip
:=
hosts
.
Lookup
(
tc
.
host
)
if
!
ip
.
Equal
(
tc
.
ip
)
{
if
!
ip
.
Equal
(
tc
.
ip
)
{
t
.
Errorf
(
"#%d test failed: lookup should be %s, got %s"
,
i
,
tc
.
ip
,
ip
)
t
.
Errorf
(
"#%d test failed: lookup should be %s, got %s"
,
i
,
tc
.
ip
,
ip
)
...
@@ -61,6 +62,11 @@ var HostsReloadTests = []struct {
...
@@ -61,6 +62,11 @@ var HostsReloadTests = []struct {
host
:
"example.com"
,
host
:
"example.com"
,
ip
:
nil
,
ip
:
nil
,
},
},
{
r
:
bytes
.
NewBufferString
(
"#reload 10s
\n
invalid.ip.addr example.com"
),
period
:
0
,
ip
:
nil
,
},
{
{
r
:
bytes
.
NewBufferString
(
"reload 10s
\n
192.168.1.1"
),
r
:
bytes
.
NewBufferString
(
"reload 10s
\n
192.168.1.1"
),
period
:
10
*
time
.
Second
,
period
:
10
*
time
.
Second
,
...
@@ -112,6 +118,9 @@ func TestHostsReload(t *testing.T) {
...
@@ -112,6 +118,9 @@ func TestHostsReload(t *testing.T) {
}
}
if
tc
.
stopped
{
if
tc
.
stopped
{
hosts
.
Stop
()
hosts
.
Stop
()
if
hosts
.
Period
()
>=
0
{
t
.
Errorf
(
"period of the stopped reloader should be minus value"
)
}
}
}
if
hosts
.
Stopped
()
!=
tc
.
stopped
{
if
hosts
.
Stopped
()
!=
tc
.
stopped
{
t
.
Errorf
(
"#%d test failed: stopped value should be %v, got %v"
,
t
.
Errorf
(
"#%d test failed: stopped value should be %v, got %v"
,
...
...
http2.go
View file @
445889c4
...
@@ -569,12 +569,13 @@ func HTTP2Listener(addr string, config *tls.Config) (Listener, error) {
...
@@ -569,12 +569,13 @@ func HTTP2Listener(addr string, config *tls.Config) (Listener, error) {
}
}
l
.
server
=
server
l
.
server
=
server
ln
,
err
:=
tls
.
Listen
(
"tcp"
,
addr
,
config
)
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
l
.
addr
=
ln
.
Addr
()
l
.
addr
=
ln
.
Addr
()
ln
=
tls
.
NewListener
(
tcpKeepAliveListener
{
ln
.
(
*
net
.
TCPListener
)},
config
)
go
func
()
{
go
func
()
{
err
:=
server
.
Serve
(
ln
)
err
:=
server
.
Serve
(
ln
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -875,42 +876,11 @@ func (c *http2ServerConn) SetWriteDeadline(t time.Time) error {
...
@@ -875,42 +876,11 @@ func (c *http2ServerConn) SetWriteDeadline(t time.Time) error {
// a dummy HTTP2 client conn used by HTTP2 client connector
// a dummy HTTP2 client conn used by HTTP2 client connector
type
http2ClientConn
struct
{
type
http2ClientConn
struct
{
nopConn
addr
string
addr
string
client
*
http
.
Client
client
*
http
.
Client
}
}
func
(
c
*
http2ClientConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
0
,
&
net
.
OpError
{
Op
:
"read"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"read not supported"
)}
}
func
(
c
*
http2ClientConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
0
,
&
net
.
OpError
{
Op
:
"write"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"write not supported"
)}
}
func
(
c
*
http2ClientConn
)
Close
()
error
{
return
nil
}
func
(
c
*
http2ClientConn
)
LocalAddr
()
net
.
Addr
{
return
nil
}
func
(
c
*
http2ClientConn
)
RemoteAddr
()
net
.
Addr
{
return
nil
}
func
(
c
*
http2ClientConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
http2ClientConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
func
(
c
*
http2ClientConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"http2"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
}
type
flushWriter
struct
{
type
flushWriter
struct
{
w
io
.
Writer
w
io
.
Writer
}
}
...
...
http_test.go
View file @
445889c4
package
gost
package
gost
import
(
import
(
"bufio"
"bytes"
"crypto/rand"
"crypto/rand"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"testing"
"testing"
"time"
)
)
// proxyConn obtains a connection to the proxy server.
func
proxyConn
(
client
*
Client
,
server
*
Server
)
(
net
.
Conn
,
error
)
{
conn
,
err
:=
client
.
Dial
(
server
.
Addr
()
.
String
())
if
err
!=
nil
{
return
nil
,
err
}
cc
,
err
:=
client
.
Handshake
(
conn
,
AddrHandshakeOption
(
server
.
Addr
()
.
String
()))
if
err
!=
nil
{
conn
.
Close
()
return
nil
,
err
}
return
cc
,
nil
}
// httpRoundtrip does a HTTP request-response roundtrip, and checks the data received.
func
httpRoundtrip
(
conn
net
.
Conn
,
targetURL
string
,
data
[]
byte
)
(
err
error
)
{
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
targetURL
,
bytes
.
NewReader
(
data
),
)
if
err
!=
nil
{
return
}
if
err
=
req
.
Write
(
conn
);
err
!=
nil
{
return
}
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
conn
),
req
)
if
err
!=
nil
{
return
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
errors
.
New
(
resp
.
Status
)
}
recv
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
}
if
!
bytes
.
Equal
(
data
,
recv
)
{
return
fmt
.
Errorf
(
"data not equal"
)
}
return
}
func
proxyRoundtrip
(
client
*
Client
,
server
*
Server
,
targetURL
string
,
data
[]
byte
)
(
err
error
)
{
conn
,
err
:=
proxyConn
(
client
,
server
)
if
err
!=
nil
{
return
err
}
defer
conn
.
Close
()
u
,
err
:=
url
.
Parse
(
targetURL
)
if
err
!=
nil
{
return
}
conn
,
err
=
client
.
Connect
(
conn
,
u
.
Host
)
if
err
!=
nil
{
return
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
500
*
time
.
Millisecond
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
return
httpRoundtrip
(
conn
,
targetURL
,
data
)
}
var
httpProxyTests
=
[]
struct
{
var
httpProxyTests
=
[]
struct
{
cliUser
*
url
.
Userinfo
cliUser
*
url
.
Userinfo
srvUsers
[]
*
url
.
Userinfo
srvUsers
[]
*
url
.
Userinfo
...
...
kcp.go
View file @
445889c4
...
@@ -123,6 +123,11 @@ func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Con
...
@@ -123,6 +123,11 @@ func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Con
defer
tr
.
sessionMutex
.
Unlock
()
defer
tr
.
sessionMutex
.
Unlock
()
session
,
ok
:=
tr
.
sessions
[
addr
]
session
,
ok
:=
tr
.
sessions
[
addr
]
if
session
!=
nil
&&
session
.
session
!=
nil
&&
session
.
session
.
IsClosed
()
{
session
.
Close
()
delete
(
tr
.
sessions
,
addr
)
// session is dead
ok
=
false
}
if
!
ok
{
if
!
ok
{
timeout
:=
opts
.
Timeout
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
if
timeout
<=
0
{
...
...
mux.go
View file @
445889c4
...
@@ -45,10 +45,16 @@ func (session *muxSession) Accept() (net.Conn, error) {
...
@@ -45,10 +45,16 @@ func (session *muxSession) Accept() (net.Conn, error) {
}
}
func
(
session
*
muxSession
)
Close
()
error
{
func
(
session
*
muxSession
)
Close
()
error
{
if
session
.
session
==
nil
{
return
nil
}
return
session
.
session
.
Close
()
return
session
.
session
.
Close
()
}
}
func
(
session
*
muxSession
)
IsClosed
()
bool
{
func
(
session
*
muxSession
)
IsClosed
()
bool
{
if
session
.
session
==
nil
{
return
true
}
return
session
.
session
.
IsClosed
()
return
session
.
session
.
IsClosed
()
}
}
...
...
obfs.go
View file @
445889c4
...
@@ -331,7 +331,7 @@ func Obfs4Listener(addr string) (Listener, error) {
...
@@ -331,7 +331,7 @@ func Obfs4Listener(addr string) (Listener, error) {
}
}
l
:=
&
obfs4Listener
{
l
:=
&
obfs4Listener
{
addr
:
addr
,
addr
:
addr
,
Listener
:
ln
,
Listener
:
tcpKeepAliveListener
{
ln
.
(
*
net
.
TCPListener
)}
,
}
}
return
l
,
nil
return
l
,
nil
}
}
...
...
quic_test.go
View file @
445889c4
...
@@ -2,6 +2,7 @@ package gost
...
@@ -2,6 +2,7 @@ package gost
import
(
import
(
"crypto/rand"
"crypto/rand"
"crypto/sha256"
"fmt"
"fmt"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
...
@@ -405,3 +406,57 @@ func TestQUICForwardTunnel(t *testing.T) {
...
@@ -405,3 +406,57 @@ func TestQUICForwardTunnel(t *testing.T) {
t
.
Error
(
err
)
t
.
Error
(
err
)
}
}
}
}
func
httpOverCipherQUICRoundtrip
(
targetURL
string
,
data
[]
byte
,
clientInfo
*
url
.
Userinfo
,
serverInfo
[]
*
url
.
Userinfo
)
error
{
sum
:=
sha256
.
Sum256
([]
byte
(
"12345678"
))
cfg
:=
&
QUICConfig
{
Key
:
sum
[
:
],
}
ln
,
err
:=
QUICListener
(
"localhost:0"
,
cfg
)
if
err
!=
nil
{
return
err
}
client
:=
&
Client
{
Connector
:
HTTPConnector
(
clientInfo
),
Transporter
:
QUICTransporter
(
cfg
),
}
server
:=
&
Server
{
Listener
:
ln
,
Handler
:
HTTPHandler
(
UsersHandlerOption
(
serverInfo
...
),
),
}
go
server
.
Run
()
defer
server
.
Close
()
return
proxyRoundtrip
(
client
,
server
,
targetURL
,
data
)
}
func
TestHTTPOverCipherQUIC
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
for
i
,
tc
:=
range
httpProxyTests
{
err
:=
httpOverCipherQUICRoundtrip
(
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 @
445889c4
...
@@ -23,8 +23,6 @@ import (
...
@@ -23,8 +23,6 @@ import (
var
(
var
(
// DefaultResolverTimeout is the default timeout for name resolution.
// DefaultResolverTimeout is the default timeout for name resolution.
DefaultResolverTimeout
=
5
*
time
.
Second
DefaultResolverTimeout
=
5
*
time
.
Second
// DefaultResolverTTL is the default cache TTL for name resolution.
DefaultResolverTTL
=
1
*
time
.
Hour
)
)
// Resolver is a name resolver for domain name.
// Resolver is a name resolver for domain name.
...
@@ -53,13 +51,18 @@ type NameServer struct {
...
@@ -53,13 +51,18 @@ type NameServer struct {
// Init initializes the name server.
// Init initializes the name server.
func
(
ns
*
NameServer
)
Init
()
error
{
func
(
ns
*
NameServer
)
Init
()
error
{
timeout
:=
ns
.
Timeout
if
timeout
<=
0
{
timeout
=
DefaultResolverTimeout
}
switch
strings
.
ToLower
(
ns
.
Protocol
)
{
switch
strings
.
ToLower
(
ns
.
Protocol
)
{
case
"tcp"
:
case
"tcp"
:
ns
.
exchanger
=
&
dnsExchanger
{
ns
.
exchanger
=
&
dnsExchanger
{
endpoint
:
ns
.
Addr
,
endpoint
:
ns
.
Addr
,
client
:
&
dns
.
Client
{
client
:
&
dns
.
Client
{
Net
:
"tcp"
,
Net
:
"tcp"
,
Timeout
:
ns
.
T
imeout
,
Timeout
:
t
imeout
,
},
},
}
}
case
"tls"
:
case
"tls"
:
...
@@ -74,7 +77,7 @@ func (ns *NameServer) Init() error {
...
@@ -74,7 +77,7 @@ func (ns *NameServer) Init() error {
endpoint
:
ns
.
Addr
,
endpoint
:
ns
.
Addr
,
client
:
&
dns
.
Client
{
client
:
&
dns
.
Client
{
Net
:
"tcp-tls"
,
Net
:
"tcp-tls"
,
Timeout
:
ns
.
T
imeout
,
Timeout
:
t
imeout
,
TLSConfig
:
cfg
,
TLSConfig
:
cfg
,
},
},
}
}
...
@@ -95,7 +98,7 @@ func (ns *NameServer) Init() error {
...
@@ -95,7 +98,7 @@ func (ns *NameServer) Init() error {
endpoint
:
u
,
endpoint
:
u
,
client
:
&
http
.
Client
{
client
:
&
http
.
Client
{
Transport
:
transport
,
Transport
:
transport
,
Timeout
:
ns
.
T
imeout
,
Timeout
:
t
imeout
,
},
},
}
}
case
"udp"
:
case
"udp"
:
...
@@ -105,7 +108,7 @@ func (ns *NameServer) Init() error {
...
@@ -105,7 +108,7 @@ func (ns *NameServer) Init() error {
endpoint
:
ns
.
Addr
,
endpoint
:
ns
.
Addr
,
client
:
&
dns
.
Client
{
client
:
&
dns
.
Client
{
Net
:
"udp"
,
Net
:
"udp"
,
Timeout
:
ns
.
T
imeout
,
Timeout
:
t
imeout
,
},
},
}
}
}
}
...
@@ -125,15 +128,9 @@ func (ns NameServer) String() string {
...
@@ -125,15 +128,9 @@ func (ns NameServer) String() string {
return
fmt
.
Sprintf
(
"%s/%s"
,
addr
,
prot
)
return
fmt
.
Sprintf
(
"%s/%s"
,
addr
,
prot
)
}
}
type
resolverCacheItem
struct
{
IPs
[]
net
.
IP
ts
int64
}
type
resolver
struct
{
type
resolver
struct
{
Servers
[]
NameServer
Servers
[]
NameServer
mCache
*
sync
.
Map
mCache
*
sync
.
Map
Timeout
time
.
Duration
TTL
time
.
Duration
TTL
time
.
Duration
period
time
.
Duration
period
time
.
Duration
domain
string
domain
string
...
@@ -142,22 +139,14 @@ type resolver struct {
...
@@ -142,22 +139,14 @@ type resolver struct {
}
}
// NewResolver create a new Resolver with the given name servers and resolution timeout.
// NewResolver create a new Resolver with the given name servers and resolution timeout.
func
NewResolver
(
timeout
,
ttl
time
.
Duration
,
servers
...
NameServer
)
ReloadResolver
{
func
NewResolver
(
ttl
time
.
Duration
,
servers
...
NameServer
)
ReloadResolver
{
r
:=
newResolver
(
timeout
,
ttl
,
servers
...
)
r
:=
newResolver
(
ttl
,
servers
...
)
if
r
.
Timeout
<=
0
{
r
.
Timeout
=
DefaultResolverTimeout
}
if
r
.
TTL
==
0
{
r
.
TTL
=
DefaultResolverTTL
}
return
r
return
r
}
}
func
newResolver
(
t
imeout
,
t
tl
time
.
Duration
,
servers
...
NameServer
)
*
resolver
{
func
newResolver
(
ttl
time
.
Duration
,
servers
...
NameServer
)
*
resolver
{
return
&
resolver
{
return
&
resolver
{
Servers
:
servers
,
Servers
:
servers
,
Timeout
:
timeout
,
TTL
:
ttl
,
TTL
:
ttl
,
mCache
:
&
sync
.
Map
{},
mCache
:
&
sync
.
Map
{},
stopped
:
make
(
chan
struct
{}),
stopped
:
make
(
chan
struct
{}),
...
@@ -204,25 +193,25 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
...
@@ -204,25 +193,25 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
}
}
for
_
,
ns
:=
range
servers
{
for
_
,
ns
:=
range
servers
{
ips
,
err
=
r
.
resolve
(
ns
.
exchanger
,
host
)
ips
,
ttl
,
err
=
r
.
resolve
(
ns
.
exchanger
,
host
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[resolver] %s via %s : %s"
,
host
,
ns
,
err
)
log
.
Logf
(
"[resolver] %s via %s : %s"
,
host
,
ns
,
err
)
continue
continue
}
}
if
Debug
{
if
Debug
{
log
.
Logf
(
"[resolver] %s via %s %v
"
,
host
,
ns
,
ips
)
log
.
Logf
(
"[resolver] %s via %s %v
(ttl: %v)"
,
host
,
ns
,
ips
,
ttl
)
}
}
if
len
(
ips
)
>
0
{
if
len
(
ips
)
>
0
{
break
break
}
}
}
}
r
.
storeCache
(
host
,
ips
)
r
.
storeCache
(
host
,
ips
,
ttl
)
return
return
}
}
func
(
*
resolver
)
resolve
(
ex
Exchanger
,
host
string
)
(
ips
[]
net
.
IP
,
err
error
)
{
func
(
*
resolver
)
resolve
(
ex
Exchanger
,
host
string
)
(
ips
[]
net
.
IP
,
ttl
time
.
Duration
,
err
error
)
{
if
ex
==
nil
{
if
ex
==
nil
{
return
return
}
}
...
@@ -236,11 +225,18 @@ func (*resolver) resolve(ex Exchanger, host string) (ips []net.IP, err error) {
...
@@ -236,11 +225,18 @@ func (*resolver) resolve(ex Exchanger, host string) (ips []net.IP, err error) {
for
_
,
ans
:=
range
mr
.
Answer
{
for
_
,
ans
:=
range
mr
.
Answer
{
if
ar
,
_
:=
ans
.
(
*
dns
.
A
);
ar
!=
nil
{
if
ar
,
_
:=
ans
.
(
*
dns
.
A
);
ar
!=
nil
{
ips
=
append
(
ips
,
ar
.
A
)
ips
=
append
(
ips
,
ar
.
A
)
ttl
=
time
.
Duration
(
ar
.
Header
()
.
Ttl
)
*
time
.
Second
}
}
}
}
return
return
}
}
type
resolverCacheItem
struct
{
IPs
[]
net
.
IP
ts
int64
ttl
time
.
Duration
}
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
ttl
<
0
{
return
nil
return
nil
...
@@ -248,6 +244,10 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
...
@@ -248,6 +244,10 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
if
v
,
ok
:=
r
.
mCache
.
Load
(
name
);
ok
{
if
v
,
ok
:=
r
.
mCache
.
Load
(
name
);
ok
{
item
,
_
:=
v
.
(
*
resolverCacheItem
)
item
,
_
:=
v
.
(
*
resolverCacheItem
)
if
ttl
==
0
{
ttl
=
item
.
ttl
}
if
item
==
nil
||
time
.
Since
(
time
.
Unix
(
item
.
ts
,
0
))
>
ttl
{
if
item
==
nil
||
time
.
Since
(
time
.
Unix
(
item
.
ts
,
0
))
>
ttl
{
return
nil
return
nil
}
}
...
@@ -257,13 +257,14 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
...
@@ -257,13 +257,14 @@ func (r *resolver) loadCache(name string, ttl time.Duration) []net.IP {
return
nil
return
nil
}
}
func
(
r
*
resolver
)
storeCache
(
name
string
,
ips
[]
net
.
IP
)
{
func
(
r
*
resolver
)
storeCache
(
name
string
,
ips
[]
net
.
IP
,
ttl
time
.
Duration
)
{
if
name
==
""
||
len
(
ips
)
==
0
{
if
name
==
""
||
len
(
ips
)
==
0
{
return
return
}
}
r
.
mCache
.
Store
(
name
,
&
resolverCacheItem
{
r
.
mCache
.
Store
(
name
,
&
resolverCacheItem
{
IPs
:
ips
,
IPs
:
ips
,
ts
:
time
.
Now
()
.
Unix
(),
ts
:
time
.
Now
()
.
Unix
(),
ttl
:
ttl
,
})
})
}
}
...
@@ -343,10 +344,10 @@ func (r *resolver) Reload(rd io.Reader) error {
...
@@ -343,10 +344,10 @@ func (r *resolver) Reload(rd io.Reader) error {
ns
.
Hostname
=
ss
[
2
]
ns
.
Hostname
=
ss
[
2
]
}
}
ns
.
Timeout
=
timeout
if
strings
.
HasPrefix
(
ns
.
Addr
,
"https"
)
{
if
timeout
<=
0
{
ns
.
Protocol
=
"https"
ns
.
Timeout
=
DefaultResolverTimeout
}
}
ns
.
Timeout
=
timeout
if
err
:=
ns
.
Init
();
err
==
nil
{
if
err
:=
ns
.
Init
();
err
==
nil
{
nss
=
append
(
nss
,
ns
)
nss
=
append
(
nss
,
ns
)
...
@@ -359,7 +360,6 @@ func (r *resolver) Reload(rd io.Reader) error {
...
@@ -359,7 +360,6 @@ func (r *resolver) Reload(rd io.Reader) error {
}
}
r
.
mux
.
Lock
()
r
.
mux
.
Lock
()
r
.
Timeout
=
timeout
r
.
TTL
=
ttl
r
.
TTL
=
ttl
r
.
domain
=
domain
r
.
domain
=
domain
r
.
period
=
period
r
.
period
=
period
...
@@ -408,9 +408,9 @@ func (r *resolver) String() string {
...
@@ -408,9 +408,9 @@ func (r *resolver) String() string {
defer
r
.
mux
.
RUnlock
()
defer
r
.
mux
.
RUnlock
()
b
:=
&
bytes
.
Buffer
{}
b
:=
&
bytes
.
Buffer
{}
fmt
.
Fprintf
(
b
,
"Timeout %v
\n
"
,
r
.
Timeout
)
fmt
.
Fprintf
(
b
,
"TTL %v
\n
"
,
r
.
TTL
)
fmt
.
Fprintf
(
b
,
"TTL %v
\n
"
,
r
.
TTL
)
fmt
.
Fprintf
(
b
,
"Reload %v
\n
"
,
r
.
period
)
fmt
.
Fprintf
(
b
,
"Reload %v
\n
"
,
r
.
period
)
fmt
.
Fprintf
(
b
,
"Domain %v
\n
"
,
r
.
domain
)
for
i
:=
range
r
.
Servers
{
for
i
:=
range
r
.
Servers
{
fmt
.
Fprintln
(
b
,
r
.
Servers
[
i
])
fmt
.
Fprintln
(
b
,
r
.
Servers
[
i
])
}
}
...
...
resolver_test.go
View file @
445889c4
...
@@ -46,7 +46,7 @@ func TestDNSResolver(t *testing.T) {
...
@@ -46,7 +46,7 @@ func TestDNSResolver(t *testing.T) {
t
.
Error
(
err
)
t
.
Error
(
err
)
}
}
t
.
Log
(
ns
)
t
.
Log
(
ns
)
r
:=
NewResolver
(
0
,
0
,
ns
)
r
:=
NewResolver
(
0
,
ns
)
err
:=
dnsResolverRoundtrip
(
t
,
r
,
tc
.
host
)
err
:=
dnsResolverRoundtrip
(
t
,
r
,
tc
.
host
)
if
err
!=
nil
{
if
err
!=
nil
{
if
tc
.
pass
{
if
tc
.
pass
{
...
@@ -104,12 +104,11 @@ var resolverReloadTests = []struct {
...
@@ -104,12 +104,11 @@ var resolverReloadTests = []struct {
r
:
bytes
.
NewBufferString
(
"1.1.1.1"
),
r
:
bytes
.
NewBufferString
(
"1.1.1.1"
),
ns
:
&
NameServer
{
ns
:
&
NameServer
{
Addr
:
"1.1.1.1"
,
Addr
:
"1.1.1.1"
,
Timeout
:
DefaultResolverTimeout
,
},
},
stopped
:
true
,
stopped
:
true
,
},
},
{
{
r
:
bytes
.
NewBufferString
(
"timeout 10s
\n
search
\n
nameserver
\n
nameserver 1.1.1.1 udp"
),
r
:
bytes
.
NewBufferString
(
"
\n
# comment
\n
timeout 10s
\n
search
\n
nameserver
\n
nameserver 1.1.1.1 udp"
),
ns
:
&
NameServer
{
ns
:
&
NameServer
{
Protocol
:
"udp"
,
Protocol
:
"udp"
,
Addr
:
"1.1.1.1"
,
Addr
:
"1.1.1.1"
,
...
@@ -123,7 +122,6 @@ var resolverReloadTests = []struct {
...
@@ -123,7 +122,6 @@ var resolverReloadTests = []struct {
ns
:
&
NameServer
{
ns
:
&
NameServer
{
Addr
:
"1.1.1.1"
,
Addr
:
"1.1.1.1"
,
Protocol
:
"tcp"
,
Protocol
:
"tcp"
,
Timeout
:
DefaultResolverTimeout
,
},
},
stopped
:
true
,
stopped
:
true
,
},
},
...
@@ -133,7 +131,6 @@ var resolverReloadTests = []struct {
...
@@ -133,7 +131,6 @@ var resolverReloadTests = []struct {
Addr
:
"1.1.1.1:853"
,
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
,
Protocol
:
"tls"
,
Hostname
:
"cloudflare-dns.com"
,
Hostname
:
"cloudflare-dns.com"
,
Timeout
:
DefaultResolverTimeout
,
},
},
stopped
:
true
,
stopped
:
true
,
},
},
...
@@ -142,7 +139,6 @@ var resolverReloadTests = []struct {
...
@@ -142,7 +139,6 @@ var resolverReloadTests = []struct {
ns
:
&
NameServer
{
ns
:
&
NameServer
{
Addr
:
"1.1.1.1:853"
,
Addr
:
"1.1.1.1:853"
,
Protocol
:
"tls"
,
Protocol
:
"tls"
,
Timeout
:
DefaultResolverTimeout
,
},
},
stopped
:
true
,
stopped
:
true
,
},
},
...
@@ -151,11 +147,10 @@ var resolverReloadTests = []struct {
...
@@ -151,11 +147,10 @@ var resolverReloadTests = []struct {
stopped
:
true
,
stopped
:
true
,
},
},
{
{
r
:
bytes
.
NewBufferString
(
"https://1.0.0.1/dns-query
https
"
),
r
:
bytes
.
NewBufferString
(
"https://1.0.0.1/dns-query"
),
ns
:
&
NameServer
{
ns
:
&
NameServer
{
Addr
:
"https://1.0.0.1/dns-query"
,
Addr
:
"https://1.0.0.1/dns-query"
,
Protocol
:
"https"
,
Protocol
:
"https"
,
Timeout
:
DefaultResolverTimeout
,
},
},
stopped
:
true
,
stopped
:
true
,
},
},
...
@@ -164,15 +159,11 @@ var resolverReloadTests = []struct {
...
@@ -164,15 +159,11 @@ var resolverReloadTests = []struct {
func
TestResolverReload
(
t
*
testing
.
T
)
{
func
TestResolverReload
(
t
*
testing
.
T
)
{
for
i
,
tc
:=
range
resolverReloadTests
{
for
i
,
tc
:=
range
resolverReloadTests
{
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
r
:=
newResolver
(
0
,
0
)
r
:=
newResolver
(
0
)
if
err
:=
r
.
Reload
(
tc
.
r
);
err
!=
nil
{
if
err
:=
r
.
Reload
(
tc
.
r
);
err
!=
nil
{
t
.
Error
(
err
)
t
.
Error
(
err
)
}
}
t
.
Log
(
r
.
String
())
t
.
Log
(
r
.
String
())
if
r
.
Timeout
!=
tc
.
timeout
{
t
.
Errorf
(
"timeout value should be %v, got %v"
,
tc
.
timeout
,
r
.
Timeout
)
}
if
r
.
TTL
!=
tc
.
ttl
{
if
r
.
TTL
!=
tc
.
ttl
{
t
.
Errorf
(
"ttl value should be %v, got %v"
,
t
.
Errorf
(
"ttl value should be %v, got %v"
,
tc
.
ttl
,
r
.
TTL
)
tc
.
ttl
,
r
.
TTL
)
...
@@ -198,6 +189,9 @@ func TestResolverReload(t *testing.T) {
...
@@ -198,6 +189,9 @@ func TestResolverReload(t *testing.T) {
if
tc
.
stopped
{
if
tc
.
stopped
{
r
.
Stop
()
r
.
Stop
()
if
r
.
Period
()
>=
0
{
t
.
Errorf
(
"period of the stopped reloader should be minus value"
)
}
}
}
if
r
.
Stopped
()
!=
tc
.
stopped
{
if
r
.
Stopped
()
!=
tc
.
stopped
{
t
.
Errorf
(
"stopped value should be %v, got %v"
,
t
.
Errorf
(
"stopped value should be %v, got %v"
,
...
...
socks.go
View file @
445889c4
...
@@ -340,6 +340,164 @@ func (c *socks5BindConnector) Connect(conn net.Conn, addr string, options ...Con
...
@@ -340,6 +340,164 @@ func (c *socks5BindConnector) Connect(conn net.Conn, addr string, options ...Con
return
&
socks5BindConn
{
Conn
:
conn
,
laddr
:
baddr
},
nil
return
&
socks5BindConn
{
Conn
:
conn
,
laddr
:
baddr
},
nil
}
}
type
socks5MuxBindConnector
struct
{}
// Socks5MuxBindConnector creates a Connector for SOCKS5 multiplex bind client.
func
Socks5MuxBindConnector
()
Connector
{
return
&
socks5MuxBindConnector
{}
}
// NOTE: the conn must be *muxBindClientConn.
func
(
c
*
socks5MuxBindConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
,
options
...
ConnectOption
)
(
net
.
Conn
,
error
)
{
accepter
,
ok
:=
conn
.
(
Accepter
)
if
!
ok
{
return
nil
,
errors
.
New
(
"wrong connection type"
)
}
return
accepter
.
Accept
()
}
type
socks5MuxBindTransporter
struct
{
bindAddr
string
sessions
map
[
string
]
*
muxSession
// server addr to session mapping
sessionMutex
sync
.
Mutex
}
// SOCKS5MuxBindTransporter creates a Transporter for SOCKS5 multiplex bind client.
func
SOCKS5MuxBindTransporter
(
bindAddr
string
)
Transporter
{
return
&
socks5MuxBindTransporter
{
bindAddr
:
bindAddr
,
sessions
:
make
(
map
[
string
]
*
muxSession
),
}
}
func
(
tr
*
socks5MuxBindTransporter
)
Dial
(
addr
string
,
options
...
DialOption
)
(
conn
net
.
Conn
,
err
error
)
{
opts
:=
&
DialOptions
{}
for
_
,
option
:=
range
options
{
option
(
opts
)
}
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
tr
.
sessionMutex
.
Lock
()
defer
tr
.
sessionMutex
.
Unlock
()
session
,
ok
:=
tr
.
sessions
[
addr
]
if
session
!=
nil
&&
session
.
IsClosed
()
{
delete
(
tr
.
sessions
,
addr
)
ok
=
false
}
if
!
ok
{
if
opts
.
Chain
==
nil
{
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
}
else
{
conn
,
err
=
opts
.
Chain
.
Dial
(
addr
)
}
if
err
!=
nil
{
return
}
session
=
&
muxSession
{
conn
:
conn
}
tr
.
sessions
[
addr
]
=
session
}
return
session
.
conn
,
nil
}
func
(
tr
*
socks5MuxBindTransporter
)
Handshake
(
conn
net
.
Conn
,
options
...
HandshakeOption
)
(
net
.
Conn
,
error
)
{
opts
:=
&
HandshakeOptions
{}
for
_
,
option
:=
range
options
{
option
(
opts
)
}
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
HandshakeTimeout
}
tr
.
sessionMutex
.
Lock
()
defer
tr
.
sessionMutex
.
Unlock
()
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
session
,
ok
:=
tr
.
sessions
[
opts
.
Addr
]
if
!
ok
||
session
.
session
==
nil
{
s
,
err
:=
tr
.
initSession
(
conn
,
tr
.
bindAddr
,
opts
)
if
err
!=
nil
{
conn
.
Close
()
delete
(
tr
.
sessions
,
opts
.
Addr
)
return
nil
,
err
}
session
=
s
tr
.
sessions
[
opts
.
Addr
]
=
session
}
return
&
muxBindClientConn
{
session
:
session
},
nil
}
func
(
tr
*
socks5MuxBindTransporter
)
initSession
(
conn
net
.
Conn
,
addr
string
,
opts
*
HandshakeOptions
)
(
*
muxSession
,
error
)
{
if
opts
==
nil
{
opts
=
&
HandshakeOptions
{}
}
cc
,
err
:=
socks5Handshake
(
conn
,
opts
.
User
)
if
err
!=
nil
{
return
nil
,
err
}
conn
=
cc
bindAddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
}
req
:=
gosocks5
.
NewRequest
(
CmdMuxBind
,
&
gosocks5
.
Addr
{
Type
:
gosocks5
.
AddrIPv4
,
Host
:
bindAddr
.
IP
.
String
(),
Port
:
uint16
(
bindAddr
.
Port
),
})
if
err
=
req
.
Write
(
conn
);
err
!=
nil
{
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5] mbind
\n
"
,
req
)
}
reply
,
err
:=
gosocks5
.
ReadReply
(
conn
)
if
err
!=
nil
{
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5] mbind
\n
"
,
reply
)
}
if
reply
.
Rep
!=
gosocks5
.
Succeeded
{
log
.
Logf
(
"[socks5] mbind on %s failure"
,
addr
)
return
nil
,
fmt
.
Errorf
(
"SOCKS5 mbind on %s failure"
,
addr
)
}
baddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp"
,
reply
.
Addr
.
String
())
if
err
!=
nil
{
return
nil
,
err
}
log
.
Logf
(
"[socks5] mbind on %s OK"
,
baddr
)
// Upgrade connection to multiplex stream.
session
,
err
:=
smux
.
Server
(
conn
,
smux
.
DefaultConfig
())
if
err
!=
nil
{
return
nil
,
err
}
return
&
muxSession
{
conn
:
conn
,
session
:
session
},
nil
}
func
(
tr
*
socks5MuxBindTransporter
)
Multiplex
()
bool
{
return
true
}
type
socks5UDPConnector
struct
{
type
socks5UDPConnector
struct
{
User
*
url
.
Userinfo
User
*
url
.
Userinfo
}
}
...
@@ -387,12 +545,10 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
...
@@ -387,12 +545,10 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
log
.
Log
(
"[socks5] udp
\n
"
,
req
)
log
.
Log
(
"[socks5] udp
\n
"
,
req
)
}
}
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
reply
,
err
:=
gosocks5
.
ReadReply
(
conn
)
reply
,
err
:=
gosocks5
.
ReadReply
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
conn
.
SetReadDeadline
(
time
.
Time
{})
if
Debug
{
if
Debug
{
log
.
Log
(
"[socks5] udp
\n
"
,
reply
)
log
.
Log
(
"[socks5] udp
\n
"
,
reply
)
...
@@ -412,11 +568,142 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
...
@@ -412,11 +568,142 @@ func (c *socks5UDPConnector) Connect(conn net.Conn, addr string, options ...Conn
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
log
.
Logf
(
"udp laddr:%s, raddr:%s"
,
uc
.
LocalAddr
(),
uc
.
RemoteAddr
())
//
log.Logf("udp laddr:%s, raddr:%s", uc.LocalAddr(), uc.RemoteAddr())
return
&
socks5UDPConn
{
UDPConn
:
uc
,
taddr
:
taddr
},
nil
return
&
socks5UDPConn
{
UDPConn
:
uc
,
taddr
:
taddr
},
nil
}
}
type
socks5UDPTunConnector
struct
{
User
*
url
.
Userinfo
}
// SOCKS5UDPTunConnector creates a connector for SOCKS5 UDP-over-TCP relay.
// It accepts an optional auth info for SOCKS5 Username/Password Authentication.
func
SOCKS5UDPTunConnector
(
user
*
url
.
Userinfo
)
Connector
{
return
&
socks5UDPTunConnector
{
User
:
user
}
}
func
(
c
*
socks5UDPTunConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
,
options
...
ConnectOption
)
(
net
.
Conn
,
error
)
{
opts
:=
&
ConnectOptions
{}
for
_
,
option
:=
range
options
{
option
(
opts
)
}
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
ConnectTimeout
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
cc
,
err
:=
socks5Handshake
(
conn
,
c
.
User
)
if
err
!=
nil
{
return
nil
,
err
}
conn
=
cc
taddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
}
req
:=
gosocks5
.
NewRequest
(
CmdUDPTun
,
&
gosocks5
.
Addr
{
Type
:
gosocks5
.
AddrIPv4
,
})
if
err
:=
req
.
Write
(
conn
);
err
!=
nil
{
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5] udp
\n
"
,
req
)
}
reply
,
err
:=
gosocks5
.
ReadReply
(
conn
)
if
err
!=
nil
{
return
nil
,
err
}
if
Debug
{
log
.
Log
(
"[socks5] udp
\n
"
,
reply
)
}
if
reply
.
Rep
!=
gosocks5
.
Succeeded
{
log
.
Logf
(
"[socks5] udp relay failure"
)
return
nil
,
fmt
.
Errorf
(
"SOCKS5 udp relay failure"
)
}
baddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
reply
.
Addr
.
String
())
if
err
!=
nil
{
return
nil
,
err
}
log
.
Logf
(
"[socks5] udp-tun associate on %s OK"
,
baddr
)
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.
...
@@ -850,11 +1137,11 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
...
@@ -850,11 +1137,11 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
relay
,
err
:=
net
.
ListenUDP
(
"udp"
,
nil
)
relay
,
err
:=
net
.
ListenUDP
(
"udp"
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
relay
.
LocalAddr
(),
err
)
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
reply
.
Write
(
conn
)
reply
.
Write
(
conn
)
if
Debug
{
if
Debug
{
log
.
Logf
(
"[socks5-udp] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
relay
.
LocalAddr
(),
reply
)
log
.
Logf
(
"[socks5-udp] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
reply
)
}
}
return
return
}
}
...
@@ -864,39 +1151,39 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
...
@@ -864,39 +1151,39 @@ func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
socksAddr
.
Host
,
_
,
_
=
net
.
SplitHostPort
(
conn
.
LocalAddr
()
.
String
())
// replace the IP to the out-going interface's
socksAddr
.
Host
,
_
,
_
=
net
.
SplitHostPort
(
conn
.
LocalAddr
()
.
String
())
// replace the IP to the out-going interface's
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Succeeded
,
socksAddr
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Succeeded
,
socksAddr
)
if
err
:=
reply
.
Write
(
conn
);
err
!=
nil
{
if
err
:=
reply
.
Write
(
conn
);
err
!=
nil
{
log
.
Logf
(
"[socks5-udp] %s <- %s : %s"
,
conn
.
RemoteAddr
(),
relay
.
LocalAddr
(),
err
)
log
.
Logf
(
"[socks5-udp] %s <- %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
return
}
}
if
Debug
{
if
Debug
{
log
.
Logf
(
"[socks5-udp] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
reply
.
Addr
,
reply
)
log
.
Logf
(
"[socks5-udp] %s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
()
,
reply
)
}
}
log
.
Logf
(
"[socks5-udp] %s - %s BIND ON %s OK"
,
conn
.
RemoteAddr
(),
relay
.
LocalAddr
(),
socksAddr
)
log
.
Logf
(
"[socks5-udp] %s - %s BIND ON %s OK"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
socksAddr
)
// serve as standard socks5 udp relay local <-> remote
// serve as standard socks5 udp relay local <-> remote
if
h
.
options
.
Chain
.
IsEmpty
()
{
if
h
.
options
.
Chain
.
IsEmpty
()
{
peer
,
er
:=
net
.
ListenUDP
(
"udp"
,
nil
)
peer
,
er
:=
net
.
ListenUDP
(
"udp"
,
nil
)
if
er
!=
nil
{
if
er
!=
nil
{
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
er
)
log
.
Logf
(
"[socks5-udp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
()
,
er
)
return
return
}
}
defer
peer
.
Close
()
defer
peer
.
Close
()
go
h
.
transportUDP
(
relay
,
peer
)
go
h
.
transportUDP
(
relay
,
peer
)
log
.
Logf
(
"[socks5-udp] %s <-> %s
"
,
conn
.
Remote
Addr
(),
socksAddr
)
log
.
Logf
(
"[socks5-udp] %s <-> %s
: associated on %s"
,
conn
.
RemoteAddr
(),
conn
.
Local
Addr
(),
socksAddr
)
if
err
:=
h
.
discardClientData
(
conn
);
err
!=
nil
{
if
err
:=
h
.
discardClientData
(
conn
);
err
!=
nil
{
log
.
Logf
(
"[socks5-udp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
log
.
Logf
(
"[socks5-udp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
()
,
err
)
}
}
log
.
Logf
(
"[socks5-udp] %s >-< %s
"
,
conn
.
Remote
Addr
(),
socksAddr
)
log
.
Logf
(
"[socks5-udp] %s >-< %s
: associated on %s"
,
conn
.
RemoteAddr
(),
conn
.
Local
Addr
(),
socksAddr
)
return
return
}
}
// forward udp local <-> tunnel
cc
,
err
:=
h
.
options
.
Chain
.
Conn
()
cc
,
err
:=
h
.
options
.
Chain
.
Conn
()
// connection error
// connection error
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
}
}
// forward udp local <-> tunnel
defer
cc
.
Close
()
defer
cc
.
Close
()
cc
,
err
=
socks5Handshake
(
cc
,
h
.
options
.
Chain
.
LastNode
()
.
User
)
cc
,
err
=
socks5Handshake
(
cc
,
h
.
options
.
Chain
.
LastNode
()
.
User
)
...
@@ -956,17 +1243,17 @@ func (h *socks5Handler) discardClientData(conn net.Conn) (err error) {
...
@@ -956,17 +1243,17 @@ func (h *socks5Handler) discardClientData(conn net.Conn) (err error) {
return
return
}
}
func
(
h
*
socks5Handler
)
transportUDP
(
relay
,
peer
*
net
.
UDP
Conn
)
(
err
error
)
{
func
(
h
*
socks5Handler
)
transportUDP
(
relay
,
peer
net
.
Packet
Conn
)
(
err
error
)
{
errc
:=
make
(
chan
error
,
2
)
errc
:=
make
(
chan
error
,
2
)
var
clientAddr
*
net
.
UDP
Addr
var
clientAddr
net
.
Addr
go
func
()
{
go
func
()
{
b
:=
mPool
.
Get
()
.
([]
byte
)
b
:=
mPool
.
Get
()
.
([]
byte
)
defer
mPool
.
Put
(
b
)
defer
mPool
.
Put
(
b
)
for
{
for
{
n
,
laddr
,
err
:=
relay
.
ReadFrom
UDP
(
b
)
n
,
laddr
,
err
:=
relay
.
ReadFrom
(
b
)
if
err
!=
nil
{
if
err
!=
nil
{
errc
<-
err
errc
<-
err
return
return
...
@@ -988,7 +1275,7 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
...
@@ -988,7 +1275,7 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
log
.
Log
(
"[socks5-udp] [bypass] write to"
,
raddr
)
log
.
Log
(
"[socks5-udp] [bypass] write to"
,
raddr
)
continue
// bypass
continue
// bypass
}
}
if
_
,
err
:=
peer
.
WriteTo
UDP
(
dgram
.
Data
,
raddr
);
err
!=
nil
{
if
_
,
err
:=
peer
.
WriteTo
(
dgram
.
Data
,
raddr
);
err
!=
nil
{
errc
<-
err
errc
<-
err
return
return
}
}
...
@@ -1003,7 +1290,7 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
...
@@ -1003,7 +1290,7 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
defer
mPool
.
Put
(
b
)
defer
mPool
.
Put
(
b
)
for
{
for
{
n
,
raddr
,
err
:=
peer
.
ReadFrom
UDP
(
b
)
n
,
raddr
,
err
:=
peer
.
ReadFrom
(
b
)
if
err
!=
nil
{
if
err
!=
nil
{
errc
<-
err
errc
<-
err
return
return
...
@@ -1018,7 +1305,7 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
...
@@ -1018,7 +1305,7 @@ func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
buf
:=
bytes
.
Buffer
{}
buf
:=
bytes
.
Buffer
{}
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
0
,
0
,
toSocksAddr
(
raddr
)),
b
[
:
n
])
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
0
,
0
,
toSocksAddr
(
raddr
)),
b
[
:
n
])
dgram
.
Write
(
&
buf
)
dgram
.
Write
(
&
buf
)
if
_
,
err
:=
relay
.
WriteTo
UDP
(
buf
.
Bytes
(),
clientAddr
);
err
!=
nil
{
if
_
,
err
:=
relay
.
WriteTo
(
buf
.
Bytes
(),
clientAddr
);
err
!=
nil
{
errc
<-
err
errc
<-
err
return
return
}
}
...
@@ -1178,7 +1465,7 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
...
@@ -1178,7 +1465,7 @@ func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
log
.
Logf
(
"[socks5-udp] %s >-< %s [tun]"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
log
.
Logf
(
"[socks5-udp] %s >-< %s [tun]"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
}
}
func
(
h
*
socks5Handler
)
tunnelServerUDP
(
cc
net
.
Conn
,
uc
*
net
.
UDP
Conn
)
(
err
error
)
{
func
(
h
*
socks5Handler
)
tunnelServerUDP
(
cc
net
.
Conn
,
pc
net
.
Packet
Conn
)
(
err
error
)
{
errc
:=
make
(
chan
error
,
2
)
errc
:=
make
(
chan
error
,
2
)
go
func
()
{
go
func
()
{
...
@@ -1186,9 +1473,9 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
...
@@ -1186,9 +1473,9 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
defer
mPool
.
Put
(
b
)
defer
mPool
.
Put
(
b
)
for
{
for
{
n
,
addr
,
err
:=
uc
.
ReadFromUDP
(
b
)
n
,
addr
,
err
:=
pc
.
ReadFrom
(
b
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[udp-tun] %s <- %s : %s"
,
cc
.
RemoteAddr
(),
addr
,
err
)
// log.Logf("[udp-tun] %s : %s", cc.RemoteAddr()
, err)
errc
<-
err
errc
<-
err
return
return
}
}
...
@@ -1215,7 +1502,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
...
@@ -1215,7 +1502,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
for
{
for
{
dgram
,
err
:=
gosocks5
.
ReadUDPDatagram
(
cc
)
dgram
,
err
:=
gosocks5
.
ReadUDPDatagram
(
cc
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[udp-tun] %s -> 0 : %s"
,
cc
.
RemoteAddr
(),
err
)
//
log.Logf("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
errc
<-
err
errc
<-
err
return
return
}
}
...
@@ -1229,7 +1516,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
...
@@ -1229,7 +1516,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error
log
.
Log
(
"[udp-tun] [bypass] write to"
,
addr
)
log
.
Log
(
"[udp-tun] [bypass] write to"
,
addr
)
continue
// bypass
continue
// bypass
}
}
if
_
,
err
:=
uc
.
WriteToUDP
(
dgram
.
Data
,
addr
);
err
!=
nil
{
if
_
,
err
:=
pc
.
WriteTo
(
dgram
.
Data
,
addr
);
err
!=
nil
{
log
.
Logf
(
"[udp-tun] %s -> %s : %s"
,
cc
.
RemoteAddr
(),
addr
,
err
)
log
.
Logf
(
"[udp-tun] %s -> %s : %s"
,
cc
.
RemoteAddr
(),
addr
,
err
)
errc
<-
err
errc
<-
err
return
return
...
@@ -1260,11 +1547,11 @@ func (h *socks5Handler) handleMuxBind(conn net.Conn, req *gosocks5.Request) {
...
@@ -1260,11 +1547,11 @@ func (h *socks5Handler) handleMuxBind(conn net.Conn, req *gosocks5.Request) {
cc
,
err
:=
h
.
options
.
Chain
.
Conn
()
cc
,
err
:=
h
.
options
.
Chain
.
Conn
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-mbind]
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
log
.
Logf
(
"[socks5
] mbind
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
err
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
reply
.
Write
(
conn
)
reply
.
Write
(
conn
)
if
Debug
{
if
Debug
{
log
.
Logf
(
"[socks5
-mbind]
%s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
reply
)
log
.
Logf
(
"[socks5
] mbind
%s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Addr
,
reply
)
}
}
return
return
}
}
...
@@ -1274,16 +1561,16 @@ func (h *socks5Handler) handleMuxBind(conn net.Conn, req *gosocks5.Request) {
...
@@ -1274,16 +1561,16 @@ func (h *socks5Handler) handleMuxBind(conn net.Conn, req *gosocks5.Request) {
// so we don't need to authenticate it, as it's as explicit as whitelisting.
// so we don't need to authenticate it, as it's as explicit as whitelisting.
defer
cc
.
Close
()
defer
cc
.
Close
()
req
.
Write
(
cc
)
req
.
Write
(
cc
)
log
.
Logf
(
"[socks5
-mbind]
%s <-> %s"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
log
.
Logf
(
"[socks5
] mbind
%s <-> %s"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
transport
(
conn
,
cc
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[socks5
-mbind]
%s >-< %s"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
log
.
Logf
(
"[socks5
] mbind
%s >-< %s"
,
conn
.
RemoteAddr
(),
cc
.
RemoteAddr
())
}
}
func
(
h
*
socks5Handler
)
muxBindOn
(
conn
net
.
Conn
,
addr
string
)
{
func
(
h
*
socks5Handler
)
muxBindOn
(
conn
net
.
Conn
,
addr
string
)
{
bindAddr
,
_
:=
net
.
ResolveTCPAddr
(
"tcp"
,
addr
)
bindAddr
,
_
:=
net
.
ResolveTCPAddr
(
"tcp"
,
addr
)
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
bindAddr
)
// strict mode: if the port already in use, it will return error
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
bindAddr
)
// strict mode: if the port already in use, it will return error
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-mbind]
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
log
.
Logf
(
"[socks5
] mbind
%s -> %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
.
Write
(
conn
)
gosocks5
.
NewReply
(
gosocks5
.
Failure
,
nil
)
.
Write
(
conn
)
return
return
}
}
...
@@ -1294,23 +1581,23 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
...
@@ -1294,23 +1581,23 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
socksAddr
.
Host
,
_
,
_
=
net
.
SplitHostPort
(
conn
.
LocalAddr
()
.
String
())
socksAddr
.
Host
,
_
,
_
=
net
.
SplitHostPort
(
conn
.
LocalAddr
()
.
String
())
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Succeeded
,
socksAddr
)
reply
:=
gosocks5
.
NewReply
(
gosocks5
.
Succeeded
,
socksAddr
)
if
err
:=
reply
.
Write
(
conn
);
err
!=
nil
{
if
err
:=
reply
.
Write
(
conn
);
err
!=
nil
{
log
.
Logf
(
"[socks5
-mbind]
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
log
.
Logf
(
"[socks5
] mbind
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
return
return
}
}
if
Debug
{
if
Debug
{
log
.
Logf
(
"[socks5
-mbind]
%s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
addr
,
reply
)
log
.
Logf
(
"[socks5
] mbind
%s <- %s
\n
%s"
,
conn
.
RemoteAddr
(),
addr
,
reply
)
}
}
log
.
Logf
(
"[socks5
-mbind]
%s - %s BIND ON %s OK"
,
conn
.
RemoteAddr
(),
addr
,
socksAddr
)
log
.
Logf
(
"[socks5
] mbind
%s - %s BIND ON %s OK"
,
conn
.
RemoteAddr
(),
addr
,
socksAddr
)
// Upgrade connection to multiplex stream.
// Upgrade connection to multiplex stream.
s
,
err
:=
smux
.
Client
(
conn
,
smux
.
DefaultConfig
())
s
,
err
:=
smux
.
Client
(
conn
,
smux
.
DefaultConfig
())
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-mbind]
%s - %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
log
.
Logf
(
"[socks5
] mbind
%s - %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
return
return
}
}
log
.
Logf
(
"[socks5
-mbind]
%s <-> %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
log
.
Logf
(
"[socks5
] mbind
%s <-> %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
defer
log
.
Logf
(
"[socks5
-mbind]
%s >-< %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
defer
log
.
Logf
(
"[socks5
] mbind
%s >-< %s"
,
conn
.
RemoteAddr
(),
socksAddr
)
session
:=
&
muxSession
{
session
:=
&
muxSession
{
conn
:
conn
,
conn
:
conn
,
...
@@ -1322,6 +1609,7 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
...
@@ -1322,6 +1609,7 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
for
{
for
{
conn
,
err
:=
session
.
Accept
()
conn
,
err
:=
session
.
Accept
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5] mbind accept : %v"
,
err
)
ln
.
Close
()
ln
.
Close
()
return
return
}
}
...
@@ -1332,10 +1620,10 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
...
@@ -1332,10 +1620,10 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
for
{
for
{
cc
,
err
:=
ln
.
Accept
()
cc
,
err
:=
ln
.
Accept
()
if
err
!=
nil
{
if
err
!=
nil
{
// log.Logf("[socks5-mbind]
%s <- %s : %v", conn.RemoteAddr(), socksAddr, err)
log
.
Logf
(
"[socks5] mbind
%s <- %s : %v"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
return
return
}
}
log
.
Logf
(
"[socks5
-mbind]
%s <- %s : ACCEPT peer %s"
,
log
.
Logf
(
"[socks5
] mbind
%s <- %s : ACCEPT peer %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
cc
.
RemoteAddr
())
conn
.
RemoteAddr
(),
socksAddr
,
cc
.
RemoteAddr
())
go
func
(
c
net
.
Conn
)
{
go
func
(
c
net
.
Conn
)
{
...
@@ -1343,9 +1631,11 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
...
@@ -1343,9 +1631,11 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) {
sc
,
err
:=
session
.
GetConn
()
sc
,
err
:=
session
.
GetConn
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[socks5
-mbind]
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
log
.
Logf
(
"[socks5
] mbind
%s <- %s : %s"
,
conn
.
RemoteAddr
(),
socksAddr
,
err
)
return
return
}
}
defer
sc
.
Close
()
transport
(
sc
,
c
)
transport
(
sc
,
c
)
}(
cc
)
}(
cc
)
}
}
...
@@ -1550,6 +1840,10 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
...
@@ -1550,6 +1840,10 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
HandshakeTimeout
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
cc
,
err
:=
socks5Handshake
(
conn
,
chain
.
LastNode
()
.
User
)
cc
,
err
:=
socks5Handshake
(
conn
,
chain
.
LastNode
()
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
conn
.
Close
()
conn
.
Close
()
...
@@ -1557,7 +1851,6 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
...
@@ -1557,7 +1851,6 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
}
}
conn
=
cc
conn
=
cc
conn
.
SetWriteDeadline
(
time
.
Now
()
.
Add
(
WriteTimeout
))
req
:=
gosocks5
.
NewRequest
(
CmdUDPTun
,
toSocksAddr
(
addr
))
req
:=
gosocks5
.
NewRequest
(
CmdUDPTun
,
toSocksAddr
(
addr
))
if
err
:=
req
.
Write
(
conn
);
err
!=
nil
{
if
err
:=
req
.
Write
(
conn
);
err
!=
nil
{
conn
.
Close
()
conn
.
Close
()
...
@@ -1566,15 +1859,13 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
...
@@ -1566,15 +1859,13 @@ func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
if
Debug
{
if
Debug
{
log
.
Log
(
"[socks5]"
,
req
)
log
.
Log
(
"[socks5]"
,
req
)
}
}
conn
.
SetWriteDeadline
(
time
.
Time
{})
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
reply
,
err
:=
gosocks5
.
ReadReply
(
conn
)
reply
,
err
:=
gosocks5
.
ReadReply
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
conn
.
Close
()
conn
.
Close
()
return
nil
,
err
return
nil
,
err
}
}
conn
.
SetReadDeadline
(
time
.
Time
{})
if
Debug
{
if
Debug
{
log
.
Log
(
"[socks5]"
,
reply
)
log
.
Log
(
"[socks5]"
,
reply
)
}
}
...
@@ -1647,7 +1938,7 @@ func (c *udpTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
...
@@ -1647,7 +1938,7 @@ func (c *udpTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
return
len
(
b
),
nil
return
len
(
b
),
nil
}
}
// socks5BindConn is a connection for SOCKS5 bind
reques
t.
// socks5BindConn is a connection for SOCKS5 bind
clien
t.
type
socks5BindConn
struct
{
type
socks5BindConn
struct
{
raddr
net
.
Addr
raddr
net
.
Addr
laddr
net
.
Addr
laddr
net
.
Addr
...
@@ -1758,3 +2049,13 @@ func (c *socks5UDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
...
@@ -1758,3 +2049,13 @@ func (c *socks5UDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
}
}
return
len
(
b
),
nil
return
len
(
b
),
nil
}
}
// a dummy client conn for multiplex bind used by SOCKS5 multiplex bind client connector
type
muxBindClientConn
struct
{
nopConn
session
*
muxSession
}
func
(
c
*
muxBindClientConn
)
Accept
()
(
net
.
Conn
,
error
)
{
return
c
.
session
.
Accept
()
}
socks_test.go
View file @
445889c4
package
gost
package
gost
import
(
import
(
"bytes"
"crypto/rand"
"crypto/rand"
"fmt"
"net"
"net"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"testing"
"testing"
"time"
)
)
var
socks5ProxyTests
=
[]
struct
{
var
socks5ProxyTests
=
[]
struct
{
...
@@ -407,6 +410,128 @@ func TestSOCKS5Bind(t *testing.T) {
...
@@ -407,6 +410,128 @@ func TestSOCKS5Bind(t *testing.T) {
}
}
}
}
func
socks5MuxBindRoundtrip
(
t
*
testing
.
T
,
targetURL
string
,
data
[]
byte
)
(
err
error
)
{
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
return
}
l
,
err
:=
net
.
Listen
(
"tcp"
,
""
)
if
err
!=
nil
{
return
err
}
bindAddr
:=
l
.
Addr
()
.
String
()
l
.
Close
()
client
:=
&
Client
{
Connector
:
Socks5MuxBindConnector
(),
Transporter
:
SOCKS5MuxBindTransporter
(
bindAddr
),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
defer
server
.
Close
()
return
muxBindRoundtrip
(
client
,
server
,
bindAddr
,
targetURL
,
data
)
}
func
muxBindRoundtrip
(
client
*
Client
,
server
*
Server
,
bindAddr
,
targetURL
string
,
data
[]
byte
)
(
err
error
)
{
cn
,
err
:=
client
.
Dial
(
server
.
Addr
()
.
String
())
if
err
!=
nil
{
return
err
}
conn
,
err
:=
client
.
Handshake
(
cn
,
AddrHandshakeOption
(
server
.
Addr
()
.
String
()),
UserHandshakeOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
)
if
err
!=
nil
{
cn
.
Close
()
return
err
}
defer
conn
.
Close
()
cc
,
err
:=
net
.
Dial
(
"tcp"
,
bindAddr
)
if
err
!=
nil
{
return
}
defer
cc
.
Close
()
conn
,
err
=
client
.
Connect
(
conn
,
""
)
if
err
!=
nil
{
return
}
u
,
err
:=
url
.
Parse
(
targetURL
)
if
err
!=
nil
{
return
}
hc
,
err
:=
net
.
Dial
(
"tcp"
,
u
.
Host
)
if
err
!=
nil
{
return
}
defer
hc
.
Close
()
go
transport
(
hc
,
conn
)
return
httpRoundtrip
(
cc
,
targetURL
,
data
)
}
func
TestSOCKS5MuxBind
(
t
*
testing
.
T
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
if
err
:=
socks5MuxBindRoundtrip
(
t
,
httpSrv
.
URL
,
sendData
);
err
!=
nil
{
t
.
Errorf
(
"got error: %v"
,
err
)
}
}
func
BenchmarkSOCKS5MuxBind
(
b
*
testing
.
B
)
{
httpSrv
:=
httptest
.
NewServer
(
httpTestHandler
)
defer
httpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
l
,
err
:=
net
.
Listen
(
"tcp"
,
""
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
bindAddr
:=
l
.
Addr
()
.
String
()
l
.
Close
()
client
:=
&
Client
{
Connector
:
Socks5MuxBindConnector
(),
Transporter
:
SOCKS5MuxBindTransporter
(
bindAddr
),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
defer
server
.
Close
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
muxBindRoundtrip
(
client
,
server
,
bindAddr
,
httpSrv
.
URL
,
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
}
}
}
func
socks5UDPRoundtrip
(
t
*
testing
.
T
,
host
string
,
data
[]
byte
)
(
err
error
)
{
func
socks5UDPRoundtrip
(
t
*
testing
.
T
,
host
string
,
data
[]
byte
)
(
err
error
)
{
ln
,
err
:=
TCPListener
(
""
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -440,3 +565,226 @@ func TestSOCKS5UDP(t *testing.T) {
...
@@ -440,3 +565,226 @@ func TestSOCKS5UDP(t *testing.T) {
t
.
Errorf
(
"got error: %v"
,
err
)
t
.
Errorf
(
"got error: %v"
,
err
)
}
}
}
}
// TODO: fix a probability of timeout.
func
BenchmarkSOCKS5UDP
(
b
*
testing
.
B
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
client
:=
&
Client
{
Connector
:
SOCKS5UDPConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Transporter
:
TCPTransporter
(),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
defer
server
.
Close
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
}
}
}
func
BenchmarkSOCKS5UDPSingleConn
(
b
*
testing
.
B
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
client
:=
&
Client
{
Connector
:
SOCKS5UDPConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Transporter
:
TCPTransporter
(),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
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
{
b
.
Error
(
err
)
}
roundtrip
:=
func
(
conn
net
.
Conn
,
data
[]
byte
)
error
{
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
1
*
time
.
Second
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
if
_
,
err
=
conn
.
Write
(
data
);
err
!=
nil
{
return
err
}
recv
:=
make
([]
byte
,
len
(
data
))
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
return
err
}
if
!
bytes
.
Equal
(
data
,
recv
)
{
return
fmt
.
Errorf
(
"data not equal"
)
}
return
nil
}
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
roundtrip
(
conn
,
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
}
}
}
func
socks5UDPTunRoundtrip
(
t
*
testing
.
T
,
host
string
,
data
[]
byte
)
(
err
error
)
{
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
return
}
client
:=
&
Client
{
Connector
:
SOCKS5UDPTunConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Transporter
:
TCPTransporter
(),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
defer
server
.
Close
()
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
}
func
TestSOCKS5UDPTun
(
t
*
testing
.
T
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
if
err
:=
socks5UDPTunRoundtrip
(
t
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
t
.
Errorf
(
"got error: %v"
,
err
)
}
}
func
BenchmarkSOCKS5UDPTun
(
b
*
testing
.
B
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
client
:=
&
Client
{
Connector
:
SOCKS5UDPTunConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Transporter
:
TCPTransporter
(),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
defer
server
.
Close
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
udpRoundtrip
(
client
,
server
,
udpSrv
.
Addr
(),
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
}
}
}
func
BenchmarkSOCKS5UDPTunSingleConn
(
b
*
testing
.
B
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
sendData
:=
make
([]
byte
,
128
)
rand
.
Read
(
sendData
)
ln
,
err
:=
TCPListener
(
""
)
if
err
!=
nil
{
b
.
Error
(
err
)
}
client
:=
&
Client
{
Connector
:
SOCKS5UDPTunConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Transporter
:
TCPTransporter
(),
}
server
:=
&
Server
{
Handler
:
SOCKS5Handler
(
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
))),
Listener
:
ln
,
}
go
server
.
Run
()
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
{
b
.
Error
(
err
)
}
roundtrip
:=
func
(
conn
net
.
Conn
,
data
[]
byte
)
error
{
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
1
*
time
.
Second
))
defer
conn
.
SetDeadline
(
time
.
Time
{})
if
_
,
err
=
conn
.
Write
(
data
);
err
!=
nil
{
return
err
}
recv
:=
make
([]
byte
,
len
(
data
))
if
_
,
err
=
conn
.
Read
(
recv
);
err
!=
nil
{
return
err
}
if
!
bytes
.
Equal
(
data
,
recv
)
{
return
fmt
.
Errorf
(
"data not equal"
)
}
return
nil
}
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
if
err
:=
roundtrip
(
conn
,
sendData
);
err
!=
nil
{
b
.
Error
(
err
)
}
}
}
ss_test.go
View file @
445889c4
...
@@ -2,6 +2,7 @@ package gost
...
@@ -2,6 +2,7 @@ package gost
import
(
import
(
"crypto/rand"
"crypto/rand"
"fmt"
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"testing"
"testing"
...
@@ -148,6 +149,8 @@ func TestSSProxy(t *testing.T) {
...
@@ -148,6 +149,8 @@ func TestSSProxy(t *testing.T) {
rand
.
Read
(
sendData
)
rand
.
Read
(
sendData
)
for
i
,
tc
:=
range
ssTests
{
for
i
,
tc
:=
range
ssTests
{
tc
:=
tc
t
.
Run
(
fmt
.
Sprintf
(
"#%d"
,
i
),
func
(
t
*
testing
.
T
)
{
err
:=
ssProxyRoundtrip
(
httpSrv
.
URL
,
sendData
,
err
:=
ssProxyRoundtrip
(
httpSrv
.
URL
,
sendData
,
tc
.
clientCipher
,
tc
.
clientCipher
,
tc
.
serverCipher
,
tc
.
serverCipher
,
...
@@ -162,6 +165,7 @@ func TestSSProxy(t *testing.T) {
...
@@ -162,6 +165,7 @@ func TestSSProxy(t *testing.T) {
t
.
Errorf
(
"#%d got error: %v"
,
i
,
err
)
t
.
Errorf
(
"#%d got error: %v"
,
i
,
err
)
}
}
}
}
})
}
}
}
}
...
@@ -317,7 +321,7 @@ func shadowUDPRoundtrip(t *testing.T, host string, data []byte) error {
...
@@ -317,7 +321,7 @@ func shadowUDPRoundtrip(t *testing.T, host string, data []byte) error {
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
return
udpRoundtrip
(
client
,
server
,
host
,
data
)
}
}
func
TestShadowUDP
(
t
*
testing
.
T
)
{
func
_
TestShadowUDP
(
t
*
testing
.
T
)
{
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
:=
newUDPTestServer
(
udpTestHandler
)
udpSrv
.
Start
()
udpSrv
.
Start
()
defer
udpSrv
.
Close
()
defer
udpSrv
.
Close
()
...
...
tls.go
View file @
445889c4
...
@@ -58,21 +58,20 @@ func (tr *mtlsTransporter) Dial(addr string, options ...DialOption) (conn net.Co
...
@@ -58,21 +58,20 @@ func (tr *mtlsTransporter) Dial(addr string, options ...DialOption) (conn net.Co
option
(
opts
)
option
(
opts
)
}
}
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
tr
.
sessionMutex
.
Lock
()
tr
.
sessionMutex
.
Lock
()
defer
tr
.
sessionMutex
.
Unlock
()
defer
tr
.
sessionMutex
.
Unlock
()
session
,
ok
:=
tr
.
sessions
[
addr
]
session
,
ok
:=
tr
.
sessions
[
addr
]
if
session
!=
nil
&&
session
.
session
!=
nil
&&
session
.
session
.
IsClosed
()
{
if
session
!=
nil
&&
session
.
IsClosed
()
{
session
.
Close
()
delete
(
tr
.
sessions
,
addr
)
delete
(
tr
.
sessions
,
addr
)
ok
=
false
ok
=
false
// session is dead
}
}
if
!
ok
{
if
!
ok
{
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
if
opts
.
Chain
==
nil
{
if
opts
.
Chain
==
nil
{
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
}
else
{
}
else
{
...
@@ -159,10 +158,12 @@ func TLSListener(addr string, config *tls.Config) (Listener, error) {
...
@@ -159,10 +158,12 @@ func TLSListener(addr string, config *tls.Config) (Listener, error) {
if
config
==
nil
{
if
config
==
nil
{
config
=
DefaultTLSConfig
config
=
DefaultTLSConfig
}
}
ln
,
err
:=
tls
.
Listen
(
"tcp"
,
addr
,
config
)
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
ln
=
tls
.
NewListener
(
tcpKeepAliveListener
{
ln
.
(
*
net
.
TCPListener
)},
config
)
return
&
tlsListener
{
ln
},
nil
return
&
tlsListener
{
ln
},
nil
}
}
...
@@ -177,13 +178,13 @@ func MTLSListener(addr string, config *tls.Config) (Listener, error) {
...
@@ -177,13 +178,13 @@ func MTLSListener(addr string, config *tls.Config) (Listener, error) {
if
config
==
nil
{
if
config
==
nil
{
config
=
DefaultTLSConfig
config
=
DefaultTLSConfig
}
}
ln
,
err
:=
tls
.
Listen
(
"tcp"
,
addr
,
config
)
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
l
:=
&
mtlsListener
{
l
:=
&
mtlsListener
{
ln
:
ln
,
ln
:
tls
.
NewListener
(
tcpKeepAliveListener
{
ln
.
(
*
net
.
TCPListener
)},
config
)
,
connChan
:
make
(
chan
net
.
Conn
,
1024
),
connChan
:
make
(
chan
net
.
Conn
,
1024
),
errChan
:
make
(
chan
error
,
1
),
errChan
:
make
(
chan
error
,
1
),
}
}
...
...
ws.go
View file @
445889c4
...
@@ -28,92 +28,6 @@ type WSOptions struct {
...
@@ -28,92 +28,6 @@ type WSOptions struct {
UserAgent
string
UserAgent
string
}
}
type
websocketConn
struct
{
conn
*
websocket
.
Conn
rb
[]
byte
}
func
websocketClientConn
(
url
string
,
conn
net
.
Conn
,
tlsConfig
*
tls
.
Config
,
options
*
WSOptions
)
(
net
.
Conn
,
error
)
{
if
options
==
nil
{
options
=
&
WSOptions
{}
}
timeout
:=
options
.
HandshakeTimeout
if
timeout
<=
0
{
timeout
=
HandshakeTimeout
}
dialer
:=
websocket
.
Dialer
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
TLSClientConfig
:
tlsConfig
,
HandshakeTimeout
:
timeout
,
EnableCompression
:
options
.
EnableCompression
,
NetDial
:
func
(
net
,
addr
string
)
(
net
.
Conn
,
error
)
{
return
conn
,
nil
},
}
header
:=
http
.
Header
{}
header
.
Set
(
"User-Agent"
,
DefaultUserAgent
)
if
options
.
UserAgent
!=
""
{
header
.
Set
(
"User-Agent"
,
options
.
UserAgent
)
}
c
,
resp
,
err
:=
dialer
.
Dial
(
url
,
header
)
if
err
!=
nil
{
return
nil
,
err
}
resp
.
Body
.
Close
()
return
&
websocketConn
{
conn
:
c
},
nil
}
func
websocketServerConn
(
conn
*
websocket
.
Conn
)
net
.
Conn
{
// conn.EnableWriteCompression(true)
return
&
websocketConn
{
conn
:
conn
,
}
}
func
(
c
*
websocketConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
if
len
(
c
.
rb
)
==
0
{
_
,
c
.
rb
,
err
=
c
.
conn
.
ReadMessage
()
}
n
=
copy
(
b
,
c
.
rb
)
c
.
rb
=
c
.
rb
[
n
:
]
return
}
func
(
c
*
websocketConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
err
=
c
.
conn
.
WriteMessage
(
websocket
.
BinaryMessage
,
b
)
n
=
len
(
b
)
return
}
func
(
c
*
websocketConn
)
Close
()
error
{
return
c
.
conn
.
Close
()
}
func
(
c
*
websocketConn
)
LocalAddr
()
net
.
Addr
{
return
c
.
conn
.
LocalAddr
()
}
func
(
c
*
websocketConn
)
RemoteAddr
()
net
.
Addr
{
return
c
.
conn
.
RemoteAddr
()
}
func
(
c
*
websocketConn
)
SetDeadline
(
t
time
.
Time
)
error
{
if
err
:=
c
.
SetReadDeadline
(
t
);
err
!=
nil
{
return
err
}
return
c
.
SetWriteDeadline
(
t
)
}
func
(
c
*
websocketConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetReadDeadline
(
t
)
}
func
(
c
*
websocketConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
type
wsTransporter
struct
{
type
wsTransporter
struct
{
tcpTransporter
tcpTransporter
options
*
WSOptions
options
*
WSOptions
...
@@ -160,21 +74,20 @@ func (tr *mwsTransporter) Dial(addr string, options ...DialOption) (conn net.Con
...
@@ -160,21 +74,20 @@ func (tr *mwsTransporter) Dial(addr string, options ...DialOption) (conn net.Con
option
(
opts
)
option
(
opts
)
}
}
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
tr
.
sessionMutex
.
Lock
()
tr
.
sessionMutex
.
Lock
()
defer
tr
.
sessionMutex
.
Unlock
()
defer
tr
.
sessionMutex
.
Unlock
()
session
,
ok
:=
tr
.
sessions
[
addr
]
session
,
ok
:=
tr
.
sessions
[
addr
]
if
session
!=
nil
&&
session
.
session
!=
nil
&&
session
.
session
.
IsClosed
()
{
if
session
!=
nil
&&
session
.
IsClosed
()
{
session
.
Close
()
delete
(
tr
.
sessions
,
addr
)
delete
(
tr
.
sessions
,
addr
)
ok
=
false
ok
=
false
}
}
if
!
ok
{
if
!
ok
{
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
if
opts
.
Chain
==
nil
{
if
opts
.
Chain
==
nil
{
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
}
else
{
}
else
{
...
@@ -302,21 +215,20 @@ func (tr *mwssTransporter) Dial(addr string, options ...DialOption) (conn net.Co
...
@@ -302,21 +215,20 @@ func (tr *mwssTransporter) Dial(addr string, options ...DialOption) (conn net.Co
option
(
opts
)
option
(
opts
)
}
}
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
tr
.
sessionMutex
.
Lock
()
tr
.
sessionMutex
.
Lock
()
defer
tr
.
sessionMutex
.
Unlock
()
defer
tr
.
sessionMutex
.
Unlock
()
session
,
ok
:=
tr
.
sessions
[
addr
]
session
,
ok
:=
tr
.
sessions
[
addr
]
if
session
!=
nil
&&
session
.
session
!=
nil
&&
session
.
session
.
IsClosed
()
{
if
session
!=
nil
&&
session
.
IsClosed
()
{
session
.
Close
()
delete
(
tr
.
sessions
,
addr
)
delete
(
tr
.
sessions
,
addr
)
ok
=
false
ok
=
false
}
}
if
!
ok
{
if
!
ok
{
timeout
:=
opts
.
Timeout
if
timeout
<=
0
{
timeout
=
DialTimeout
}
if
opts
.
Chain
==
nil
{
if
opts
.
Chain
==
nil
{
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
conn
,
err
=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
}
else
{
}
else
{
...
@@ -428,7 +340,11 @@ func WSListener(addr string, options *WSOptions) (Listener, error) {
...
@@ -428,7 +340,11 @@ func WSListener(addr string, options *WSOptions) (Listener, error) {
mux
:=
http
.
NewServeMux
()
mux
:=
http
.
NewServeMux
()
mux
.
Handle
(
"/ws"
,
http
.
HandlerFunc
(
l
.
upgrade
))
mux
.
Handle
(
"/ws"
,
http
.
HandlerFunc
(
l
.
upgrade
))
l
.
srv
=
&
http
.
Server
{
Addr
:
addr
,
Handler
:
mux
}
l
.
srv
=
&
http
.
Server
{
Addr
:
addr
,
Handler
:
mux
,
ReadHeaderTimeout
:
30
*
time
.
Second
,
}
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -517,7 +433,11 @@ func MWSListener(addr string, options *WSOptions) (Listener, error) {
...
@@ -517,7 +433,11 @@ func MWSListener(addr string, options *WSOptions) (Listener, error) {
mux
:=
http
.
NewServeMux
()
mux
:=
http
.
NewServeMux
()
mux
.
Handle
(
"/ws"
,
http
.
HandlerFunc
(
l
.
upgrade
))
mux
.
Handle
(
"/ws"
,
http
.
HandlerFunc
(
l
.
upgrade
))
l
.
srv
=
&
http
.
Server
{
Addr
:
addr
,
Handler
:
mux
}
l
.
srv
=
&
http
.
Server
{
Addr
:
addr
,
Handler
:
mux
,
ReadHeaderTimeout
:
30
*
time
.
Second
,
}
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -637,6 +557,7 @@ func WSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Listen
...
@@ -637,6 +557,7 @@ func WSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Listen
Addr
:
addr
,
Addr
:
addr
,
TLSConfig
:
tlsConfig
,
TLSConfig
:
tlsConfig
,
Handler
:
mux
,
Handler
:
mux
,
ReadHeaderTimeout
:
30
*
time
.
Second
,
}
}
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
...
@@ -697,6 +618,7 @@ func MWSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Liste
...
@@ -697,6 +618,7 @@ func MWSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Liste
Addr
:
addr
,
Addr
:
addr
,
TLSConfig
:
tlsConfig
,
TLSConfig
:
tlsConfig
,
Handler
:
mux
,
Handler
:
mux
,
ReadHeaderTimeout
:
30
*
time
.
Second
,
}
}
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
ln
,
err
:=
net
.
ListenTCP
(
"tcp"
,
tcpAddr
)
...
@@ -737,3 +659,89 @@ func generateChallengeKey() (string, error) {
...
@@ -737,3 +659,89 @@ func generateChallengeKey() (string, error) {
}
}
return
base64
.
StdEncoding
.
EncodeToString
(
p
),
nil
return
base64
.
StdEncoding
.
EncodeToString
(
p
),
nil
}
}
type
websocketConn
struct
{
conn
*
websocket
.
Conn
rb
[]
byte
}
func
websocketClientConn
(
url
string
,
conn
net
.
Conn
,
tlsConfig
*
tls
.
Config
,
options
*
WSOptions
)
(
net
.
Conn
,
error
)
{
if
options
==
nil
{
options
=
&
WSOptions
{}
}
timeout
:=
options
.
HandshakeTimeout
if
timeout
<=
0
{
timeout
=
HandshakeTimeout
}
dialer
:=
websocket
.
Dialer
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
TLSClientConfig
:
tlsConfig
,
HandshakeTimeout
:
timeout
,
EnableCompression
:
options
.
EnableCompression
,
NetDial
:
func
(
net
,
addr
string
)
(
net
.
Conn
,
error
)
{
return
conn
,
nil
},
}
header
:=
http
.
Header
{}
header
.
Set
(
"User-Agent"
,
DefaultUserAgent
)
if
options
.
UserAgent
!=
""
{
header
.
Set
(
"User-Agent"
,
options
.
UserAgent
)
}
c
,
resp
,
err
:=
dialer
.
Dial
(
url
,
header
)
if
err
!=
nil
{
return
nil
,
err
}
resp
.
Body
.
Close
()
return
&
websocketConn
{
conn
:
c
},
nil
}
func
websocketServerConn
(
conn
*
websocket
.
Conn
)
net
.
Conn
{
// conn.EnableWriteCompression(true)
return
&
websocketConn
{
conn
:
conn
,
}
}
func
(
c
*
websocketConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
if
len
(
c
.
rb
)
==
0
{
_
,
c
.
rb
,
err
=
c
.
conn
.
ReadMessage
()
}
n
=
copy
(
b
,
c
.
rb
)
c
.
rb
=
c
.
rb
[
n
:
]
return
}
func
(
c
*
websocketConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
err
=
c
.
conn
.
WriteMessage
(
websocket
.
BinaryMessage
,
b
)
n
=
len
(
b
)
return
}
func
(
c
*
websocketConn
)
Close
()
error
{
return
c
.
conn
.
Close
()
}
func
(
c
*
websocketConn
)
LocalAddr
()
net
.
Addr
{
return
c
.
conn
.
LocalAddr
()
}
func
(
c
*
websocketConn
)
RemoteAddr
()
net
.
Addr
{
return
c
.
conn
.
RemoteAddr
()
}
func
(
c
*
websocketConn
)
SetDeadline
(
t
time
.
Time
)
error
{
if
err
:=
c
.
SetReadDeadline
(
t
);
err
!=
nil
{
return
err
}
return
c
.
SetWriteDeadline
(
t
)
}
func
(
c
*
websocketConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetReadDeadline
(
t
)
}
func
(
c
*
websocketConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
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