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
dc4c78ca
Commit
dc4c78ca
authored
Nov 29, 2018
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add stop for live reloading
parent
5e0e08d5
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
337 additions
and
203 deletions
+337
-203
bypass.go
bypass.go
+30
-1
chain.go
chain.go
+4
-1
cmd/gost/cfg.go
cmd/gost/cfg.go
+41
-68
cmd/gost/gost.json
cmd/gost/gost.json
+0
-30
cmd/gost/main.go
cmd/gost/main.go
+15
-4
cmd/gost/peer.go
cmd/gost/peer.go
+33
-31
cmd/gost/route.go
cmd/gost/route.go
+72
-26
hosts.go
hosts.go
+33
-4
http.go
http.go
+1
-1
http2.go
http2.go
+4
-2
node.go
node.go
+11
-6
node_test.go
node_test.go
+1
-1
reload.go
reload.go
+39
-11
resolver.go
resolver.go
+32
-1
selector.go
selector.go
+14
-0
server.go
server.go
+0
-10
ss.go
ss.go
+3
-2
ws.go
ws.go
+4
-4
No files found.
bypass.go
View file @
dc4c78ca
...
...
@@ -124,6 +124,7 @@ type Bypass struct {
matchers
[]
Matcher
period
time
.
Duration
// the period for live reloading
reversed
bool
stopped
chan
struct
{}
mux
sync
.
RWMutex
}
...
...
@@ -133,6 +134,7 @@ func NewBypass(reversed bool, matchers ...Matcher) *Bypass {
return
&
Bypass
{
matchers
:
matchers
,
reversed
:
reversed
,
stopped
:
make
(
chan
struct
{}),
}
}
...
...
@@ -207,6 +209,10 @@ func (bp *Bypass) Reload(r io.Reader) error {
var
period
time
.
Duration
var
reversed
bool
if
bp
.
Stopped
()
{
return
nil
}
scanner
:=
bufio
.
NewScanner
(
r
)
for
scanner
.
Scan
()
{
line
:=
scanner
.
Text
()
...
...
@@ -264,14 +270,37 @@ func (bp *Bypass) Reload(r io.Reader) error {
return
nil
}
// Period returns the reload period
// Period returns the reload period
.
func
(
bp
*
Bypass
)
Period
()
time
.
Duration
{
if
bp
.
Stopped
()
{
return
-
1
}
bp
.
mux
.
RLock
()
defer
bp
.
mux
.
RUnlock
()
return
bp
.
period
}
// Stop stops reloading.
func
(
bp
*
Bypass
)
Stop
()
{
select
{
case
<-
bp
.
stopped
:
default
:
close
(
bp
.
stopped
)
}
}
// Stopped checks whether the reloader is stopped.
func
(
bp
*
Bypass
)
Stopped
()
bool
{
select
{
case
<-
bp
.
stopped
:
return
true
default
:
return
false
}
}
func
(
bp
*
Bypass
)
String
()
string
{
bp
.
mux
.
RLock
()
defer
bp
.
mux
.
RUnlock
()
...
...
chain.go
View file @
dc4c78ca
...
...
@@ -15,7 +15,7 @@ var (
ErrEmptyChain
=
errors
.
New
(
"empty chain"
)
)
// Chain is a proxy chain that holds a list of proxy nodes.
// Chain is a proxy chain that holds a list of proxy node
group
s.
type
Chain
struct
{
isRoute
bool
Retries
int
...
...
@@ -23,6 +23,7 @@ type Chain struct {
}
// NewChain creates a proxy chain with a list of proxy nodes.
// It creates the node groups automatically, one group per node.
func
NewChain
(
nodes
...
Node
)
*
Chain
{
chain
:=
&
Chain
{}
for
_
,
node
:=
range
nodes
{
...
...
@@ -31,6 +32,8 @@ func NewChain(nodes ...Node) *Chain {
return
chain
}
// newRoute creates a chain route.
// a chain route is the final route after node selection.
func
newRoute
(
nodes
...
Node
)
*
Chain
{
chain
:=
NewChain
(
nodes
...
)
chain
.
isRoute
=
true
...
...
cmd/gost/cfg.go
View file @
dc4c78ca
...
...
@@ -6,8 +6,6 @@ import (
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
...
...
@@ -17,6 +15,34 @@ import (
"github.com/ginuerzh/gost"
)
var
(
routers
[]
router
)
type
baseConfig
struct
{
route
Routes
[]
route
Debug
bool
}
func
parseBaseConfig
(
s
string
)
(
*
baseConfig
,
error
)
{
file
,
err
:=
os
.
Open
(
s
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
if
err
:=
json
.
NewDecoder
(
file
)
.
Decode
(
baseCfg
);
err
!=
nil
{
return
nil
,
err
}
return
baseCfg
,
nil
}
func
(
cfg
*
baseConfig
)
IsValid
()
bool
{
return
len
(
cfg
.
route
.
ServeNodes
)
>
0
}
var
(
defaultCertFile
=
"cert.pem"
defaultKeyFile
=
"key.pem"
...
...
@@ -52,70 +78,6 @@ func loadCA(caFile string) (cp *x509.CertPool, err error) {
return
}
type
baseConfig
struct
{
route
Routes
[]
route
ReloadPeriod
string
Debug
bool
}
func
parseBaseConfig
(
s
string
)
(
*
baseConfig
,
error
)
{
file
,
err
:=
os
.
Open
(
s
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
if
err
:=
json
.
NewDecoder
(
file
)
.
Decode
(
baseCfg
);
err
!=
nil
{
return
nil
,
err
}
return
baseCfg
,
nil
}
func
(
cfg
*
baseConfig
)
IsValid
()
bool
{
return
len
(
cfg
.
route
.
ServeNodes
)
>
0
}
func
(
cfg
*
baseConfig
)
Reload
(
r
io
.
Reader
)
error
{
c
:=
baseConfig
{}
if
err
:=
json
.
NewDecoder
(
r
)
.
Decode
(
&
c
);
err
!=
nil
{
return
err
}
cfg
.
route
.
Close
()
for
_
,
r
:=
range
cfg
.
Routes
{
r
.
Close
()
}
*
cfg
=
c
gost
.
Debug
=
cfg
.
Debug
if
err
:=
cfg
.
route
.
serve
();
err
!=
nil
{
return
err
}
for
_
,
route
:=
range
cfg
.
Routes
{
if
err
:=
route
.
serve
();
err
!=
nil
{
return
err
}
}
return
nil
}
func
(
cfg
*
baseConfig
)
Period
()
time
.
Duration
{
d
,
_
:=
time
.
ParseDuration
(
cfg
.
ReloadPeriod
)
return
d
}
type
stringList
[]
string
func
(
l
*
stringList
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s"
,
*
l
)
}
func
(
l
*
stringList
)
Set
(
value
string
)
error
{
*
l
=
append
(
*
l
,
value
)
return
nil
}
func
parseKCPConfig
(
configFile
string
)
(
*
gost
.
KCPConfig
,
error
)
{
if
configFile
==
""
{
return
nil
,
nil
...
...
@@ -221,9 +183,10 @@ func parseBypass(s string) *gost.Bypass {
}
return
gost
.
NewBypass
(
reversed
,
matchers
...
)
}
f
.
Close
()
defer
f
.
Close
()
bp
:=
gost
.
NewBypass
(
reversed
)
bp
.
Reload
(
f
)
go
gost
.
PeriodReload
(
bp
,
s
)
return
bp
...
...
@@ -259,16 +222,26 @@ func parseResolver(cfg string) gost.Resolver {
}
return
gost
.
NewResolver
(
timeout
,
ttl
,
nss
...
)
}
f
.
Close
()
defer
f
.
Close
()
resolver
:=
gost
.
NewResolver
(
timeout
,
ttl
)
resolver
.
Reload
(
f
)
go
gost
.
PeriodReload
(
resolver
,
cfg
)
return
resolver
}
func
parseHosts
(
s
string
)
*
gost
.
Hosts
{
f
,
err
:=
os
.
Open
(
s
)
if
err
!=
nil
{
return
nil
}
defer
f
.
Close
()
hosts
:=
gost
.
NewHosts
()
hosts
.
Reload
(
f
)
go
gost
.
PeriodReload
(
hosts
,
s
)
return
hosts
...
...
cmd/gost/gost.json
deleted
100644 → 0
View file @
5e0e08d5
{
"Debug"
:
false
,
"Retries"
:
1
,
"ServeNodes"
:
[
":8080"
,
"ss://chacha20:12345678@:8338"
],
"ChainNodes"
:
[
"http://192.168.1.1:8080"
,
"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 @
dc4c78ca
...
...
@@ -71,7 +71,10 @@ func main() {
}
gost
.
DefaultTLSConfig
=
tlsConfig
start
()
if
err
:=
start
();
err
!=
nil
{
log
.
Log
(
err
)
os
.
Exit
(
1
)
}
select
{}
}
...
...
@@ -79,16 +82,24 @@ func main() {
func
start
()
error
{
gost
.
Debug
=
baseCfg
.
Debug
if
err
:=
baseCfg
.
route
.
serve
();
err
!=
nil
{
var
routers
[]
router
rts
,
err
:=
baseCfg
.
route
.
GenRouters
()
if
err
!=
nil
{
return
err
}
routers
=
append
(
routers
,
rts
...
)
for
_
,
route
:=
range
baseCfg
.
Routes
{
if
err
:=
route
.
serve
();
err
!=
nil
{
rts
,
err
:=
route
.
GenRouters
()
if
err
!=
nil
{
return
err
}
routers
=
append
(
routers
,
rts
...
)
}
go
gost
.
PeriodReload
(
baseCfg
,
configureFile
)
for
i
:=
range
routers
{
go
routers
[
i
]
.
Serve
()
}
return
nil
}
cmd/gost/peer.go
View file @
dc4c78ca
...
...
@@ -26,20 +26,13 @@ type peerConfig struct {
Nodes
[]
string
`json:"nodes"`
group
*
gost
.
NodeGroup
baseNodes
[]
gost
.
Node
stopped
chan
struct
{}
}
type
bypass
struct
{
Reverse
bool
`json:"reverse"`
Patterns
[]
string
`json:"patterns"`
}
func
parsePeerConfig
(
cfg
string
,
group
*
gost
.
NodeGroup
,
baseNodes
[]
gost
.
Node
)
*
peerConfig
{
pc
:=
&
peerConfig
{
group
:
group
,
baseNodes
:
baseNodes
,
func
newPeerConfig
()
*
peerConfig
{
return
&
peerConfig
{
stopped
:
make
(
chan
struct
{}),
}
go
gost
.
PeriodReload
(
pc
,
cfg
)
return
pc
}
func
(
cfg
*
peerConfig
)
Validate
()
{
...
...
@@ -52,28 +45,23 @@ func (cfg *peerConfig) Validate() {
}
func
(
cfg
*
peerConfig
)
Reload
(
r
io
.
Reader
)
error
{
if
cfg
.
Stopped
()
{
return
nil
}
if
err
:=
cfg
.
parse
(
r
);
err
!=
nil
{
return
err
}
cfg
.
Validate
()
group
:=
cfg
.
group
/*
strategy := cfg.Strategy
if len(cfg.baseNodes) > 0 {
// overwrite the strategry in the peer config if `strategy` param exists.
if s := cfg.baseNodes[0].Get("strategy"); s != "" {
strategy = s
}
}
*/
group
.
SetSelector
(
nil
,
gost
.
WithFilter
(
&
gost
.
FailFilter
{
MaxFails
:
cfg
.
MaxFails
,
FailTimeout
:
cfg
.
FailTimeout
,
}),
gost
.
WithStrategy
(
parse
Strategy
(
cfg
.
Strategy
)),
gost
.
WithStrategy
(
gost
.
New
Strategy
(
cfg
.
Strategy
)),
)
gNodes
:=
cfg
.
baseNodes
...
...
@@ -92,7 +80,12 @@ func (cfg *peerConfig) Reload(r io.Reader) error {
gNodes
=
append
(
gNodes
,
nodes
...
)
}
group
.
SetNodes
(
gNodes
...
)
nodes
:=
group
.
SetNodes
(
gNodes
...
)
for
_
,
node
:=
range
nodes
[
len
(
cfg
.
baseNodes
)
:
]
{
if
node
.
Bypass
!=
nil
{
node
.
Bypass
.
Stop
()
// clear the old nodes
}
}
return
nil
}
...
...
@@ -154,18 +147,27 @@ func (cfg *peerConfig) parse(r io.Reader) error {
}
func
(
cfg
*
peerConfig
)
Period
()
time
.
Duration
{
if
cfg
.
Stopped
()
{
return
-
1
}
return
cfg
.
period
}
func
parseStrategy
(
s
string
)
gost
.
Strategy
{
switch
s
{
case
"random"
:
return
&
gost
.
RandomStrategy
{}
case
"fifo"
:
return
&
gost
.
FIFOStrategy
{}
case
"round"
:
fallthrough
// Stop stops reloading.
func
(
cfg
*
peerConfig
)
Stop
()
{
select
{
case
<-
cfg
.
stopped
:
default
:
close
(
cfg
.
stopped
)
}
}
// Stopped checks whether the reloader is stopped.
func
(
cfg
*
peerConfig
)
Stopped
()
bool
{
select
{
case
<-
cfg
.
stopped
:
return
true
default
:
return
&
gost
.
RoundStrategy
{}
return
false
}
}
cmd/gost/route.go
View file @
dc4c78ca
...
...
@@ -3,20 +3,32 @@ package main
import
(
"crypto/sha256"
"crypto/tls"
"fmt"
"net"
"os"
"time"
"github.com/ginuerzh/gost"
"github.com/go-log/log"
)
type
stringList
[]
string
func
(
l
*
stringList
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s"
,
*
l
)
}
func
(
l
*
stringList
)
Set
(
value
string
)
error
{
*
l
=
append
(
*
l
,
value
)
return
nil
}
type
route
struct
{
ServeNodes
stringList
ChainNodes
stringList
Retries
int
server
*
gost
.
Server
}
func
(
r
*
route
)
init
Chain
()
(
*
gost
.
Chain
,
error
)
{
func
(
r
*
route
)
parse
Chain
()
(
*
gost
.
Chain
,
error
)
{
chain
:=
gost
.
NewChain
()
chain
.
Retries
=
r
.
Retries
gid
:=
1
// group ID
...
...
@@ -44,13 +56,20 @@ func (r *route) initChain() (*gost.Chain, error) {
MaxFails
:
defaultMaxFails
,
FailTimeout
:
defaultFailTimeout
,
}),
gost
.
WithStrategy
(
parse
Strategy
(
nodes
[
0
]
.
Get
(
"strategy"
))),
gost
.
WithStrategy
(
gost
.
New
Strategy
(
nodes
[
0
]
.
Get
(
"strategy"
))),
)
go
gost
.
PeriodReload
(
&
peerConfig
{
group
:
ngroup
,
baseNodes
:
nodes
,
},
nodes
[
0
]
.
Get
(
"peer"
))
cfg
:=
nodes
[
0
]
.
Get
(
"peer"
)
f
,
err
:=
os
.
Open
(
cfg
)
if
err
==
nil
{
peerCfg
:=
newPeerConfig
()
peerCfg
.
group
=
ngroup
peerCfg
.
baseNodes
=
nodes
peerCfg
.
Reload
(
f
)
f
.
Close
()
go
gost
.
PeriodReload
(
peerCfg
,
cfg
)
}
chain
.
AddNodeGroup
(
ngroup
)
}
...
...
@@ -219,20 +238,22 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
return
}
func
(
r
*
route
)
serve
()
error
{
chain
,
err
:=
r
.
init
Chain
()
func
(
r
*
route
)
GenRouters
()
([]
router
,
error
)
{
chain
,
err
:=
r
.
parse
Chain
()
if
err
!=
nil
{
return
err
return
nil
,
err
}
var
rts
[]
router
for
_
,
ns
:=
range
r
.
ServeNodes
{
node
,
err
:=
gost
.
ParseNode
(
ns
)
if
err
!=
nil
{
return
err
return
nil
,
err
}
users
,
err
:=
parseUsers
(
node
.
Get
(
"secrets"
))
if
err
!=
nil
{
return
err
return
nil
,
err
}
if
node
.
User
!=
nil
{
users
=
append
(
users
,
node
.
User
)
...
...
@@ -240,7 +261,7 @@ func (r *route) serve() error {
certFile
,
keyFile
:=
node
.
Get
(
"cert"
),
node
.
Get
(
"key"
)
tlsCfg
,
err
:=
tlsConfig
(
certFile
,
keyFile
)
if
err
!=
nil
&&
certFile
!=
""
&&
keyFile
!=
""
{
return
err
return
nil
,
err
}
wsOpts
:=
&
gost
.
WSOptions
{}
...
...
@@ -266,7 +287,7 @@ func (r *route) serve() error {
case
"kcp"
:
config
,
er
:=
parseKCPConfig
(
node
.
Get
(
"c"
))
if
er
!=
nil
{
return
er
return
nil
,
er
}
ln
,
err
=
gost
.
KCPListener
(
node
.
Addr
,
config
)
case
"ssh"
:
...
...
@@ -320,7 +341,7 @@ func (r *route) serve() error {
ln
,
err
=
gost
.
ShadowUDPListener
(
node
.
Addr
,
node
.
User
,
time
.
Duration
(
node
.
GetInt
(
"ttl"
))
*
time
.
Second
)
case
"obfs4"
:
if
err
=
gost
.
Obfs4Init
(
node
,
true
);
err
!=
nil
{
return
err
return
nil
,
err
}
ln
,
err
=
gost
.
Obfs4Listener
(
node
.
Addr
)
case
"ohttp"
:
...
...
@@ -329,7 +350,7 @@ func (r *route) serve() error {
ln
,
err
=
gost
.
TCPListener
(
node
.
Addr
)
}
if
err
!=
nil
{
return
err
return
nil
,
err
}
var
handler
gost
.
Handler
...
...
@@ -372,15 +393,19 @@ func (r *route) serve() error {
var
whitelist
,
blacklist
*
gost
.
Permissions
if
node
.
Values
.
Get
(
"whitelist"
)
!=
""
{
if
whitelist
,
err
=
gost
.
ParsePermissions
(
node
.
Get
(
"whitelist"
));
err
!=
nil
{
return
err
return
nil
,
err
}
}
if
node
.
Values
.
Get
(
"blacklist"
)
!=
""
{
if
blacklist
,
err
=
gost
.
ParsePermissions
(
node
.
Get
(
"blacklist"
));
err
!=
nil
{
return
err
return
nil
,
err
}
}
node
.
Bypass
=
parseBypass
(
node
.
Get
(
"bypass"
))
resolver
:=
parseResolver
(
node
.
Get
(
"dns"
))
hosts
:=
parseHosts
(
node
.
Get
(
"hosts"
))
handler
.
Init
(
gost
.
AddrHandlerOption
(
node
.
Addr
),
gost
.
ChainHandlerOption
(
chain
),
...
...
@@ -388,23 +413,44 @@ func (r *route) serve() error {
gost
.
TLSConfigHandlerOption
(
tlsCfg
),
gost
.
WhitelistHandlerOption
(
whitelist
),
gost
.
BlacklistHandlerOption
(
blacklist
),
gost
.
StrategyHandlerOption
(
parse
Strategy
(
node
.
Get
(
"strategy"
))),
gost
.
BypassHandlerOption
(
parseBypass
(
node
.
Get
(
"bypass"
))
),
gost
.
ResolverHandlerOption
(
parseResolver
(
node
.
Get
(
"dns"
))
),
gost
.
HostsHandlerOption
(
parseHosts
(
node
.
Get
(
"hosts"
))
),
gost
.
StrategyHandlerOption
(
gost
.
New
Strategy
(
node
.
Get
(
"strategy"
))),
gost
.
BypassHandlerOption
(
node
.
Bypass
),
gost
.
ResolverHandlerOption
(
resolver
),
gost
.
HostsHandlerOption
(
hosts
),
gost
.
RetryHandlerOption
(
node
.
GetInt
(
"retry"
)),
gost
.
TimeoutHandlerOption
(
time
.
Duration
(
node
.
GetInt
(
"timeout"
))
*
time
.
Second
),
gost
.
ProbeResistHandlerOption
(
node
.
Get
(
"probe_resist"
)),
)
r
.
server
=
&
gost
.
Server
{
Listener
:
ln
}
go
r
.
server
.
Serve
(
handler
)
rt
:=
router
{
node
:
node
,
server
:
&
gost
.
Server
{
Listener
:
ln
},
handler
:
handler
,
chain
:
chain
,
resolver
:
resolver
,
hosts
:
hosts
,
}
rts
=
append
(
rts
,
rt
)
}
return
nil
return
rts
,
nil
}
type
router
struct
{
node
gost
.
Node
server
*
gost
.
Server
handler
gost
.
Handler
chain
*
gost
.
Chain
resolver
gost
.
Resolver
hosts
*
gost
.
Hosts
}
func
(
r
*
router
)
Serve
()
error
{
log
.
Logf
(
"[route] start %s on %s"
,
r
.
node
.
String
(),
r
.
server
.
Addr
())
return
r
.
server
.
Serve
(
r
.
handler
)
}
func
(
r
*
route
)
Close
()
error
{
func
(
r
*
route
r
)
Close
()
error
{
if
r
==
nil
||
r
.
server
==
nil
{
return
nil
}
...
...
hosts.go
View file @
dc4c78ca
...
...
@@ -24,15 +24,17 @@ type Host struct {
// Fields of the entry are separated by any number of blanks and/or tab characters.
// Text from a "#" character until the end of the line is a comment, and is ignored.
type
Hosts
struct
{
hosts
[]
Host
period
time
.
Duration
mux
sync
.
RWMutex
hosts
[]
Host
period
time
.
Duration
stopped
chan
struct
{}
mux
sync
.
RWMutex
}
// NewHosts creates a Hosts with optional list of host
func
NewHosts
(
hosts
...
Host
)
*
Hosts
{
return
&
Hosts
{
hosts
:
hosts
,
hosts
:
hosts
,
stopped
:
make
(
chan
struct
{}),
}
}
...
...
@@ -76,6 +78,10 @@ func (h *Hosts) Reload(r io.Reader) error {
var
period
time
.
Duration
var
hosts
[]
Host
if
h
.
Stopped
()
{
return
nil
}
scanner
:=
bufio
.
NewScanner
(
r
)
for
scanner
.
Scan
()
{
line
:=
scanner
.
Text
()
...
...
@@ -130,8 +136,31 @@ func (h *Hosts) Reload(r io.Reader) error {
// Period returns the reload period
func
(
h
*
Hosts
)
Period
()
time
.
Duration
{
if
h
.
Stopped
()
{
return
-
1
}
h
.
mux
.
RLock
()
defer
h
.
mux
.
RUnlock
()
return
h
.
period
}
// Stop stops reloading.
func
(
h
*
Hosts
)
Stop
()
{
select
{
case
<-
h
.
stopped
:
default
:
close
(
h
.
stopped
)
}
}
// Stopped checks whether the reloader is stopped.
func
(
h
*
Hosts
)
Stopped
()
bool
{
select
{
case
<-
h
.
stopped
:
return
true
default
:
return
false
}
}
http.go
View file @
dc4c78ca
...
...
@@ -263,7 +263,7 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
if
err
==
nil
{
return
}
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
err
)
//
log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
continue
}
...
...
http2.go
View file @
dc4c78ca
...
...
@@ -468,6 +468,7 @@ func (h *http2Handler) writeResponse(w http.ResponseWriter, resp *http.Response)
type
http2Listener
struct
{
server
*
http
.
Server
connChan
chan
*
http2ServerConn
addr
net
.
Addr
errChan
chan
error
}
...
...
@@ -494,6 +495,8 @@ func HTTP2Listener(addr string, config *tls.Config) (Listener, error) {
if
err
!=
nil
{
return
nil
,
err
}
l
.
addr
=
ln
.
Addr
()
go
func
()
{
err
:=
server
.
Serve
(
ln
)
if
err
!=
nil
{
...
...
@@ -532,8 +535,7 @@ func (l *http2Listener) Accept() (conn net.Conn, err error) {
}
func
(
l
*
http2Listener
)
Addr
()
net
.
Addr
{
addr
,
_
:=
net
.
ResolveTCPAddr
(
"tcp"
,
l
.
server
.
Addr
)
return
addr
return
l
.
addr
}
func
(
l
*
http2Listener
)
Close
()
(
err
error
)
{
...
...
node.go
View file @
dc4c78ca
...
...
@@ -2,7 +2,6 @@ package gost
import
(
"errors"
"fmt"
"net/url"
"strconv"
"strings"
...
...
@@ -22,6 +21,7 @@ type Node struct {
Protocol
string
Transport
string
Remote
string
// remote address, used by tcp/udp port forwarding
url
string
// raw url
User
*
url
.
Userinfo
Values
url
.
Values
DialOptions
[]
DialOption
...
...
@@ -57,6 +57,9 @@ func ParseNode(s string) (node Node, err error) {
marker
:
&
failMarker
{},
}
u
.
RawQuery
=
""
node
.
url
=
u
.
String
()
schemes
:=
strings
.
Split
(
u
.
Scheme
,
"+"
)
if
len
(
schemes
)
==
1
{
node
.
Protocol
=
schemes
[
0
]
...
...
@@ -136,8 +139,7 @@ func (node *Node) GetInt(key string) int {
}
func
(
node
Node
)
String
()
string
{
return
fmt
.
Sprintf
(
"%d@%s+%s://%s"
,
node
.
ID
,
node
.
Protocol
,
node
.
Transport
,
node
.
Addr
)
return
node
.
url
}
// NodeGroup is a group of nodes.
...
...
@@ -167,16 +169,19 @@ func (group *NodeGroup) AddNode(node ...Node) {
group
.
nodes
=
append
(
group
.
nodes
,
node
...
)
}
// SetNodes replaces the group nodes to the specified nodes.
func
(
group
*
NodeGroup
)
SetNodes
(
nodes
...
Node
)
{
// SetNodes replaces the group nodes to the specified nodes,
// and returns the previous nodes.
func
(
group
*
NodeGroup
)
SetNodes
(
nodes
...
Node
)
[]
Node
{
if
group
==
nil
{
return
return
nil
}
group
.
mux
.
Lock
()
defer
group
.
mux
.
Unlock
()
old
:=
group
.
nodes
group
.
nodes
=
nodes
return
old
}
// SetSelector sets node selector with options for the group.
...
...
node_test.go
View file @
dc4c78ca
...
...
@@ -8,7 +8,7 @@ var nodeTests = []struct {
out
Node
hasError
bool
}{
{
""
,
Node
{},
fals
e
},
{
""
,
Node
{},
tru
e
},
{
"://"
,
Node
{},
true
},
{
"localhost"
,
Node
{
Addr
:
"localhost"
,
Transport
:
"tcp"
},
false
},
{
":"
,
Node
{
Addr
:
":"
,
Transport
:
"tcp"
},
false
},
...
...
reload.go
View file @
dc4c78ca
...
...
@@ -14,43 +14,71 @@ type Reloader interface {
Period
()
time
.
Duration
}
// PeriodReload reloads the config periodically according to the period of the reloader.
// Stoppable is the interface that indicates a Reloader can be stopped.
type
Stoppable
interface
{
Stop
()
}
//StopReloader is the interface that adds Stop method to the Reloader.
type
StopReloader
interface
{
Reloader
Stoppable
}
type
nopStoppable
struct
{
Reloader
}
func
(
nopStoppable
)
Stop
()
{
return
}
// NopStoppable returns a StopReloader with a no-op Stop method,
// wrapping the provided Reloader r.
func
NopStoppable
(
r
Reloader
)
StopReloader
{
return
nopStoppable
{
r
}
}
// PeriodReload reloads the config configFile periodically according to the period of the Reloader r.
func
PeriodReload
(
r
Reloader
,
configFile
string
)
error
{
if
configFile
==
""
{
if
r
==
nil
||
configFile
==
""
{
return
nil
}
var
lastMod
time
.
Time
for
{
if
r
.
Period
()
<
0
{
log
.
Log
(
"[reload] stopped:"
,
configFile
)
return
nil
}
f
,
err
:=
os
.
Open
(
configFile
)
if
err
!=
nil
{
return
err
}
finfo
,
err
:=
f
.
Stat
()
if
err
!=
nil
{
f
.
Close
()
return
err
mt
:=
lastMod
if
finfo
,
err
:=
f
.
Stat
();
err
==
nil
{
mt
=
finfo
.
ModTime
()
}
mt
:=
finfo
.
ModTime
()
if
!
mt
.
Equal
(
lastMod
)
{
if
!
lastMod
.
IsZero
()
&&
!
mt
.
Equal
(
lastMod
)
{
log
.
Log
(
"[reload]"
,
configFile
)
if
err
:=
r
.
Reload
(
f
);
err
!=
nil
{
log
.
Logf
(
"[reload] %s: %s"
,
configFile
,
err
)
}
lastMod
=
mt
}
f
.
Close
()
lastMod
=
mt
period
:=
r
.
Period
()
if
period
<
=
0
{
if
period
=
=
0
{
log
.
Log
(
"[reload] disabled:"
,
configFile
)
return
nil
}
if
period
<
time
.
Second
{
period
=
time
.
Second
}
<-
time
.
After
(
period
)
}
}
resolver.go
View file @
dc4c78ca
...
...
@@ -29,10 +29,11 @@ type Resolver interface {
Resolve
(
host
string
)
([]
net
.
IP
,
error
)
}
// ReloadResolver is resolover that support live reloading
// ReloadResolver is resolover that support live reloading
.
type
ReloadResolver
interface
{
Resolver
Reloader
Stoppable
}
// NameServer is a name server.
...
...
@@ -68,6 +69,7 @@ type resolver struct {
TTL
time
.
Duration
period
time
.
Duration
domain
string
stopped
chan
struct
{}
mux
sync
.
RWMutex
}
...
...
@@ -78,6 +80,7 @@ func NewResolver(timeout, ttl time.Duration, servers ...NameServer) ReloadResolv
Timeout
:
timeout
,
TTL
:
ttl
,
mCache
:
&
sync
.
Map
{},
stopped
:
make
(
chan
struct
{}),
}
if
r
.
Timeout
<=
0
{
...
...
@@ -110,6 +113,7 @@ func (r *resolver) Resolve(host string) (ips []net.IP, err error) {
r
.
mux
.
RLock
()
domain
=
r
.
domain
timeout
=
r
.
Timeout
ttl
=
r
.
TTL
servers
=
r
.
copyServers
()
r
.
mux
.
RUnlock
()
...
...
@@ -219,6 +223,10 @@ func (r *resolver) Reload(rd io.Reader) error {
var
domain
string
var
nss
[]
NameServer
if
r
.
Stopped
()
{
return
nil
}
split
:=
func
(
line
string
)
[]
string
{
if
line
==
""
{
return
nil
...
...
@@ -305,12 +313,35 @@ func (r *resolver) Reload(rd io.Reader) error {
}
func
(
r
*
resolver
)
Period
()
time
.
Duration
{
if
r
.
Stopped
()
{
return
-
1
}
r
.
mux
.
RLock
()
defer
r
.
mux
.
RUnlock
()
return
r
.
period
}
// Stop stops reloading.
func
(
r
*
resolver
)
Stop
()
{
select
{
case
<-
r
.
stopped
:
default
:
close
(
r
.
stopped
)
}
}
// Stopped checks whether the reloader is stopped.
func
(
r
*
resolver
)
Stopped
()
bool
{
select
{
case
<-
r
.
stopped
:
return
true
default
:
return
false
}
}
func
(
r
*
resolver
)
String
()
string
{
if
r
==
nil
{
return
""
...
...
selector.go
View file @
dc4c78ca
...
...
@@ -68,6 +68,20 @@ type Strategy interface {
String
()
string
}
// NewStrategy creates a Strategy by the name s.
func
NewStrategy
(
s
string
)
Strategy
{
switch
s
{
case
"random"
:
return
&
RandomStrategy
{}
case
"fifo"
:
return
&
FIFOStrategy
{}
case
"round"
:
fallthrough
default
:
return
&
RoundStrategy
{}
}
}
// RoundStrategy is a strategy for node selector.
// The node will be selected by round-robin algorithm.
type
RoundStrategy
struct
{
...
...
server.go
View file @
dc4c78ca
...
...
@@ -86,21 +86,11 @@ func (s *Server) Serve(h Handler, opts ...ServerOption) error {
// ServerOptions holds the options for Server.
type
ServerOptions
struct
{
Bypass
*
Bypass
}
// ServerOption allows a common way to set server options.
type
ServerOption
func
(
opts
*
ServerOptions
)
/*
// BypassServerOption sets the bypass option of ServerOptions.
func BypassServerOption(bypass *Bypass) ServerOption {
return func(opts *ServerOptions) {
opts.Bypass = bypass
}
}
*/
// Listener is a proxy server listener, just like a net.Listener.
type
Listener
interface
{
net
.
Listener
...
...
ss.go
View file @
dc4c78ca
...
...
@@ -84,8 +84,9 @@ func (c *shadowConnector) Connect(conn net.Conn, addr string, options ...Connect
return
nil
,
err
}
sc
,
err
:=
ss
.
DialWithRawAddrConn
(
rawaddr
,
conn
,
cipher
)
if
err
!=
nil
{
sc
:=
ss
.
NewConn
(
conn
,
cipher
)
// sc, err := ss.DialWithRawAddrConn(rawaddr, conn, cipher)
if
_
,
err
:=
sc
.
Write
(
rawaddr
);
err
!=
nil
{
return
nil
,
err
}
return
&
shadowConn
{
conn
:
sc
},
nil
...
...
ws.go
View file @
dc4c78ca
...
...
@@ -384,7 +384,6 @@ func WSListener(addr string, options *WSOptions) (Listener, error) {
options
=
&
WSOptions
{}
}
l
:=
&
wsListener
{
addr
:
tcpAddr
,
upgrader
:
&
websocket
.
Upgrader
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
...
...
@@ -403,6 +402,7 @@ func WSListener(addr string, options *WSOptions) (Listener, error) {
if
err
!=
nil
{
return
nil
,
err
}
l
.
addr
=
ln
.
Addr
()
go
func
()
{
err
:=
l
.
srv
.
Serve
(
tcpKeepAliveListener
{
ln
})
...
...
@@ -473,7 +473,6 @@ func MWSListener(addr string, options *WSOptions) (Listener, error) {
options
=
&
WSOptions
{}
}
l
:=
&
mwsListener
{
addr
:
tcpAddr
,
upgrader
:
&
websocket
.
Upgrader
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
...
...
@@ -492,6 +491,7 @@ func MWSListener(addr string, options *WSOptions) (Listener, error) {
if
err
!=
nil
{
return
nil
,
err
}
l
.
addr
=
ln
.
Addr
()
go
func
()
{
err
:=
l
.
srv
.
Serve
(
tcpKeepAliveListener
{
ln
})
...
...
@@ -584,7 +584,6 @@ func WSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Listen
}
l
:=
&
wssListener
{
wsListener
:
&
wsListener
{
addr
:
tcpAddr
,
upgrader
:
&
websocket
.
Upgrader
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
...
...
@@ -612,6 +611,7 @@ func WSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Listen
if
err
!=
nil
{
return
nil
,
err
}
l
.
addr
=
ln
.
Addr
()
go
func
()
{
err
:=
l
.
srv
.
Serve
(
tls
.
NewListener
(
tcpKeepAliveListener
{
ln
},
tlsConfig
))
...
...
@@ -644,7 +644,6 @@ func MWSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Liste
}
l
:=
&
mwssListener
{
mwsListener
:
&
mwsListener
{
addr
:
tcpAddr
,
upgrader
:
&
websocket
.
Upgrader
{
ReadBufferSize
:
options
.
ReadBufferSize
,
WriteBufferSize
:
options
.
WriteBufferSize
,
...
...
@@ -672,6 +671,7 @@ func MWSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Liste
if
err
!=
nil
{
return
nil
,
err
}
l
.
addr
=
ln
.
Addr
()
go
func
()
{
err
:=
l
.
srv
.
Serve
(
tls
.
NewListener
(
tcpKeepAliveListener
{
ln
},
tlsConfig
))
...
...
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