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
b3068a7d
Commit
b3068a7d
authored
Nov 16, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of github.com:ginuerzh/gost into dev
parents
6974e9a8
6f935fc3
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
431 additions
and
204 deletions
+431
-204
chain.go
chain.go
+73
-66
client.go
client.go
+8
-0
cmd/gost/gost.json
cmd/gost/gost.json
+20
-0
cmd/gost/main.go
cmd/gost/main.go
+127
-47
cmd/gost/peer.json
cmd/gost/peer.json
+10
-0
gost.go
gost.go
+1
-0
handler.go
handler.go
+2
-1
http.go
http.go
+7
-0
node.go
node.go
+92
-8
obfs.go
obfs.go
+3
-2
selector.go
selector.go
+59
-60
sni.go
sni.go
+12
-4
ss.go
ss.go
+10
-9
ssh.go
ssh.go
+3
-3
ws.go
ws.go
+4
-4
No files found.
chain.go
View file @
b3068a7d
package
gost
package
gost
import
(
import
(
"bytes"
"errors"
"errors"
"fmt"
"net"
"net"
"strings"
"github.com/go-log/log"
"github.com/go-log/log"
)
)
...
@@ -15,6 +16,8 @@ var (
...
@@ -15,6 +16,8 @@ var (
// Chain is a proxy chain that holds a list of proxy nodes.
// Chain is a proxy chain that holds a list of proxy nodes.
type
Chain
struct
{
type
Chain
struct
{
isRoute
bool
Retries
int
nodeGroups
[]
*
NodeGroup
nodeGroups
[]
*
NodeGroup
}
}
...
@@ -27,6 +30,12 @@ func NewChain(nodes ...Node) *Chain {
...
@@ -27,6 +30,12 @@ func NewChain(nodes ...Node) *Chain {
return
chain
return
chain
}
}
func
newRoute
(
nodes
...
Node
)
*
Chain
{
chain
:=
NewChain
(
nodes
...
)
chain
.
isRoute
=
true
return
chain
}
// Nodes returns the proxy nodes that the chain holds.
// Nodes returns the proxy nodes that the chain holds.
// If a node is a node group, the first node in the group will be returned.
// If a node is a node group, the first node in the group will be returned.
func
(
c
*
Chain
)
Nodes
()
(
nodes
[]
Node
)
{
func
(
c
*
Chain
)
Nodes
()
(
nodes
[]
Node
)
{
...
@@ -50,8 +59,8 @@ func (c *Chain) LastNode() Node {
...
@@ -50,8 +59,8 @@ func (c *Chain) LastNode() Node {
if
c
.
IsEmpty
()
{
if
c
.
IsEmpty
()
{
return
Node
{}
return
Node
{}
}
}
last
:=
c
.
nodeGroups
[
len
(
c
.
nodeGroups
)
-
1
]
group
:=
c
.
nodeGroups
[
len
(
c
.
nodeGroups
)
-
1
]
return
last
.
nodes
[
0
]
return
group
.
nodes
[
0
]
.
Clone
()
}
}
// LastNodeGroup returns the last group of the group list.
// LastNodeGroup returns the last group of the group list.
...
@@ -90,17 +99,27 @@ func (c *Chain) IsEmpty() bool {
...
@@ -90,17 +99,27 @@ func (c *Chain) IsEmpty() bool {
// Dial connects to the target address addr through the chain.
// Dial connects to the target address addr through the chain.
// If the chain is empty, it will use the net.Dial directly.
// If the chain is empty, it will use the net.Dial directly.
func
(
c
*
Chain
)
Dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
Chain
)
Dial
(
addr
string
)
(
conn
net
.
Conn
,
err
error
)
{
if
c
.
IsEmpty
()
{
if
c
.
IsEmpty
()
{
return
net
.
Dial
(
"tcp"
,
addr
)
return
net
.
Dial
Timeout
(
"tcp"
,
addr
,
DialTimeout
)
}
}
for
i
:=
0
;
i
<
c
.
Retries
+
1
;
i
++
{
conn
,
err
=
c
.
dial
(
addr
)
if
err
==
nil
{
break
}
}
return
}
func
(
c
*
Chain
)
dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
route
,
err
:=
c
.
selectRoute
()
route
,
err
:=
c
.
selectRoute
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
conn
,
err
:=
c
.
getConn
(
route
)
conn
,
err
:=
route
.
getConn
(
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -116,77 +135,60 @@ func (c *Chain) Dial(addr string) (net.Conn, error) {
...
@@ -116,77 +135,60 @@ func (c *Chain) Dial(addr string) (net.Conn, error) {
// Conn obtains a handshaked connection to the last node of the chain.
// Conn obtains a handshaked connection to the last node of the chain.
// If the chain is empty, it returns an ErrEmptyChain error.
// If the chain is empty, it returns an ErrEmptyChain error.
func
(
c
*
Chain
)
Conn
()
(
conn
net
.
Conn
,
err
error
)
{
func
(
c
*
Chain
)
Conn
()
(
conn
net
.
Conn
,
err
error
)
{
route
,
err
:=
c
.
selectRoute
()
for
i
:=
0
;
i
<
c
.
Retries
+
1
;
i
++
{
if
err
!=
nil
{
var
route
*
Chain
return
nil
,
err
route
,
err
=
c
.
selectRoute
()
}
conn
,
err
=
c
.
getConn
(
route
)
return
}
func
(
c
*
Chain
)
selectRoute
()
(
route
*
Chain
,
err
error
)
{
route
=
NewChain
()
for
_
,
group
:=
range
c
.
nodeGroups
{
selector
:=
group
.
Selector
if
selector
==
nil
{
selector
=
&
defaultSelector
{}
}
// select node from node group
node
,
err
:=
selector
.
Select
(
group
.
Nodes
(),
group
.
Options
...
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
continue
}
}
if
node
.
Client
.
Transporter
.
Multiplex
()
{
conn
,
err
=
route
.
getConn
()
node
.
DialOptions
=
append
(
node
.
DialOptions
,
if
err
!=
nil
{
ChainDialOption
(
route
),
continue
)
route
=
NewChain
()
// cutoff the chain for multiplex
}
}
route
.
AddNode
(
node
)
break
}
}
return
return
}
}
func
(
c
*
Chain
)
getConn
(
route
*
Chain
)
(
conn
net
.
Conn
,
err
error
)
{
func
(
c
*
Chain
)
getConn
()
(
conn
net
.
Conn
,
err
error
)
{
if
route
.
IsEmpty
()
{
if
c
.
IsEmpty
()
{
err
=
ErrEmptyChain
err
=
ErrEmptyChain
return
return
}
}
nodes
:=
route
.
Nodes
()
nodes
:=
c
.
Nodes
()
node
:=
nodes
[
0
]
node
:=
nodes
[
0
]
addr
,
err
:=
selectIP
(
&
node
)
cn
,
err
:=
node
.
Client
.
Dial
(
node
.
Addr
,
node
.
DialOptions
...
)
if
err
!=
nil
{
return
}
cn
,
err
:=
node
.
Client
.
Dial
(
addr
,
node
.
DialOptions
...
)
if
err
!=
nil
{
if
err
!=
nil
{
node
.
MarkDead
()
return
return
}
}
cn
,
err
=
node
.
Client
.
Handshake
(
cn
,
node
.
HandshakeOptions
...
)
cn
,
err
=
node
.
Client
.
Handshake
(
cn
,
node
.
HandshakeOptions
...
)
if
err
!=
nil
{
if
err
!=
nil
{
node
.
MarkDead
()
return
return
}
}
node
.
ResetDead
()
preNode
:=
node
preNode
:=
node
for
_
,
node
:=
range
nodes
[
1
:
]
{
for
_
,
node
:=
range
nodes
[
1
:
]
{
addr
,
err
=
selectIP
(
&
node
)
if
err
!=
nil
{
return
}
var
cc
net
.
Conn
var
cc
net
.
Conn
cc
,
err
=
preNode
.
Client
.
Connect
(
cn
,
a
ddr
)
cc
,
err
=
preNode
.
Client
.
Connect
(
cn
,
node
.
A
ddr
)
if
err
!=
nil
{
if
err
!=
nil
{
cn
.
Close
()
cn
.
Close
()
node
.
MarkDead
()
return
return
}
}
cc
,
err
=
node
.
Client
.
Handshake
(
cc
,
node
.
HandshakeOptions
...
)
cc
,
err
=
node
.
Client
.
Handshake
(
cc
,
node
.
HandshakeOptions
...
)
if
err
!=
nil
{
if
err
!=
nil
{
cn
.
Close
()
cn
.
Close
()
node
.
MarkDead
()
return
return
}
}
node
.
ResetDead
()
cn
=
cc
cn
=
cc
preNode
=
node
preNode
=
node
}
}
...
@@ -195,29 +197,34 @@ func (c *Chain) getConn(route *Chain) (conn net.Conn, err error) {
...
@@ -195,29 +197,34 @@ func (c *Chain) getConn(route *Chain) (conn net.Conn, err error) {
return
return
}
}
func
selectIP
(
node
*
Node
)
(
string
,
error
)
{
func
(
c
*
Chain
)
selectRoute
()
(
route
*
Chain
,
err
error
)
{
addr
:=
node
.
Addr
if
c
.
isRoute
{
s
:=
node
.
IPSelector
return
c
,
nil
if
s
==
nil
{
s
=
&
RandomIPSelector
{}
}
}
// select IP from IP list
ip
,
err
:=
s
.
Select
(
node
.
IPs
)
buf
:=
bytes
.
Buffer
{}
if
err
!=
nil
{
route
=
newRoute
()
return
""
,
err
route
.
Retries
=
c
.
Retries
}
if
ip
!=
""
{
for
_
,
group
:=
range
c
.
nodeGroups
{
if
!
strings
.
Contains
(
ip
,
":"
)
{
node
,
err
:=
group
.
Next
()
_
,
sport
,
err
:=
net
.
SplitHostPort
(
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
""
,
err
}
ip
=
ip
+
":"
+
sport
}
}
addr
=
ip
buf
.
WriteString
(
fmt
.
Sprintf
(
"%s -> "
,
node
.
String
()))
// override the original address
node
.
HandshakeOptions
=
append
(
node
.
HandshakeOptions
,
AddrHandshakeOption
(
addr
))
if
node
.
Client
.
Transporter
.
Multiplex
()
{
node
.
DialOptions
=
append
(
node
.
DialOptions
,
ChainDialOption
(
route
),
)
route
=
newRoute
()
// cutoff the chain for multiplex.
route
.
Retries
=
c
.
Retries
}
route
.
AddNode
(
node
)
}
if
Debug
{
log
.
Log
(
"select route:"
,
buf
.
String
())
}
}
log
.
Log
(
"select IP:"
,
node
.
Addr
,
node
.
IPs
,
addr
)
return
return
addr
,
nil
}
}
client.go
View file @
b3068a7d
...
@@ -116,6 +116,7 @@ func ChainDialOption(chain *Chain) DialOption {
...
@@ -116,6 +116,7 @@ func ChainDialOption(chain *Chain) DialOption {
// HandshakeOptions describes the options for handshake.
// HandshakeOptions describes the options for handshake.
type
HandshakeOptions
struct
{
type
HandshakeOptions
struct
{
Addr
string
Addr
string
Host
string
User
*
url
.
Userinfo
User
*
url
.
Userinfo
Timeout
time
.
Duration
Timeout
time
.
Duration
Interval
time
.
Duration
Interval
time
.
Duration
...
@@ -136,6 +137,13 @@ func AddrHandshakeOption(addr string) HandshakeOption {
...
@@ -136,6 +137,13 @@ func AddrHandshakeOption(addr string) HandshakeOption {
}
}
}
}
// HostHandshakeOption specifies the hostname
func
HostHandshakeOption
(
host
string
)
HandshakeOption
{
return
func
(
opts
*
HandshakeOptions
)
{
opts
.
Host
=
host
}
}
// UserHandshakeOption specifies the user used by Transporter.Handshake
// UserHandshakeOption specifies the user used by Transporter.Handshake
func
UserHandshakeOption
(
user
*
url
.
Userinfo
)
HandshakeOption
{
func
UserHandshakeOption
(
user
*
url
.
Userinfo
)
HandshakeOption
{
return
func
(
opts
*
HandshakeOptions
)
{
return
func
(
opts
*
HandshakeOptions
)
{
...
...
cmd/gost/gost.json
View file @
b3068a7d
{
{
"Debug"
:
false
,
"Retries"
:
1
,
"ServeNodes"
:
[
"ServeNodes"
:
[
":8080"
,
":8080"
,
"ss://chacha20:12345678@:8338"
"ss://chacha20:12345678@:8338"
...
@@ -6,5 +8,23 @@
...
@@ -6,5 +8,23 @@
"ChainNodes"
:
[
"ChainNodes"
:
[
"http://192.168.1.1:8080"
,
"http://192.168.1.1:8080"
,
"https://10.0.2.1:443"
"https://10.0.2.1:443"
],
"Routes"
:
[
{
"Retries"
:
1
,
"ServeNodes"
:
[
"ws://:1443"
],
"ChainNodes"
:
[
"socks://:192.168.1.1:1080"
]
},
{
"Retries"
:
3
,
"ServeNodes"
:
[
"quic://:443"
]
}
]
]
}
}
\ No newline at end of file
cmd/gost/main.go
View file @
b3068a7d
...
@@ -22,10 +22,8 @@ import (
...
@@ -22,10 +22,8 @@ import (
)
)
var
(
var
(
options
struct
{
options
route
ChainNodes
,
ServeNodes
stringList
routes
[]
route
Debug
bool
}
)
)
func
init
()
{
func
init
()
{
...
@@ -43,12 +41,17 @@ func init() {
...
@@ -43,12 +41,17 @@ func init() {
flag
.
BoolVar
(
&
printVersion
,
"V"
,
false
,
"print version"
)
flag
.
BoolVar
(
&
printVersion
,
"V"
,
false
,
"print version"
)
flag
.
Parse
()
flag
.
Parse
()
if
len
(
options
.
ServeNodes
)
>
0
{
routes
=
append
(
routes
,
options
)
}
gost
.
Debug
=
options
.
Debug
if
err
:=
loadConfigureFile
(
configureFile
);
err
!=
nil
{
if
err
:=
loadConfigureFile
(
configureFile
);
err
!=
nil
{
log
.
Log
(
err
)
log
.
Log
(
err
)
os
.
Exit
(
1
)
os
.
Exit
(
1
)
}
}
if
flag
.
NFlag
()
==
0
{
if
flag
.
NFlag
()
==
0
||
len
(
routes
)
==
0
{
flag
.
PrintDefaults
()
flag
.
PrintDefaults
()
os
.
Exit
(
0
)
os
.
Exit
(
0
)
}
}
...
@@ -57,8 +60,6 @@ func init() {
...
@@ -57,8 +60,6 @@ func init() {
fmt
.
Fprintf
(
os
.
Stderr
,
"gost %s (%s)
\n
"
,
gost
.
Version
,
runtime
.
Version
())
fmt
.
Fprintf
(
os
.
Stderr
,
"gost %s (%s)
\n
"
,
gost
.
Version
,
runtime
.
Version
())
os
.
Exit
(
0
)
os
.
Exit
(
0
)
}
}
gost
.
Debug
=
options
.
Debug
}
}
func
main
()
{
func
main
()
{
...
@@ -72,45 +73,73 @@ func main() {
...
@@ -72,45 +73,73 @@ func main() {
Certificates
:
[]
tls
.
Certificate
{
cert
},
Certificates
:
[]
tls
.
Certificate
{
cert
},
}
}
chain
,
err
:=
initChain
()
for
_
,
route
:=
range
routes
{
if
err
!=
nil
{
if
err
:=
route
.
serve
();
err
!=
nil
{
log
.
Log
(
err
)
log
.
Log
(
err
)
os
.
Exit
(
1
)
os
.
Exit
(
1
)
}
}
if
err
:=
serve
(
chain
);
err
!=
nil
{
log
.
Log
(
err
)
os
.
Exit
(
1
)
}
}
select
{}
select
{}
}
}
func
initChain
()
(
*
gost
.
Chain
,
error
)
{
type
route
struct
{
ChainNodes
,
ServeNodes
stringList
Retries
int
Debug
bool
}
func
(
r
*
route
)
initChain
()
(
*
gost
.
Chain
,
error
)
{
chain
:=
gost
.
NewChain
()
chain
:=
gost
.
NewChain
()
for
_
,
ns
:=
range
options
.
ChainNodes
{
chain
.
Retries
=
r
.
Retries
gid
:=
1
// group ID
for
_
,
ns
:=
range
r
.
ChainNodes
{
ngroup
:=
gost
.
NewNodeGroup
()
ngroup
.
ID
=
gid
gid
++
// parse the base node
// parse the base node
node
,
err
:=
parseChainNode
(
ns
)
node
s
,
err
:=
parseChainNode
(
ns
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
n
group
:=
gost
.
NewNodeGroup
(
node
)
n
id
:=
1
// node ID
// parse node peers if exists
for
i
:=
range
nodes
{
peerCfg
,
err
:=
loadPeerConfig
(
node
.
Values
.
Get
(
"peer"
))
nodes
[
i
]
.
ID
=
nid
nid
++
}
ngroup
.
AddNode
(
nodes
...
)
// parse peer nodes if exists
peerCfg
,
err
:=
loadPeerConfig
(
nodes
[
0
]
.
Values
.
Get
(
"peer"
))
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Log
(
err
)
log
.
Log
(
err
)
}
}
peerCfg
.
Validate
()
ngroup
.
Options
=
append
(
ngroup
.
Options
,
ngroup
.
Options
=
append
(
ngroup
.
Options
,
// gost.WithFilter(),
gost
.
WithFilter
(
&
gost
.
FailFilter
{
MaxFails
:
peerCfg
.
MaxFails
,
FailTimeout
:
time
.
Duration
(
peerCfg
.
FailTimeout
)
*
time
.
Second
,
}),
gost
.
WithStrategy
(
parseStrategy
(
peerCfg
.
Strategy
)),
gost
.
WithStrategy
(
parseStrategy
(
peerCfg
.
Strategy
)),
)
)
for
_
,
s
:=
range
peerCfg
.
Nodes
{
for
_
,
s
:=
range
peerCfg
.
Nodes
{
node
,
err
=
parseChainNode
(
s
)
node
s
,
err
=
parseChainNode
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
ngroup
.
AddNode
(
node
)
for
i
:=
range
nodes
{
nodes
[
i
]
.
ID
=
nid
nid
++
}
ngroup
.
AddNode
(
nodes
...
)
}
}
chain
.
AddNodeGroup
(
ngroup
)
chain
.
AddNodeGroup
(
ngroup
)
...
@@ -119,15 +148,12 @@ func initChain() (*gost.Chain, error) {
...
@@ -119,15 +148,12 @@ func initChain() (*gost.Chain, error) {
return
chain
,
nil
return
chain
,
nil
}
}
func
parseChainNode
(
ns
string
)
(
node
gost
.
Node
,
err
error
)
{
func
parseChainNode
(
ns
string
)
(
node
s
[]
gost
.
Node
,
err
error
)
{
node
,
err
=
gost
.
ParseNode
(
ns
)
node
,
err
:
=
gost
.
ParseNode
(
ns
)
if
err
!=
nil
{
if
err
!=
nil
{
return
return
}
}
node
.
IPs
=
parseIP
(
node
.
Values
.
Get
(
"ip"
))
node
.
IPSelector
=
&
gost
.
RoundRobinIPSelector
{}
users
,
err
:=
parseUsers
(
node
.
Values
.
Get
(
"secrets"
))
users
,
err
:=
parseUsers
(
node
.
Values
.
Get
(
"secrets"
))
if
err
!=
nil
{
if
err
!=
nil
{
return
return
...
@@ -135,7 +161,7 @@ func parseChainNode(ns string) (node gost.Node, err error) {
...
@@ -135,7 +161,7 @@ func parseChainNode(ns string) (node gost.Node, err error) {
if
node
.
User
==
nil
&&
len
(
users
)
>
0
{
if
node
.
User
==
nil
&&
len
(
users
)
>
0
{
node
.
User
=
users
[
0
]
node
.
User
=
users
[
0
]
}
}
serverName
,
_
,
_
:=
net
.
SplitHostPort
(
node
.
Addr
)
serverName
,
sport
,
_
:=
net
.
SplitHostPort
(
node
.
Addr
)
if
serverName
==
""
{
if
serverName
==
""
{
serverName
=
"localhost"
// default server name
serverName
=
"localhost"
// default server name
}
}
...
@@ -177,7 +203,7 @@ func parseChainNode(ns string) (node gost.Node, err error) {
...
@@ -177,7 +203,7 @@ func parseChainNode(ns string) (node gost.Node, err error) {
*/
*/
config
,
err
:=
parseKCPConfig
(
node
.
Values
.
Get
(
"c"
))
config
,
err
:=
parseKCPConfig
(
node
.
Values
.
Get
(
"c"
))
if
err
!=
nil
{
if
err
!=
nil
{
return
n
ode
,
err
return
n
il
,
err
}
}
tr
=
gost
.
KCPTransporter
(
config
)
tr
=
gost
.
KCPTransporter
(
config
)
case
"ssh"
:
case
"ssh"
:
...
@@ -206,7 +232,7 @@ func parseChainNode(ns string) (node gost.Node, err error) {
...
@@ -206,7 +232,7 @@ func parseChainNode(ns string) (node gost.Node, err error) {
case
"obfs4"
:
case
"obfs4"
:
if
err
:=
gost
.
Obfs4Init
(
node
,
false
);
err
!=
nil
{
if
err
:=
gost
.
Obfs4Init
(
node
,
false
);
err
!=
nil
{
return
n
ode
,
err
return
n
il
,
err
}
}
tr
=
gost
.
Obfs4Transporter
()
tr
=
gost
.
Obfs4Transporter
()
case
"ohttp"
:
case
"ohttp"
:
...
@@ -249,24 +275,41 @@ func parseChainNode(ns string) (node gost.Node, err error) {
...
@@ -249,24 +275,41 @@ func parseChainNode(ns string) (node gost.Node, err error) {
interval
,
_
:=
strconv
.
Atoi
(
node
.
Values
.
Get
(
"ping"
))
interval
,
_
:=
strconv
.
Atoi
(
node
.
Values
.
Get
(
"ping"
))
retry
,
_
:=
strconv
.
Atoi
(
node
.
Values
.
Get
(
"retry"
))
retry
,
_
:=
strconv
.
Atoi
(
node
.
Values
.
Get
(
"retry"
))
node
.
HandshakeOptions
=
append
(
node
.
HandshakeOptions
,
handshakeOptions
:=
[]
gost
.
HandshakeOption
{
gost
.
AddrHandshakeOption
(
node
.
Addr
),
gost
.
AddrHandshakeOption
(
node
.
Addr
),
gost
.
HostHandshakeOption
(
node
.
Host
),
gost
.
UserHandshakeOption
(
node
.
User
),
gost
.
UserHandshakeOption
(
node
.
User
),
gost
.
TLSConfigHandshakeOption
(
tlsCfg
),
gost
.
TLSConfigHandshakeOption
(
tlsCfg
),
gost
.
IntervalHandshakeOption
(
time
.
Duration
(
interval
)
*
time
.
Second
),
gost
.
IntervalHandshakeOption
(
time
.
Duration
(
interval
)
*
time
.
Second
),
gost
.
TimeoutHandshakeOption
(
time
.
Duration
(
timeout
)
*
time
.
Second
),
gost
.
TimeoutHandshakeOption
(
time
.
Duration
(
timeout
)
*
time
.
Second
),
gost
.
RetryHandshakeOption
(
retry
),
gost
.
RetryHandshakeOption
(
retry
),
)
}
node
.
Client
=
&
gost
.
Client
{
node
.
Client
=
&
gost
.
Client
{
Connector
:
connector
,
Connector
:
connector
,
Transporter
:
tr
,
Transporter
:
tr
,
}
}
ips
:=
parseIP
(
node
.
Values
.
Get
(
"ip"
),
sport
)
for
_
,
ip
:=
range
ips
{
node
.
Addr
=
ip
node
.
HandshakeOptions
=
append
(
handshakeOptions
,
gost
.
AddrHandshakeOption
(
ip
))
nodes
=
append
(
nodes
,
node
)
}
if
len
(
ips
)
==
0
{
node
.
HandshakeOptions
=
handshakeOptions
nodes
=
[]
gost
.
Node
{
node
}
}
return
return
}
}
func
serve
(
chain
*
gost
.
Chain
)
error
{
func
(
r
*
route
)
serve
()
error
{
for
_
,
ns
:=
range
options
.
ServeNodes
{
chain
,
err
:=
r
.
initChain
()
if
err
!=
nil
{
return
err
}
for
_
,
ns
:=
range
r
.
ServeNodes
{
node
,
err
:=
gost
.
ParseNode
(
ns
)
node
,
err
:=
gost
.
ParseNode
(
ns
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -475,9 +518,24 @@ func loadConfigureFile(configureFile string) error {
...
@@ -475,9 +518,24 @@ func loadConfigureFile(configureFile string) error {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
json
.
Unmarshal
(
content
,
&
options
);
err
!=
nil
{
var
cfg
struct
{
route
Routes
[]
route
}
if
err
:=
json
.
Unmarshal
(
content
,
&
cfg
);
err
!=
nil
{
return
err
return
err
}
}
if
len
(
cfg
.
route
.
ServeNodes
)
>
0
{
routes
=
append
(
routes
,
cfg
.
route
)
}
for
_
,
route
:=
range
cfg
.
Routes
{
if
len
(
cfg
.
route
.
ServeNodes
)
>
0
{
routes
=
append
(
routes
,
route
)
}
}
gost
.
Debug
=
cfg
.
Debug
return
nil
return
nil
}
}
...
@@ -544,16 +602,23 @@ func parseUsers(authFile string) (users []*url.Userinfo, err error) {
...
@@ -544,16 +602,23 @@ func parseUsers(authFile string) (users []*url.Userinfo, err error) {
return
return
}
}
func
parseIP
(
s
string
)
(
ips
[]
string
)
{
func
parseIP
(
s
string
,
port
string
)
(
ips
[]
string
)
{
if
s
==
""
{
if
s
==
""
{
return
nil
return
}
}
if
port
==
""
{
port
=
"8080"
// default port
}
file
,
err
:=
os
.
Open
(
s
)
file
,
err
:=
os
.
Open
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
ss
:=
strings
.
Split
(
s
,
","
)
ss
:=
strings
.
Split
(
s
,
","
)
for
_
,
s
:=
range
ss
{
for
_
,
s
:=
range
ss
{
s
=
strings
.
TrimSpace
(
s
)
s
=
strings
.
TrimSpace
(
s
)
if
s
!=
""
{
if
s
!=
""
{
if
!
strings
.
Contains
(
s
,
":"
)
{
s
=
s
+
":"
+
port
}
ips
=
append
(
ips
,
s
)
ips
=
append
(
ips
,
s
)
}
}
...
@@ -567,15 +632,20 @@ func parseIP(s string) (ips []string) {
...
@@ -567,15 +632,20 @@ func parseIP(s string) (ips []string) {
if
line
==
""
||
strings
.
HasPrefix
(
line
,
"#"
)
{
if
line
==
""
||
strings
.
HasPrefix
(
line
,
"#"
)
{
continue
continue
}
}
if
!
strings
.
Contains
(
line
,
":"
)
{
line
=
line
+
":"
+
port
}
ips
=
append
(
ips
,
line
)
ips
=
append
(
ips
,
line
)
}
}
return
return
}
}
type
peerConfig
struct
{
type
peerConfig
struct
{
Strategy
string
`json:"strategy"`
Strategy
string
`json:"strategy"`
Filters
[]
string
`json:"filters"`
Filters
[]
string
`json:"filters"`
Nodes
[]
string
`json:"nodes"`
MaxFails
int
`json:"max_fails"`
FailTimeout
int
`json:"fail_timeout"`
Nodes
[]
string
`json:"nodes"`
}
}
func
loadPeerConfig
(
peer
string
)
(
config
peerConfig
,
err
error
)
{
func
loadPeerConfig
(
peer
string
)
(
config
peerConfig
,
err
error
)
{
...
@@ -590,13 +660,23 @@ func loadPeerConfig(peer string) (config peerConfig, err error) {
...
@@ -590,13 +660,23 @@ func loadPeerConfig(peer string) (config peerConfig, err error) {
return
return
}
}
func
(
cfg
*
peerConfig
)
Validate
()
{
if
cfg
.
MaxFails
<=
0
{
cfg
.
MaxFails
=
3
}
if
cfg
.
FailTimeout
<=
0
{
cfg
.
FailTimeout
=
30
// seconds
}
}
func
parseStrategy
(
s
string
)
gost
.
Strategy
{
func
parseStrategy
(
s
string
)
gost
.
Strategy
{
switch
s
{
switch
s
{
case
"round"
:
return
&
gost
.
RoundStrategy
{}
case
"random"
:
case
"random"
:
return
&
gost
.
RandomStrategy
{}
case
"round"
:
fallthrough
fallthrough
default
:
default
:
return
&
gost
.
RandomStrategy
{}
return
&
gost
.
RoundStrategy
{}
}
}
}
}
cmd/gost/peer.json
0 → 100644
View file @
b3068a7d
{
"strategy"
:
"round"
,
"max_fails"
:
3
,
"fail_timeout"
:
30
,
"nodes"
:[
"socks5://:1081"
,
"socks://:1082"
,
"socks4a://:1083"
]
}
\ No newline at end of file
gost.go
View file @
b3068a7d
...
@@ -56,6 +56,7 @@ func SetLogger(logger log.Logger) {
...
@@ -56,6 +56,7 @@ func SetLogger(logger log.Logger) {
log
.
DefaultLogger
=
logger
log
.
DefaultLogger
=
logger
}
}
// GenCertificate generates a random TLS certificate
func
GenCertificate
()
(
cert
tls
.
Certificate
,
err
error
)
{
func
GenCertificate
()
(
cert
tls
.
Certificate
,
err
error
)
{
rawCert
,
rawKey
,
err
:=
generateKeyPair
()
rawCert
,
rawKey
,
err
:=
generateKeyPair
()
if
err
!=
nil
{
if
err
!=
nil
{
...
...
handler.go
View file @
b3068a7d
...
@@ -95,7 +95,8 @@ func (h *autoHandler) Handle(conn net.Conn) {
...
@@ -95,7 +95,8 @@ func (h *autoHandler) Handle(conn net.Conn) {
cc
:=
&
bufferdConn
{
Conn
:
conn
,
br
:
br
}
cc
:=
&
bufferdConn
{
Conn
:
conn
,
br
:
br
}
switch
b
[
0
]
{
switch
b
[
0
]
{
case
gosocks4
.
Ver4
:
case
gosocks4
.
Ver4
:
return
// SOCKS4(a) does not suppport authentication method, so we ignore it.
cc
.
Close
()
return
// SOCKS4(a) does not suppport authentication method, so we ignore it for security reason.
case
gosocks5
.
Ver5
:
case
gosocks5
.
Ver5
:
SOCKS5Handler
(
h
.
options
...
)
.
Handle
(
cc
)
SOCKS5Handler
(
h
.
options
...
)
.
Handle
(
cc
)
default
:
// http
default
:
// http
...
...
http.go
View file @
b3068a7d
...
@@ -93,6 +93,13 @@ func (h *httpHandler) Handle(conn net.Conn) {
...
@@ -93,6 +93,13 @@ func (h *httpHandler) Handle(conn net.Conn) {
return
return
}
}
h
.
handleRequest
(
conn
,
req
)
}
func
(
h
*
httpHandler
)
handleRequest
(
conn
net
.
Conn
,
req
*
http
.
Request
)
{
if
req
==
nil
{
return
}
if
Debug
{
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
log
.
Logf
(
"[http] %s -> %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
string
(
dump
))
log
.
Logf
(
"[http] %s -> %s
\n
%s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
string
(
dump
))
...
...
node.go
View file @
b3068a7d
package
gost
package
gost
import
(
import
(
"fmt"
"net/url"
"net/url"
"strings"
"strings"
"sync/atomic"
"time"
)
)
// Node is a proxy node, mainly used to construct a proxy chain.
// Node is a proxy node, mainly used to construct a proxy chain.
type
Node
struct
{
type
Node
struct
{
ID
int
Addr
string
Addr
string
IPs
[]
string
Host
string
Protocol
string
Protocol
string
Transport
string
Transport
string
Remote
string
// remote address, used by tcp/udp port forwarding
Remote
string
// remote address, used by tcp/udp port forwarding
...
@@ -17,7 +21,9 @@ type Node struct {
...
@@ -17,7 +21,9 @@ type Node struct {
DialOptions
[]
DialOption
DialOptions
[]
DialOption
HandshakeOptions
[]
HandshakeOption
HandshakeOptions
[]
HandshakeOption
Client
*
Client
Client
*
Client
IPSelector
IPSelector
group
*
NodeGroup
failCount
uint32
failTime
int64
}
}
// ParseNode parses the node info.
// ParseNode parses the node info.
...
@@ -38,6 +44,7 @@ func ParseNode(s string) (node Node, err error) {
...
@@ -38,6 +44,7 @@ func ParseNode(s string) (node Node, err error) {
node
=
Node
{
node
=
Node
{
Addr
:
u
.
Host
,
Addr
:
u
.
Host
,
Host
:
u
.
Host
,
Remote
:
strings
.
Trim
(
u
.
EscapedPath
(),
"/"
),
Remote
:
strings
.
Trim
(
u
.
EscapedPath
(),
"/"
),
Values
:
u
.
Query
(),
Values
:
u
.
Query
(),
User
:
u
.
User
,
User
:
u
.
User
,
...
@@ -79,8 +86,68 @@ func ParseNode(s string) (node Node, err error) {
...
@@ -79,8 +86,68 @@ func ParseNode(s string) (node Node, err error) {
return
return
}
}
// MarkDead marks the node fail status.
func
(
node
*
Node
)
MarkDead
()
{
atomic
.
AddUint32
(
&
node
.
failCount
,
1
)
atomic
.
StoreInt64
(
&
node
.
failTime
,
time
.
Now
()
.
Unix
())
if
node
.
group
==
nil
{
return
}
for
i
:=
range
node
.
group
.
nodes
{
if
node
.
group
.
nodes
[
i
]
.
ID
==
node
.
ID
{
atomic
.
AddUint32
(
&
node
.
group
.
nodes
[
i
]
.
failCount
,
1
)
atomic
.
StoreInt64
(
&
node
.
group
.
nodes
[
i
]
.
failTime
,
time
.
Now
()
.
Unix
())
break
}
}
}
// ResetDead resets the node fail status.
func
(
node
*
Node
)
ResetDead
()
{
atomic
.
StoreUint32
(
&
node
.
failCount
,
0
)
atomic
.
StoreInt64
(
&
node
.
failTime
,
0
)
if
node
.
group
==
nil
{
return
}
for
i
:=
range
node
.
group
.
nodes
{
if
node
.
group
.
nodes
[
i
]
.
ID
==
node
.
ID
{
atomic
.
StoreUint32
(
&
node
.
group
.
nodes
[
i
]
.
failCount
,
0
)
atomic
.
StoreInt64
(
&
node
.
group
.
nodes
[
i
]
.
failTime
,
0
)
break
}
}
}
// Clone clones the node, it will prevent data race.
func
(
node
*
Node
)
Clone
()
Node
{
return
Node
{
ID
:
node
.
ID
,
Addr
:
node
.
Addr
,
Host
:
node
.
Host
,
Protocol
:
node
.
Protocol
,
Transport
:
node
.
Transport
,
Remote
:
node
.
Remote
,
User
:
node
.
User
,
Values
:
node
.
Values
,
DialOptions
:
node
.
DialOptions
,
HandshakeOptions
:
node
.
HandshakeOptions
,
Client
:
node
.
Client
,
group
:
node
.
group
,
failCount
:
atomic
.
LoadUint32
(
&
node
.
failCount
),
failTime
:
atomic
.
LoadInt64
(
&
node
.
failTime
),
}
}
func
(
node
*
Node
)
String
()
string
{
return
fmt
.
Sprintf
(
"%d@%s"
,
node
.
ID
,
node
.
Addr
)
}
// NodeGroup is a group of nodes.
// NodeGroup is a group of nodes.
type
NodeGroup
struct
{
type
NodeGroup
struct
{
ID
int
nodes
[]
Node
nodes
[]
Node
Options
[]
SelectOption
Options
[]
SelectOption
Selector
NodeSelector
Selector
NodeSelector
...
@@ -94,17 +161,34 @@ func NewNodeGroup(nodes ...Node) *NodeGroup {
...
@@ -94,17 +161,34 @@ func NewNodeGroup(nodes ...Node) *NodeGroup {
}
}
// AddNode adds node or node list into group
// AddNode adds node or node list into group
func
(
ng
*
NodeGroup
)
AddNode
(
node
...
Node
)
{
func
(
group
*
NodeGroup
)
AddNode
(
node
...
Node
)
{
if
ng
==
nil
{
if
group
==
nil
{
return
return
}
}
ng
.
nodes
=
append
(
ng
.
nodes
,
node
...
)
group
.
nodes
=
append
(
group
.
nodes
,
node
...
)
}
}
// Nodes returns node list in the group
// Nodes returns node list in the group
func
(
ng
*
NodeGroup
)
Nodes
()
[]
Node
{
func
(
group
*
NodeGroup
)
Nodes
()
[]
Node
{
if
ng
==
nil
{
if
group
==
nil
{
return
nil
return
nil
}
}
return
ng
.
nodes
return
group
.
nodes
}
// Next selects the next node from group.
// It also selects IP if the IP list exists.
func
(
group
*
NodeGroup
)
Next
()
(
node
Node
,
err
error
)
{
selector
:=
group
.
Selector
if
selector
==
nil
{
selector
=
&
defaultSelector
{}
}
// select node from node group
node
,
err
=
selector
.
Select
(
group
.
Nodes
(),
group
.
Options
...
)
if
err
!=
nil
{
return
}
node
.
group
=
group
return
}
}
obfs.go
View file @
b3068a7d
...
@@ -35,7 +35,7 @@ func (tr *obfsHTTPTransporter) Handshake(conn net.Conn, options ...HandshakeOpti
...
@@ -35,7 +35,7 @@ func (tr *obfsHTTPTransporter) Handshake(conn net.Conn, options ...HandshakeOpti
for
_
,
option
:=
range
options
{
for
_
,
option
:=
range
options
{
option
(
opts
)
option
(
opts
)
}
}
return
&
obfsHTTPConn
{
Conn
:
conn
},
nil
return
&
obfsHTTPConn
{
Conn
:
conn
,
host
:
opts
.
Host
},
nil
}
}
type
obfsHTTPListener
struct
{
type
obfsHTTPListener
struct
{
...
@@ -66,6 +66,7 @@ func (l *obfsHTTPListener) Accept() (net.Conn, error) {
...
@@ -66,6 +66,7 @@ func (l *obfsHTTPListener) Accept() (net.Conn, error) {
type
obfsHTTPConn
struct
{
type
obfsHTTPConn
struct
{
net
.
Conn
net
.
Conn
host
string
request
*
http
.
Request
request
*
http
.
Request
response
*
http
.
Response
response
*
http
.
Response
rbuf
[]
byte
rbuf
[]
byte
...
@@ -151,7 +152,7 @@ func (c *obfsHTTPConn) clientHandshake() (err error) {
...
@@ -151,7 +152,7 @@ func (c *obfsHTTPConn) clientHandshake() (err error) {
Method
:
http
.
MethodGet
,
Method
:
http
.
MethodGet
,
ProtoMajor
:
1
,
ProtoMajor
:
1
,
ProtoMinor
:
1
,
ProtoMinor
:
1
,
URL
:
&
url
.
URL
{
Scheme
:
"http"
,
Host
:
"www.baidu.com"
},
URL
:
&
url
.
URL
{
Scheme
:
"http"
,
Host
:
c
.
host
},
Header
:
make
(
http
.
Header
),
Header
:
make
(
http
.
Header
),
}
}
r
.
Header
.
Set
(
"Connection"
,
"keep-alive"
)
r
.
Header
.
Set
(
"Connection"
,
"keep-alive"
)
...
...
selector.go
View file @
b3068a7d
...
@@ -2,6 +2,8 @@ package gost
...
@@ -2,6 +2,8 @@ package gost
import
(
import
(
"errors"
"errors"
"math/rand"
"sync"
"sync/atomic"
"sync/atomic"
"time"
"time"
)
)
...
@@ -37,9 +39,28 @@ func (s *defaultSelector) Select(nodes []Node, opts ...SelectOption) (Node, erro
...
@@ -37,9 +39,28 @@ func (s *defaultSelector) Select(nodes []Node, opts ...SelectOption) (Node, erro
return
sopts
.
Strategy
.
Apply
(
nodes
),
nil
return
sopts
.
Strategy
.
Apply
(
nodes
),
nil
}
}
// Filter is used to filter a node during the selection process
// SelectOption used when making a select call
type
Filter
interface
{
type
SelectOption
func
(
*
SelectOptions
)
Filter
([]
Node
)
[]
Node
// SelectOptions is the options for node selection
type
SelectOptions
struct
{
Filters
[]
Filter
Strategy
Strategy
}
// WithFilter adds a filter function to the list of filters
// used during the Select call.
func
WithFilter
(
f
...
Filter
)
SelectOption
{
return
func
(
o
*
SelectOptions
)
{
o
.
Filters
=
append
(
o
.
Filters
,
f
...
)
}
}
// WithStrategy sets the selector strategy
func
WithStrategy
(
s
Strategy
)
SelectOption
{
return
func
(
o
*
SelectOptions
)
{
o
.
Strategy
=
s
}
}
}
// Strategy is a selection strategy e.g random, round robin
// Strategy is a selection strategy e.g random, round robin
...
@@ -58,7 +79,7 @@ func (s *RoundStrategy) Apply(nodes []Node) Node {
...
@@ -58,7 +79,7 @@ func (s *RoundStrategy) Apply(nodes []Node) Node {
if
len
(
nodes
)
==
0
{
if
len
(
nodes
)
==
0
{
return
Node
{}
return
Node
{}
}
}
old
:=
s
.
count
old
:=
atomic
.
LoadUint64
(
&
s
.
count
)
atomic
.
AddUint64
(
&
s
.
count
,
1
)
atomic
.
AddUint64
(
&
s
.
count
,
1
)
return
nodes
[
int
(
old
%
uint64
(
len
(
nodes
)))]
return
nodes
[
int
(
old
%
uint64
(
len
(
nodes
)))]
}
}
...
@@ -68,82 +89,60 @@ func (s *RoundStrategy) String() string {
...
@@ -68,82 +89,60 @@ func (s *RoundStrategy) String() string {
}
}
// RandomStrategy is a strategy for node selector
// RandomStrategy is a strategy for node selector
type
RandomStrategy
struct
{}
type
RandomStrategy
struct
{
Seed
int64
rand
*
rand
.
Rand
once
sync
.
Once
}
// Apply applies the random strategy for the nodes
// Apply applies the random strategy for the nodes
func
(
s
*
RandomStrategy
)
Apply
(
nodes
[]
Node
)
Node
{
func
(
s
*
RandomStrategy
)
Apply
(
nodes
[]
Node
)
Node
{
s
.
once
.
Do
(
func
()
{
seed
:=
s
.
Seed
if
seed
==
0
{
seed
=
time
.
Now
()
.
UnixNano
()
}
s
.
rand
=
rand
.
New
(
rand
.
NewSource
(
seed
))
})
if
len
(
nodes
)
==
0
{
if
len
(
nodes
)
==
0
{
return
Node
{}
return
Node
{}
}
}
return
nodes
[
time
.
Now
()
.
Nanosecond
()
%
len
(
nodes
)]
return
nodes
[
s
.
rand
.
Int
()
%
len
(
nodes
)]
}
}
func
(
s
*
RandomStrategy
)
String
()
string
{
func
(
s
*
RandomStrategy
)
String
()
string
{
return
"random"
return
"random"
}
}
// SelectOption used when making a select call
// Filter is used to filter a node during the selection process
type
SelectOption
func
(
*
SelectOptions
)
type
Filter
interface
{
Filter
([]
Node
)
[]
Node
// SelectOptions is the options for node selection
type
SelectOptions
struct
{
Filters
[]
Filter
Strategy
Strategy
}
// WithFilter adds a filter function to the list of filters
// used during the Select call.
func
WithFilter
(
f
...
Filter
)
SelectOption
{
return
func
(
o
*
SelectOptions
)
{
o
.
Filters
=
append
(
o
.
Filters
,
f
...
)
}
}
// WithStrategy sets the selector strategy
func
WithStrategy
(
s
Strategy
)
SelectOption
{
return
func
(
o
*
SelectOptions
)
{
o
.
Strategy
=
s
}
}
// IPSelector as a mechanism to pick IPs and mark their status.
type
IPSelector
interface
{
Select
(
ips
[]
string
)
(
string
,
error
)
String
()
string
String
()
string
}
}
// RandomIPSelector is an IP Selector that selects an IP with random strategy.
// FailFilter filters the dead node.
type
RandomIPSelector
struct
{
// A node is marked as dead if its failed count is greater than MaxFails.
type
FailFilter
struct
{
MaxFails
int
FailTimeout
time
.
Duration
}
}
//
Select selects an IP from ips list
.
//
Filter filters nodes
.
func
(
s
*
RandomIPSelector
)
Select
(
ips
[]
string
)
(
string
,
error
)
{
func
(
f
*
FailFilter
)
Filter
(
nodes
[]
Node
)
[]
Node
{
if
len
(
ips
)
=
=
0
{
if
f
.
MaxFails
<
=
0
{
return
""
,
nil
return
nodes
}
}
return
ips
[
time
.
Now
()
.
Nanosecond
()
%
len
(
ips
)],
nil
nl
:=
[]
Node
{}
}
for
i
:=
range
nodes
{
if
atomic
.
LoadUint32
(
&
nodes
[
i
]
.
failCount
)
<
uint32
(
f
.
MaxFails
)
||
func
(
s
*
RandomIPSelector
)
String
()
string
{
time
.
Since
(
time
.
Unix
(
atomic
.
LoadInt64
(
&
nodes
[
i
]
.
failTime
),
0
))
>=
f
.
FailTimeout
{
return
"random"
nl
=
append
(
nl
,
nodes
[
i
]
.
Clone
())
}
}
// RoundRobinIPSelector is an IP Selector that selects an IP with round-robin strategy.
type
RoundRobinIPSelector
struct
{
count
uint64
}
// Select selects an IP from ips list.
func
(
s
*
RoundRobinIPSelector
)
Select
(
ips
[]
string
)
(
string
,
error
)
{
if
len
(
ips
)
==
0
{
return
""
,
nil
}
}
old
:=
s
.
count
return
nl
atomic
.
AddUint64
(
&
s
.
count
,
1
)
return
ips
[
int
(
old
%
uint64
(
len
(
ips
)))],
nil
}
}
func
(
s
*
RoundRobinIPSelecto
r
)
String
()
string
{
func
(
f
*
FailFilte
r
)
String
()
string
{
return
"
round
"
return
"
fail
"
}
}
sni.go
View file @
b3068a7d
...
@@ -11,6 +11,7 @@ import (
...
@@ -11,6 +11,7 @@ import (
"hash/crc32"
"hash/crc32"
"io"
"io"
"net"
"net"
"net/http"
"strings"
"strings"
"sync"
"sync"
...
@@ -53,15 +54,22 @@ func (h *sniHandler) Handle(conn net.Conn) {
...
@@ -53,15 +54,22 @@ func (h *sniHandler) Handle(conn net.Conn) {
return
return
}
}
conn
=
&
bufferdConn
{
br
:
br
,
Conn
:
conn
}
conn
=
&
bufferdConn
{
br
:
br
,
Conn
:
conn
}
defer
conn
.
Close
()
if
hdr
[
0
]
!=
dissector
.
Handshake
{
if
hdr
[
0
]
!=
dissector
.
Handshake
{
// We assume that it is HTTP request
// We assume it is an HTTP request
HTTPHandler
(
h
.
options
...
)
.
Handle
(
conn
)
req
,
err
:=
http
.
ReadRequest
(
bufio
.
NewReader
(
conn
))
if
!
req
.
URL
.
IsAbs
()
{
req
.
URL
.
Scheme
=
"http"
// make sure that the URL is absolute
}
if
err
!=
nil
{
log
.
Logf
(
"[sni] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
HTTPHandler
(
h
.
options
...
)
.
(
*
httpHandler
)
.
handleRequest
(
conn
,
req
)
return
return
}
}
defer
conn
.
Close
()
b
,
host
,
err
:=
readClientHelloRecord
(
conn
,
""
,
false
)
b
,
host
,
err
:=
readClientHelloRecord
(
conn
,
""
,
false
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Log
(
"[sni]"
,
err
)
log
.
Log
(
"[sni]"
,
err
)
...
...
ss.go
View file @
b3068a7d
...
@@ -124,11 +124,15 @@ func (h *shadowHandler) Handle(conn net.Conn) {
...
@@ -124,11 +124,15 @@ func (h *shadowHandler) Handle(conn net.Conn) {
log
.
Logf
(
"[ss] %s - %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
log
.
Logf
(
"[ss] %s - %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
addr
,
err
:=
h
.
getRequest
(
conn
)
addr
,
err
:=
h
.
getRequest
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
log
.
Logf
(
"[ss] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
return
}
}
// clear timer
conn
.
SetReadDeadline
(
time
.
Time
{})
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
addr
)
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
addr
)
if
!
Can
(
"tcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
if
!
Can
(
"tcp"
,
addr
,
h
.
options
.
Whitelist
,
h
.
options
.
Blacklist
)
{
...
@@ -165,19 +169,16 @@ const (
...
@@ -165,19 +169,16 @@ const (
)
)
// This function is copied from shadowsocks library with some modification.
// This function is copied from shadowsocks library with some modification.
func
(
h
*
shadowHandler
)
getRequest
(
conn
net
.
Conn
)
(
host
string
,
err
error
)
{
func
(
h
*
shadowHandler
)
getRequest
(
r
io
.
Reader
)
(
host
string
,
err
error
)
{
// buf size should at least have the same size with the largest possible
// 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)
// request size (when addrType is 3, domain name has at most 256 bytes)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
buf
:=
make
([]
byte
,
smallBufferSize
)
buf
:=
make
([]
byte
,
smallBufferSize
)
// read till we get possible domain length field
// read till we get possible domain length field
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
if
_
,
err
=
io
.
ReadFull
(
r
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
return
return
}
}
// clear timer
conn
.
SetReadDeadline
(
time
.
Time
{})
var
reqStart
,
reqEnd
int
var
reqStart
,
reqEnd
int
addrType
:=
buf
[
idType
]
addrType
:=
buf
[
idType
]
...
@@ -187,16 +188,16 @@ func (h *shadowHandler) getRequest(conn net.Conn) (host string, err error) {
...
@@ -187,16 +188,16 @@ func (h *shadowHandler) getRequest(conn net.Conn) (host string, err error) {
case
typeIPv6
:
case
typeIPv6
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
case
typeDm
:
case
typeDm
:
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
if
_
,
err
=
io
.
ReadFull
(
r
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
return
return
}
}
reqStart
,
reqEnd
=
idDm0
,
i
nt
(
idDm0
+
buf
[
idDmLen
]
+
lenDmBase
)
reqStart
,
reqEnd
=
idDm0
,
i
dDm0
+
int
(
buf
[
idDmLen
])
+
lenDmBase
default
:
default
:
err
=
fmt
.
Errorf
(
"addr type %d not supported"
,
addrType
&
ss
.
AddrMask
)
err
=
fmt
.
Errorf
(
"addr type %d not supported"
,
addrType
&
ss
.
AddrMask
)
return
return
}
}
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
if
_
,
err
=
io
.
ReadFull
(
r
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
return
return
}
}
...
@@ -209,7 +210,7 @@ func (h *shadowHandler) getRequest(conn net.Conn) (host string, err error) {
...
@@ -209,7 +210,7 @@ func (h *shadowHandler) getRequest(conn net.Conn) (host string, err error) {
case
typeIPv6
:
case
typeIPv6
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv6len
])
.
String
()
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv6len
])
.
String
()
case
typeDm
:
case
typeDm
:
host
=
string
(
buf
[
idDm0
:
idDm0
+
buf
[
idDmLen
]
])
host
=
string
(
buf
[
idDm0
:
idDm0
+
int
(
buf
[
idDmLen
])
])
}
}
// parse port
// parse port
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
...
...
ssh.go
View file @
b3068a7d
...
@@ -830,13 +830,13 @@ func (c *sshConn) RemoteAddr() net.Addr {
...
@@ -830,13 +830,13 @@ func (c *sshConn) RemoteAddr() net.Addr {
}
}
func
(
c
*
sshConn
)
SetDeadline
(
t
time
.
Time
)
error
{
func
(
c
*
sshConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"ssh"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
return
nil
}
}
func
(
c
*
sshConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
func
(
c
*
sshConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"ssh"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
return
nil
}
}
func
(
c
*
sshConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
func
(
c
*
sshConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
&
net
.
OpError
{
Op
:
"set"
,
Net
:
"ssh"
,
Source
:
nil
,
Addr
:
nil
,
Err
:
errors
.
New
(
"deadline not supported"
)}
return
nil
}
}
ws.go
View file @
b3068a7d
...
@@ -129,7 +129,7 @@ func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (n
...
@@ -129,7 +129,7 @@ func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (n
if
opts
.
WSOptions
!=
nil
{
if
opts
.
WSOptions
!=
nil
{
wsOptions
=
opts
.
WSOptions
wsOptions
=
opts
.
WSOptions
}
}
url
:=
url
.
URL
{
Scheme
:
"ws"
,
Host
:
opts
.
Addr
,
Path
:
"/ws"
}
url
:=
url
.
URL
{
Scheme
:
"ws"
,
Host
:
opts
.
Host
,
Path
:
"/ws"
}
return
websocketClientConn
(
url
.
String
(),
conn
,
nil
,
wsOptions
)
return
websocketClientConn
(
url
.
String
(),
conn
,
nil
,
wsOptions
)
}
}
...
@@ -210,7 +210,7 @@ func (tr *mwsTransporter) initSession(addr string, conn net.Conn, opts *Handshak
...
@@ -210,7 +210,7 @@ func (tr *mwsTransporter) initSession(addr string, conn net.Conn, opts *Handshak
if
opts
.
WSOptions
!=
nil
{
if
opts
.
WSOptions
!=
nil
{
wsOptions
=
opts
.
WSOptions
wsOptions
=
opts
.
WSOptions
}
}
url
:=
url
.
URL
{
Scheme
:
"ws"
,
Host
:
opts
.
Addr
,
Path
:
"/ws"
}
url
:=
url
.
URL
{
Scheme
:
"ws"
,
Host
:
opts
.
Host
,
Path
:
"/ws"
}
conn
,
err
:=
websocketClientConn
(
url
.
String
(),
conn
,
nil
,
wsOptions
)
conn
,
err
:=
websocketClientConn
(
url
.
String
(),
conn
,
nil
,
wsOptions
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -252,7 +252,7 @@ func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
...
@@ -252,7 +252,7 @@ func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
if
opts
.
TLSConfig
==
nil
{
if
opts
.
TLSConfig
==
nil
{
opts
.
TLSConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
opts
.
TLSConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
}
}
url
:=
url
.
URL
{
Scheme
:
"wss"
,
Host
:
opts
.
Addr
,
Path
:
"/ws"
}
url
:=
url
.
URL
{
Scheme
:
"wss"
,
Host
:
opts
.
Host
,
Path
:
"/ws"
}
return
websocketClientConn
(
url
.
String
(),
conn
,
opts
.
TLSConfig
,
wsOptions
)
return
websocketClientConn
(
url
.
String
(),
conn
,
opts
.
TLSConfig
,
wsOptions
)
}
}
...
@@ -337,7 +337,7 @@ func (tr *mwssTransporter) initSession(addr string, conn net.Conn, opts *Handsha
...
@@ -337,7 +337,7 @@ func (tr *mwssTransporter) initSession(addr string, conn net.Conn, opts *Handsha
if
tlsConfig
==
nil
{
if
tlsConfig
==
nil
{
tlsConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
tlsConfig
=
&
tls
.
Config
{
InsecureSkipVerify
:
true
}
}
}
url
:=
url
.
URL
{
Scheme
:
"wss"
,
Host
:
opts
.
Addr
,
Path
:
"/ws"
}
url
:=
url
.
URL
{
Scheme
:
"wss"
,
Host
:
opts
.
Host
,
Path
:
"/ws"
}
conn
,
err
:=
websocketClientConn
(
url
.
String
(),
conn
,
tlsConfig
,
wsOptions
)
conn
,
err
:=
websocketClientConn
(
url
.
String
(),
conn
,
tlsConfig
,
wsOptions
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
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