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
425099a7
Commit
425099a7
authored
Feb 03, 2020
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
merge ss2 and ss
parent
18a515a5
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
159 additions
and
840 deletions
+159
-840
cmd/gost/route.go
cmd/gost/route.go
+0
-4
node.go
node.go
+3
-1
ss.go
ss.go
+99
-158
ss2.go
ss2.go
+0
-229
ss2_test.go
ss2_test.go
+0
-425
ss_test.go
ss_test.go
+57
-23
No files found.
cmd/gost/route.go
View file @
425099a7
...
@@ -216,8 +216,6 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
...
@@ -216,8 +216,6 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
connector
=
gost
.
SOCKS4AConnector
()
connector
=
gost
.
SOCKS4AConnector
()
case
"ss"
:
case
"ss"
:
connector
=
gost
.
ShadowConnector
(
node
.
User
)
connector
=
gost
.
ShadowConnector
(
node
.
User
)
case
"ss2"
:
connector
=
gost
.
Shadow2Connector
(
node
.
User
)
case
"ssu"
:
case
"ssu"
:
connector
=
gost
.
ShadowUDPConnector
(
node
.
User
)
connector
=
gost
.
ShadowUDPConnector
(
node
.
User
)
case
"direct"
:
case
"direct"
:
...
@@ -505,8 +503,6 @@ func (r *route) GenRouters() ([]router, error) {
...
@@ -505,8 +503,6 @@ func (r *route) GenRouters() ([]router, error) {
handler
=
gost
.
SOCKS4Handler
()
handler
=
gost
.
SOCKS4Handler
()
case
"ss"
:
case
"ss"
:
handler
=
gost
.
ShadowHandler
()
handler
=
gost
.
ShadowHandler
()
case
"ss2"
:
handler
=
gost
.
Shadow2Handler
()
case
"http"
:
case
"http"
:
handler
=
gost
.
HTTPHandler
()
handler
=
gost
.
HTTPHandler
()
case
"tcp"
:
case
"tcp"
:
...
...
node.go
View file @
425099a7
...
@@ -102,7 +102,9 @@ func ParseNode(s string) (node Node, err error) {
...
@@ -102,7 +102,9 @@ func ParseNode(s string) (node Node, err error) {
case
"socks4"
,
"socks4a"
:
case
"socks4"
,
"socks4a"
:
case
"socks"
,
"socks5"
:
case
"socks"
,
"socks5"
:
node
.
Protocol
=
"socks5"
node
.
Protocol
=
"socks5"
case
"ss"
,
"ss2"
,
"ssu"
:
case
"ss"
,
"ssu"
:
case
"ss2"
:
// as of 2.10.1, ss2 is same as ss
node
.
Protocol
=
"ss"
case
"sni"
:
case
"sni"
:
case
"tcp"
,
"udp"
,
"rtcp"
,
"rudp"
:
// port forwarding
case
"tcp"
,
"udp"
,
"rtcp"
,
"rudp"
:
// port forwarding
case
"direct"
,
"remote"
,
"forward"
:
// forwarding
case
"direct"
,
"remote"
,
"forward"
:
// forwarding
...
...
ss.go
View file @
425099a7
...
@@ -7,7 +7,6 @@ import (
...
@@ -7,7 +7,6 @@ import (
"io"
"io"
"net"
"net"
"net/url"
"net/url"
"strconv"
"time"
"time"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gosocks5"
...
@@ -17,14 +16,15 @@ import (
...
@@ -17,14 +16,15 @@ import (
)
)
type
shadowConnector
struct
{
type
shadowConnector
struct
{
Cipher
*
url
.
Userinfo
cipher
core
.
Cipher
}
}
// ShadowConnector creates a Connector for shadowsocks proxy client.
// ShadowConnector creates a Connector for shadowsocks proxy client.
// It accepts a cipher info for shadowsocks data encryption/decryption.
// It accepts an optional cipher info for shadowsocks data encryption/decryption.
// The cipher must not be nil.
func
ShadowConnector
(
info
*
url
.
Userinfo
)
Connector
{
func
ShadowConnector
(
cipher
*
url
.
Userinfo
)
Connector
{
return
&
shadowConnector
{
return
&
shadowConnector
{
Cipher
:
cipher
}
cipher
:
initShadowCipher
(
info
),
}
}
}
func
(
c
*
shadowConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
,
options
...
ConnectOption
)
(
net
.
Conn
,
error
)
{
func
(
c
*
shadowConnector
)
Connect
(
conn
net
.
Conn
,
addr
string
,
options
...
ConnectOption
)
(
net
.
Conn
,
error
)
{
...
@@ -38,37 +38,32 @@ func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...Connect
...
@@ -38,37 +38,32 @@ func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...Connect
timeout
=
ConnectTimeout
timeout
=
ConnectTimeout
}
}
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
socksAddr
,
err
:=
gosocks5
.
NewAddr
(
addr
)
defer
conn
.
SetDeadline
(
time
.
Time
{})
rawaddr
,
err
:=
ss
.
RawAddr
(
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
rawaddr
:=
sPool
.
Get
()
.
([]
byte
)
defer
sPool
.
Put
(
rawaddr
)
var
method
,
password
string
n
,
err
:=
socksAddr
.
Encode
(
rawaddr
)
cp
:=
opts
.
User
if
cp
==
nil
{
cp
=
c
.
Cipher
}
if
cp
!=
nil
{
method
=
cp
.
Username
()
password
,
_
=
cp
.
Password
()
}
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
sc
:=
&
shadowConn
{
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
timeout
))
Conn
:
ss
.
NewConn
(
conn
,
cipher
),
defer
conn
.
SetDeadline
(
time
.
Time
{})
if
c
.
cipher
!=
nil
{
conn
=
c
.
cipher
.
StreamConn
(
conn
)
}
}
_
,
err
=
sc
.
Write
(
rawaddr
)
if
_
,
err
:=
conn
.
Write
(
rawaddr
[
:
n
]);
err
!=
nil
{
return
sc
,
err
return
nil
,
err
}
return
conn
,
nil
}
}
type
shadowHandler
struct
{
type
shadowHandler
struct
{
cipher
core
.
Cipher
options
*
HandlerOptions
options
*
HandlerOptions
}
}
...
@@ -88,37 +83,32 @@ func (h *shadowHandler) Init(options ...HandlerOption) {
...
@@ -88,37 +83,32 @@ func (h *shadowHandler) Init(options ...HandlerOption) {
for
_
,
opt
:=
range
options
{
for
_
,
opt
:=
range
options
{
opt
(
h
.
options
)
opt
(
h
.
options
)
}
}
if
len
(
h
.
options
.
Users
)
>
0
{
h
.
cipher
=
initShadowCipher
(
h
.
options
.
Users
[
0
])
}
}
}
func
(
h
*
shadowHandler
)
Handle
(
conn
net
.
Conn
)
{
func
(
h
*
shadowHandler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
defer
conn
.
Close
()
var
method
,
password
string
if
h
.
cipher
!=
nil
{
users
:=
h
.
options
.
Users
conn
=
h
.
cipher
.
StreamConn
(
conn
)
if
len
(
users
)
>
0
{
method
=
users
[
0
]
.
Username
()
password
,
_
=
users
[
0
]
.
Password
()
}
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
}
conn
=
&
shadowConn
{
Conn
:
ss
.
NewConn
(
conn
,
cipher
)}
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
host
,
err
:=
h
.
getRequest
(
conn
)
addr
,
err
:=
readSocksAddr
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s -> %s : %s"
,
log
.
Logf
(
"[ss] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
return
}
}
// clear timer
conn
.
SetReadDeadline
(
time
.
Time
{})
conn
.
SetReadDeadline
(
time
.
Time
{})
log
.
Logf
(
"[ss] %s -> %s -> %s"
,
host
:=
addr
.
String
()
conn
.
RemoteAddr
(),
h
.
options
.
Node
.
String
(),
host
)
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
host
)
if
!
Can
(
"tcp"
,
host
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
if
!
Can
(
"tcp"
,
host
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
log
.
Logf
(
"[ss] %s - %s : Unauthorized to tcp connect to %s"
,
log
.
Logf
(
"[ss] %s - %s : Unauthorized to tcp connect to %s"
,
...
@@ -181,104 +171,15 @@ func (h *shadowHandler) Handle(conn net.Conn) {
...
@@ -181,104 +171,15 @@ func (h *shadowHandler) Handle(conn net.Conn) {
log
.
Logf
(
"[ss] %s >-< %s"
,
conn
.
RemoteAddr
(),
host
)
log
.
Logf
(
"[ss] %s >-< %s"
,
conn
.
RemoteAddr
(),
host
)
}
}
const
(
idType
=
0
// address type index
idIP0
=
1
// ip address start index
idDmLen
=
1
// domain address length index
idDm0
=
2
// domain address start index
typeIPv4
=
1
// type is ipv4 address
typeDm
=
3
// type is domain address
typeIPv6
=
4
// type is ipv6 address
lenIPv4
=
net
.
IPv4len
+
2
// ipv4 + 2port
lenIPv6
=
net
.
IPv6len
+
2
// ipv6 + 2port
lenDmBase
=
2
// 1addrLen + 2port, plus addrLen
lenHmacSha1
=
10
)
// This function is copied from shadowsocks library with some modification.
func
(
h
*
shadowHandler
)
getRequest
(
r
io
.
Reader
)
(
host
string
,
err
error
)
{
// buf size should at least have the same size with the largest possible
// request size (when addrType is 3, domain name has at most 256 bytes)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
buf
:=
make
([]
byte
,
smallBufferSize
)
// read till we get possible domain length field
if
_
,
err
=
io
.
ReadFull
(
r
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
return
}
var
reqStart
,
reqEnd
int
addrType
:=
buf
[
idType
]
switch
addrType
&
ss
.
AddrMask
{
case
typeIPv4
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv4
case
typeIPv6
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
case
typeDm
:
if
_
,
err
=
io
.
ReadFull
(
r
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
return
}
reqStart
,
reqEnd
=
idDm0
,
idDm0
+
int
(
buf
[
idDmLen
])
+
lenDmBase
default
:
err
=
fmt
.
Errorf
(
"addr type %d not supported"
,
addrType
&
ss
.
AddrMask
)
return
}
if
_
,
err
=
io
.
ReadFull
(
r
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
return
}
// Return string for typeIP is not most efficient, but browsers (Chrome,
// Safari, Firefox) all seems using typeDm exclusively. So this is not a
// big problem.
switch
addrType
&
ss
.
AddrMask
{
case
typeIPv4
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv4len
])
.
String
()
case
typeIPv6
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv6len
])
.
String
()
case
typeDm
:
host
=
string
(
buf
[
idDm0
:
idDm0
+
int
(
buf
[
idDmLen
])])
}
// parse port
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
host
=
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
int
(
port
)))
return
}
type
shadowUDPConnector
struct
{
type
shadowUDPConnector
struct
{
cipher
core
.
Cipher
cipher
core
.
Cipher
}
}
// ShadowUDPConnector creates a Connector for shadowsocks UDP client.
// ShadowUDPConnector creates a Connector for shadowsocks UDP client.
// It accepts a cipher info for shadowsocks data encryption/decryption.
// It accepts an optional cipher info for shadowsocks data encryption/decryption.
// The cipher must not be nil.
func
ShadowUDPConnector
(
info
*
url
.
Userinfo
)
Connector
{
func
ShadowUDPConnector
(
info
*
url
.
Userinfo
)
Connector
{
c
:=
&
shadowUDPConnector
{}
return
&
shadowUDPConnector
{
c
.
initCipher
(
info
)
cipher
:
initShadowCipher
(
info
),
return
c
}
func
(
c
*
shadowUDPConnector
)
initCipher
(
info
*
url
.
Userinfo
)
{
var
method
,
password
string
if
info
!=
nil
{
method
=
info
.
Username
()
password
,
_
=
info
.
Password
()
}
if
method
==
""
||
password
==
""
{
return
}
c
.
cipher
,
_
=
core
.
PickCipher
(
method
,
nil
,
password
)
if
c
.
cipher
==
nil
{
cp
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
log
.
Logf
(
"[ssu] %s"
,
err
)
return
}
c
.
cipher
=
&
shadowCipher
{
cipher
:
cp
}
}
}
}
}
...
@@ -346,33 +247,11 @@ func (h *shadowUDPHandler) Init(options ...HandlerOption) {
...
@@ -346,33 +247,11 @@ func (h *shadowUDPHandler) Init(options ...HandlerOption) {
if
h
.
options
==
nil
{
if
h
.
options
==
nil
{
h
.
options
=
&
HandlerOptions
{}
h
.
options
=
&
HandlerOptions
{}
}
}
for
_
,
opt
:=
range
options
{
for
_
,
opt
:=
range
options
{
opt
(
h
.
options
)
opt
(
h
.
options
)
}
}
if
len
(
h
.
options
.
Users
)
>
0
{
h
.
initCipher
()
h
.
cipher
=
initShadowCipher
(
h
.
options
.
Users
[
0
])
}
func
(
h
*
shadowUDPHandler
)
initCipher
()
{
var
method
,
password
string
users
:=
h
.
options
.
Users
if
len
(
users
)
>
0
{
method
=
users
[
0
]
.
Username
()
password
,
_
=
users
[
0
]
.
Password
()
}
if
method
==
""
||
password
==
""
{
return
}
h
.
cipher
,
_
=
core
.
PickCipher
(
method
,
nil
,
password
)
if
h
.
cipher
==
nil
{
cp
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
log
.
Logf
(
"[ssu] %s"
,
err
)
return
}
h
.
cipher
=
&
shadowCipher
{
cipher
:
cp
}
}
}
}
}
...
@@ -668,9 +547,71 @@ type shadowCipher struct {
...
@@ -668,9 +547,71 @@ type shadowCipher struct {
}
}
func
(
c
*
shadowCipher
)
StreamConn
(
conn
net
.
Conn
)
net
.
Conn
{
func
(
c
*
shadowCipher
)
StreamConn
(
conn
net
.
Conn
)
net
.
Conn
{
return
ss
.
NewConn
(
conn
,
c
.
cipher
.
Copy
())
return
&
shadowConn
{
Conn
:
ss
.
NewConn
(
conn
,
c
.
cipher
.
Copy
()),
}
}
}
func
(
c
*
shadowCipher
)
PacketConn
(
conn
net
.
PacketConn
)
net
.
PacketConn
{
func
(
c
*
shadowCipher
)
PacketConn
(
conn
net
.
PacketConn
)
net
.
PacketConn
{
return
ss
.
NewSecurePacketConn
(
conn
,
c
.
cipher
.
Copy
(),
false
)
return
ss
.
NewSecurePacketConn
(
conn
,
c
.
cipher
.
Copy
(),
false
)
}
}
func
initShadowCipher
(
info
*
url
.
Userinfo
)
(
cipher
core
.
Cipher
)
{
var
method
,
password
string
if
info
!=
nil
{
method
=
info
.
Username
()
password
,
_
=
info
.
Password
()
}
if
method
==
""
||
password
==
""
{
return
}
cipher
,
_
=
core
.
PickCipher
(
method
,
nil
,
password
)
if
cipher
==
nil
{
cp
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s"
,
err
)
return
}
cipher
=
&
shadowCipher
{
cipher
:
cp
}
}
return
}
func
readSocksAddr
(
r
io
.
Reader
)
(
*
gosocks5
.
Addr
,
error
)
{
addr
:=
&
gosocks5
.
Addr
{}
b
:=
sPool
.
Get
()
.
([]
byte
)
defer
sPool
.
Put
(
b
)
_
,
err
:=
io
.
ReadFull
(
r
,
b
[
:
1
])
if
err
!=
nil
{
return
nil
,
err
}
addr
.
Type
=
b
[
0
]
switch
addr
.
Type
{
case
gosocks5
.
AddrIPv4
:
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
net
.
IPv4len
])
addr
.
Host
=
net
.
IP
(
b
[
0
:
net
.
IPv4len
])
.
String
()
case
gosocks5
.
AddrIPv6
:
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
net
.
IPv6len
])
addr
.
Host
=
net
.
IP
(
b
[
0
:
net
.
IPv6len
])
.
String
()
case
gosocks5
.
AddrDomain
:
if
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
1
]);
err
!=
nil
{
return
nil
,
err
}
addrlen
:=
int
(
b
[
0
])
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
addrlen
])
addr
.
Host
=
string
(
b
[
:
addrlen
])
default
:
return
nil
,
gosocks5
.
ErrBadAddrType
}
if
err
!=
nil
{
return
nil
,
err
}
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
2
])
addr
.
Port
=
binary
.
BigEndian
.
Uint16
(
b
[
:
2
])
return
addr
,
err
}
ss2.go
deleted
100644 → 0
View file @
18a515a5
package
gost
import
(
"bytes"
"encoding/binary"
"fmt"
"io"
"net"
"net/url"
"time"
"github.com/ginuerzh/gosocks5"
"github.com/go-log/log"
"github.com/shadowsocks/go-shadowsocks2/core"
)
type
shadow2Connector
struct
{
Cipher
*
url
.
Userinfo
}
// Shadow2Connector creates a Connector for go-shadowsocks2 proxy client.
// It accepts a cipher info for shadowsocks data encryption/decryption.
// The cipher must not be nil.
func
Shadow2Connector
(
cipher
*
url
.
Userinfo
)
Connector
{
return
&
shadow2Connector
{
Cipher
:
cipher
}
}
func
(
c
*
shadow2Connector
)
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
{})
socksAddr
,
err
:=
gosocks5
.
NewAddr
(
addr
)
if
err
!=
nil
{
return
nil
,
err
}
rawaddr
:=
sPool
.
Get
()
.
([]
byte
)
defer
sPool
.
Put
(
rawaddr
)
n
,
err
:=
socksAddr
.
Encode
(
rawaddr
)
if
err
!=
nil
{
return
nil
,
err
}
var
method
,
password
string
cp
:=
opts
.
User
if
cp
==
nil
{
cp
=
c
.
Cipher
}
if
cp
!=
nil
{
method
=
cp
.
Username
()
password
,
_
=
cp
.
Password
()
}
cipher
,
err
:=
core
.
PickCipher
(
method
,
nil
,
password
)
if
err
!=
nil
{
return
nil
,
err
}
conn
=
cipher
.
StreamConn
(
conn
)
if
_
,
err
:=
conn
.
Write
(
rawaddr
[
:
n
]);
err
!=
nil
{
return
nil
,
err
}
return
conn
,
nil
}
type
shadow2Handler
struct
{
options
*
HandlerOptions
}
// Shadow2Handler creates a server Handler for go-shadowsocks2 proxy server.
func
Shadow2Handler
(
opts
...
HandlerOption
)
Handler
{
h
:=
&
shadow2Handler
{}
h
.
Init
(
opts
...
)
return
h
}
func
(
h
*
shadow2Handler
)
Init
(
options
...
HandlerOption
)
{
if
h
.
options
==
nil
{
h
.
options
=
&
HandlerOptions
{}
}
for
_
,
opt
:=
range
options
{
opt
(
h
.
options
)
}
}
func
(
h
*
shadow2Handler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
var
method
,
password
string
users
:=
h
.
options
.
Users
if
len
(
users
)
>
0
{
method
=
users
[
0
]
.
Username
()
password
,
_
=
users
[
0
]
.
Password
()
}
cipher
,
err
:=
core
.
PickCipher
(
method
,
nil
,
password
)
if
err
!=
nil
{
log
.
Logf
(
"[ss2] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
conn
=
cipher
.
StreamConn
(
conn
)
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
addr
,
err
:=
readSocksAddr
(
conn
)
if
err
!=
nil
{
log
.
Logf
(
"[ss2] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
// clear timer
conn
.
SetReadDeadline
(
time
.
Time
{})
host
:=
addr
.
String
()
log
.
Logf
(
"[ss2] %s -> %s -> %s"
,
conn
.
RemoteAddr
(),
h
.
options
.
Node
.
String
(),
host
)
if
!
Can
(
"tcp"
,
host
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
log
.
Logf
(
"[ss2] %s - %s : Unauthorized to tcp connect to %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
host
)
return
}
if
h
.
options
.
Bypass
.
Contains
(
host
)
{
log
.
Logf
(
"[ss2] %s - %s : Bypass %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
host
)
return
}
retries
:=
1
if
h
.
options
.
Chain
!=
nil
&&
h
.
options
.
Chain
.
Retries
>
0
{
retries
=
h
.
options
.
Chain
.
Retries
}
if
h
.
options
.
Retries
>
0
{
retries
=
h
.
options
.
Retries
}
var
cc
net
.
Conn
var
route
*
Chain
for
i
:=
0
;
i
<
retries
;
i
++
{
route
,
err
=
h
.
options
.
Chain
.
selectRouteFor
(
host
)
if
err
!=
nil
{
log
.
Logf
(
"[ss2] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
continue
}
buf
:=
bytes
.
Buffer
{}
fmt
.
Fprintf
(
&
buf
,
"%s -> %s -> "
,
conn
.
RemoteAddr
(),
h
.
options
.
Node
.
String
())
for
_
,
nd
:=
range
route
.
route
{
fmt
.
Fprintf
(
&
buf
,
"%d@%s -> "
,
nd
.
ID
,
nd
.
String
())
}
fmt
.
Fprintf
(
&
buf
,
"%s"
,
host
)
log
.
Log
(
"[route]"
,
buf
.
String
())
cc
,
err
=
route
.
Dial
(
host
,
TimeoutChainOption
(
h
.
options
.
Timeout
),
HostsChainOption
(
h
.
options
.
Hosts
),
ResolverChainOption
(
h
.
options
.
Resolver
),
)
if
err
==
nil
{
break
}
log
.
Logf
(
"[ss2] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
}
if
err
!=
nil
{
return
}
defer
cc
.
Close
()
log
.
Logf
(
"[ss2] %s <-> %s"
,
conn
.
RemoteAddr
(),
host
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[ss2] %s >-< %s"
,
conn
.
RemoteAddr
(),
host
)
}
func
readSocksAddr
(
r
io
.
Reader
)
(
*
gosocks5
.
Addr
,
error
)
{
addr
:=
&
gosocks5
.
Addr
{}
b
:=
sPool
.
Get
()
.
([]
byte
)
defer
sPool
.
Put
(
b
)
_
,
err
:=
io
.
ReadFull
(
r
,
b
[
:
1
])
if
err
!=
nil
{
return
nil
,
err
}
addr
.
Type
=
b
[
0
]
switch
addr
.
Type
{
case
gosocks5
.
AddrIPv4
:
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
net
.
IPv4len
])
addr
.
Host
=
net
.
IP
(
b
[
0
:
net
.
IPv4len
])
.
String
()
case
gosocks5
.
AddrIPv6
:
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
net
.
IPv6len
])
addr
.
Host
=
net
.
IP
(
b
[
0
:
net
.
IPv6len
])
.
String
()
case
gosocks5
.
AddrDomain
:
if
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
1
]);
err
!=
nil
{
return
nil
,
err
}
addrlen
:=
int
(
b
[
0
])
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
addrlen
])
addr
.
Host
=
string
(
b
[
:
addrlen
])
default
:
return
nil
,
gosocks5
.
ErrBadAddrType
}
if
err
!=
nil
{
return
nil
,
err
}
_
,
err
=
io
.
ReadFull
(
r
,
b
[
:
2
])
addr
.
Port
=
binary
.
BigEndian
.
Uint16
(
b
[
:
2
])
return
addr
,
err
}
ss2_test.go
deleted
100644 → 0
View file @
18a515a5
This diff is collapsed.
Click to expand it.
ss_test.go
View file @
425099a7
This diff is collapsed.
Click to expand it.
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