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
d39e211f
Commit
d39e211f
authored
Apr 28, 2018
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add bypass support for proxy chain
parent
f6e09eaa
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
127 additions
and
30 deletions
+127
-30
chain.go
chain.go
+54
-7
cmd/gost/bypass.txt
cmd/gost/bypass.txt
+5
-0
cmd/gost/main.go
cmd/gost/main.go
+45
-14
cmd/gost/peer.json
cmd/gost/peer.json
+9
-1
http.go
http.go
+12
-7
node.go
node.go
+1
-0
socks.go
socks.go
+1
-1
No files found.
chain.go
View file @
d39e211f
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"errors"
"errors"
"fmt"
"fmt"
"net"
"net"
"strings"
"github.com/go-log/log"
"github.com/go-log/log"
)
)
...
@@ -100,11 +101,7 @@ func (c *Chain) IsEmpty() bool {
...
@@ -100,11 +101,7 @@ 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
)
(
conn
net
.
Conn
,
err
error
)
{
func
(
c
*
Chain
)
Dial
(
addr
string
)
(
conn
net
.
Conn
,
err
error
)
{
if
c
.
IsEmpty
()
{
for
i
:=
0
;
i
<
c
.
Retries
;
i
++
{
return
net
.
DialTimeout
(
"tcp"
,
addr
,
DialTimeout
)
}
for
i
:=
0
;
i
<
c
.
Retries
+
1
;
i
++
{
conn
,
err
=
c
.
dial
(
addr
)
conn
,
err
=
c
.
dial
(
addr
)
if
err
==
nil
{
if
err
==
nil
{
break
break
...
@@ -114,10 +111,13 @@ func (c *Chain) Dial(addr string) (conn net.Conn, err error) {
...
@@ -114,10 +111,13 @@ func (c *Chain) Dial(addr string) (conn net.Conn, err error) {
}
}
func
(
c
*
Chain
)
dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
func
(
c
*
Chain
)
dial
(
addr
string
)
(
net
.
Conn
,
error
)
{
route
,
err
:=
c
.
selectRoute
(
)
route
,
err
:=
c
.
selectRoute
For
(
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
route
.
IsEmpty
()
{
return
net
.
DialTimeout
(
"tcp"
,
addr
,
DialTimeout
)
}
conn
,
err
:=
route
.
getConn
()
conn
,
err
:=
route
.
getConn
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -135,7 +135,7 @@ func (c *Chain) dial(addr string) (net.Conn, error) {
...
@@ -135,7 +135,7 @@ 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
)
{
for
i
:=
0
;
i
<
c
.
Retries
+
1
;
i
++
{
for
i
:=
0
;
i
<
c
.
Retries
;
i
++
{
var
route
*
Chain
var
route
*
Chain
route
,
err
=
c
.
selectRoute
()
route
,
err
=
c
.
selectRoute
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -228,3 +228,50 @@ func (c *Chain) selectRoute() (route *Chain, err error) {
...
@@ -228,3 +228,50 @@ func (c *Chain) selectRoute() (route *Chain, err error) {
}
}
return
return
}
}
// selectRouteFor selects route with bypass testing.
func
(
c
*
Chain
)
selectRouteFor
(
addr
string
)
(
route
*
Chain
,
err
error
)
{
if
c
.
IsEmpty
()
||
c
.
isRoute
{
return
c
,
nil
}
buf
:=
bytes
.
Buffer
{}
route
=
newRoute
()
route
.
Retries
=
c
.
Retries
for
_
,
group
:=
range
c
.
nodeGroups
{
var
node
Node
node
,
err
=
group
.
Next
()
if
err
!=
nil
{
return
}
// NOTE: IPv6 will not work.
if
strings
.
Contains
(
addr
,
":"
)
{
addr
=
strings
.
Split
(
addr
,
":"
)[
0
]
}
if
node
.
Bypass
.
Contains
(
addr
)
{
if
Debug
{
buf
.
WriteString
(
fmt
.
Sprintf
(
"[%d@bypass: %s]"
,
node
.
ID
,
addr
))
log
.
Log
(
"select route:"
,
buf
.
String
())
}
return
}
buf
.
WriteString
(
fmt
.
Sprintf
(
"%s -> "
,
node
.
String
()))
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
())
}
return
}
cmd/gost/bypass.txt
0 → 100644
View file @
d39e211f
10.0.0.1
192.168.0.0/24
172.1.0.0/16
192.168.100.190/32
*.example.com
\ No newline at end of file
cmd/gost/main.go
View file @
d39e211f
...
@@ -92,7 +92,11 @@ type route struct {
...
@@ -92,7 +92,11 @@ type route struct {
func
(
r
*
route
)
initChain
()
(
*
gost
.
Chain
,
error
)
{
func
(
r
*
route
)
initChain
()
(
*
gost
.
Chain
,
error
)
{
chain
:=
gost
.
NewChain
()
chain
:=
gost
.
NewChain
()
chain
.
Retries
=
r
.
Retries
chain
.
Retries
=
r
.
Retries
if
chain
.
Retries
==
0
{
chain
.
Retries
=
1
}
gid
:=
1
// group ID
gid
:=
1
// group ID
...
@@ -143,6 +147,17 @@ func (r *route) initChain() (*gost.Chain, error) {
...
@@ -143,6 +147,17 @@ func (r *route) initChain() (*gost.Chain, error) {
ngroup
.
AddNode
(
nodes
...
)
ngroup
.
AddNode
(
nodes
...
)
}
}
var
bypass
*
gost
.
Bypass
if
peerCfg
.
Bypass
!=
nil
{
bypass
=
gost
.
NewBypassPatterns
(
peerCfg
.
Bypass
.
Patterns
,
peerCfg
.
Bypass
.
Reverse
)
}
nodes
=
ngroup
.
Nodes
()
for
i
:=
range
nodes
{
if
nodes
[
i
]
.
Bypass
==
nil
{
nodes
[
i
]
.
Bypass
=
bypass
// use global bypass if local bypass does not exist.
}
}
chain
.
AddNodeGroup
(
ngroup
)
chain
.
AddNodeGroup
(
ngroup
)
}
}
...
@@ -297,9 +312,12 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
...
@@ -297,9 +312,12 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
Transporter
:
tr
,
Transporter
:
tr
,
}
}
node
.
Bypass
=
parseBypass
(
node
.
Get
(
"bypass"
))
ips
:=
parseIP
(
node
.
Get
(
"ip"
),
sport
)
ips
:=
parseIP
(
node
.
Get
(
"ip"
),
sport
)
for
_
,
ip
:=
range
ips
{
for
_
,
ip
:=
range
ips
{
node
.
Addr
=
ip
node
.
Addr
=
ip
// override the default node address
node
.
HandshakeOptions
=
append
(
handshakeOptions
,
gost
.
AddrHandshakeOption
(
ip
))
node
.
HandshakeOptions
=
append
(
handshakeOptions
,
gost
.
AddrHandshakeOption
(
ip
))
nodes
=
append
(
nodes
,
node
)
nodes
=
append
(
nodes
,
node
)
}
}
...
@@ -484,14 +502,9 @@ func (r *route) serve() error {
...
@@ -484,14 +502,9 @@ func (r *route) serve() error {
}
}
}
}
fBypass
:=
node
.
Get
(
"bypass"
)
if
fBypass
==
""
{
fBypass
=
"bypass"
// default bypass file
}
srv
:=
&
gost
.
Server
{
Listener
:
ln
}
srv
:=
&
gost
.
Server
{
Listener
:
ln
}
srv
.
Init
(
srv
.
Init
(
gost
.
BypassServerOption
(
parseBypass
(
fBypass
)),
gost
.
BypassServerOption
(
parseBypass
(
node
.
Get
(
"bypass"
)
)),
)
)
go
srv
.
Serve
(
handler
)
go
srv
.
Serve
(
handler
)
}
}
...
@@ -657,6 +670,12 @@ type peerConfig struct {
...
@@ -657,6 +670,12 @@ type peerConfig struct {
MaxFails
int
`json:"max_fails"`
MaxFails
int
`json:"max_fails"`
FailTimeout
int
`json:"fail_timeout"`
FailTimeout
int
`json:"fail_timeout"`
Nodes
[]
string
`json:"nodes"`
Nodes
[]
string
`json:"nodes"`
Bypass
*
bypass
`json:"bypass"`
// global bypass
}
type
bypass
struct
{
Reverse
bool
`json:"reverse"`
Patterns
[]
string
`json:"patterns"`
}
}
func
loadPeerConfig
(
peer
string
)
(
config
peerConfig
,
err
error
)
{
func
loadPeerConfig
(
peer
string
)
(
config
peerConfig
,
err
error
)
{
...
@@ -694,16 +713,29 @@ func parseStrategy(s string) gost.Strategy {
...
@@ -694,16 +713,29 @@ func parseStrategy(s string) gost.Strategy {
}
}
}
}
func
parseBypass
(
fpath
string
)
(
bypass
*
gost
.
Bypass
)
{
func
parseBypass
(
s
string
)
*
gost
.
Bypass
{
if
fpath
==
""
{
if
s
==
""
{
return
return
nil
}
}
f
,
err
:=
os
.
Open
(
fpath
)
var
matchers
[]
gost
.
Matcher
var
reversed
bool
if
strings
.
HasPrefix
(
s
,
"~"
)
{
reversed
=
true
s
=
strings
.
TrimLeft
(
s
,
"~"
)
}
f
,
err
:=
os
.
Open
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
return
for
_
,
s
:=
range
strings
.
Split
(
s
,
","
)
{
s
=
strings
.
TrimSpace
(
s
)
if
s
==
""
{
continue
}
matchers
=
append
(
matchers
,
gost
.
NewMatcher
(
s
))
}
return
gost
.
NewBypass
(
matchers
,
reversed
)
}
}
var
matchers
[]
gost
.
Matcher
scanner
:=
bufio
.
NewScanner
(
f
)
scanner
:=
bufio
.
NewScanner
(
f
)
for
scanner
.
Scan
()
{
for
scanner
.
Scan
()
{
line
:=
scanner
.
Text
()
line
:=
scanner
.
Text
()
...
@@ -716,6 +748,5 @@ func parseBypass(fpath string) (bypass *gost.Bypass) {
...
@@ -716,6 +748,5 @@ func parseBypass(fpath string) (bypass *gost.Bypass) {
}
}
matchers
=
append
(
matchers
,
gost
.
NewMatcher
(
line
))
matchers
=
append
(
matchers
,
gost
.
NewMatcher
(
line
))
}
}
bypass
=
gost
.
NewBypass
(
matchers
,
strings
.
HasPrefix
(
fpath
,
"~"
))
return
gost
.
NewBypass
(
matchers
,
reversed
)
return
}
}
cmd/gost/peer.json
View file @
d39e211f
...
@@ -6,5 +6,13 @@
...
@@ -6,5 +6,13 @@
"socks5://:1081"
,
"socks5://:1081"
,
"socks://:1082"
,
"socks://:1082"
,
"socks4a://:1083"
"socks4a://:1083"
]
],
"bypass"
:{
"reverse"
:
false
,
"patterns"
:
[
"10.0.0.1"
,
"192.168.0.0/24"
,
"*.example.com"
]
}
}
}
\ No newline at end of file
http.go
View file @
d39e211f
...
@@ -150,10 +150,15 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
...
@@ -150,10 +150,15 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
}
}
}
}
route
,
err
:=
h
.
options
.
Chain
.
selectRouteFor
(
req
.
Host
)
if
err
!=
nil
{
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
req
.
Host
,
err
)
return
}
// forward http request
// forward http request
lastNode
:=
h
.
options
.
Chain
.
LastNode
()
lastNode
:=
route
.
LastNode
()
if
req
.
Method
!=
http
.
MethodConnect
&&
lastNode
.
Protocol
==
"http"
{
if
req
.
Method
!=
http
.
MethodConnect
&&
lastNode
.
Protocol
==
"http"
{
h
.
forwardRequest
(
conn
,
req
)
h
.
forwardRequest
(
conn
,
req
,
route
)
return
return
}
}
...
@@ -162,7 +167,7 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
...
@@ -162,7 +167,7 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
host
+=
":80"
host
+=
":80"
}
}
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
host
)
cc
,
err
:=
route
.
Dial
(
host
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
host
,
err
)
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
host
,
err
)
...
@@ -197,13 +202,13 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
...
@@ -197,13 +202,13 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
log
.
Logf
(
"[http] %s >-< %s"
,
cc
.
LocalAddr
(),
host
)
log
.
Logf
(
"[http] %s >-< %s"
,
cc
.
LocalAddr
(),
host
)
}
}
func
(
h
*
httpHandler
)
forwardRequest
(
conn
net
.
Conn
,
req
*
http
.
Request
)
{
func
(
h
*
httpHandler
)
forwardRequest
(
conn
net
.
Conn
,
req
*
http
.
Request
,
route
*
Chain
)
{
if
h
.
options
.
Chain
.
IsEmpty
()
{
if
route
.
IsEmpty
()
{
return
return
}
}
lastNode
:=
h
.
options
.
Chain
.
LastNode
()
lastNode
:=
route
.
LastNode
()
cc
,
err
:=
h
.
options
.
Chain
.
Conn
()
cc
,
err
:=
route
.
Conn
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
lastNode
.
Addr
,
err
)
log
.
Logf
(
"[http] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
lastNode
.
Addr
,
err
)
...
...
node.go
View file @
d39e211f
...
@@ -25,6 +25,7 @@ type Node struct {
...
@@ -25,6 +25,7 @@ type Node struct {
group
*
NodeGroup
group
*
NodeGroup
failCount
uint32
failCount
uint32
failTime
int64
failTime
int64
Bypass
*
Bypass
}
}
// ParseNode parses the node info.
// ParseNode parses the node info.
...
...
socks.go
View file @
d39e211f
...
@@ -267,7 +267,7 @@ func (c *socks4Connector) Connect(conn net.Conn, addr string) (net.Conn, error)
...
@@ -267,7 +267,7 @@ func (c *socks4Connector) Connect(conn net.Conn, addr string) (net.Conn, error)
return
nil
,
err
return
nil
,
err
}
}
if
len
(
taddr
.
IP
)
==
0
{
if
len
(
taddr
.
IP
)
==
0
{
taddr
.
IP
=
net
.
IPv4
(
0
,
0
,
0
,
0
)
taddr
.
IP
=
net
.
IPv4
zero
}
}
req
:=
gosocks4
.
NewRequest
(
gosocks4
.
CmdConnect
,
req
:=
gosocks4
.
NewRequest
(
gosocks4
.
CmdConnect
,
...
...
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