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
9345a2dc
Commit
9345a2dc
authored
May 20, 2018
by
ginuerzh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#249 add load balancing support for port forwarding
parent
b15c5bb3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
165 additions
and
22 deletions
+165
-22
forward.go
forward.go
+155
-22
node.go
node.go
+10
-0
No files found.
forward.go
View file @
9345a2dc
...
@@ -3,6 +3,7 @@ package gost
...
@@ -3,6 +3,7 @@ package gost
import
(
import
(
"errors"
"errors"
"net"
"net"
"strings"
"sync"
"sync"
"time"
"time"
...
@@ -27,17 +28,39 @@ func (c *forwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error)
...
@@ -27,17 +28,39 @@ func (c *forwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error)
type
tcpDirectForwardHandler
struct
{
type
tcpDirectForwardHandler
struct
{
raddr
string
raddr
string
group
*
NodeGroup
options
*
HandlerOptions
options
*
HandlerOptions
}
}
// TCPDirectForwardHandler creates a server Handler for TCP port forwarding server.
// TCPDirectForwardHandler creates a server Handler for TCP port forwarding server.
// The raddr is the remote address that the server will forward to.
// The raddr is the remote address that the server will forward to.
// NOTE: as of 2.6, remote address can be a comma-separated address list.
func
TCPDirectForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
func
TCPDirectForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
if
raddr
==
""
{
group
:=
NewNodeGroup
()
raddr
=
"0.0.0.0:0"
group
.
SetSelector
(
&
defaultSelector
{},
WithStrategy
(
&
RoundStrategy
{}),
WithFilter
(
&
FailFilter
{
MaxFails
:
1
,
FailTimeout
:
30
*
time
.
Second
,
}),
)
for
i
,
addr
:=
range
strings
.
Split
(
raddr
,
","
)
{
if
addr
==
""
{
continue
}
// We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing.
group
.
AddNode
(
Node
{
ID
:
i
+
1
,
Addr
:
addr
,
Host
:
addr
,
})
}
}
h
:=
&
tcpDirectForwardHandler
{
h
:=
&
tcpDirectForwardHandler
{
raddr
:
raddr
,
raddr
:
raddr
,
group
:
group
,
options
:
&
HandlerOptions
{},
options
:
&
HandlerOptions
{},
}
}
for
_
,
opt
:=
range
opts
{
for
_
,
opt
:=
range
opts
{
...
@@ -49,29 +72,63 @@ func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
...
@@ -49,29 +72,63 @@ func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
func
(
h
*
tcpDirectForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
func
(
h
*
tcpDirectForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
defer
conn
.
Close
()
log
.
Logf
(
"[tcp] %s - %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
)
node
,
err
:=
h
.
group
.
Next
()
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
h
.
raddr
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[tcp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
,
err
)
log
.
Logf
(
"[tcp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
,
err
)
return
}
log
.
Logf
(
"[tcp] %s - %s"
,
conn
.
RemoteAddr
(),
node
.
Addr
)
cc
,
err
:=
h
.
options
.
Chain
.
Dial
(
node
.
Addr
)
if
err
!=
nil
{
log
.
Logf
(
"[tcp] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
node
.
Addr
,
err
)
node
.
MarkDead
()
return
return
}
}
defer
cc
.
Close
()
defer
cc
.
Close
()
log
.
Logf
(
"[tcp] %s <-> %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
)
node
.
ResetDead
()
log
.
Logf
(
"[tcp] %s <-> %s"
,
conn
.
RemoteAddr
(),
node
.
Addr
)
transport
(
conn
,
cc
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[tcp] %s >-< %s"
,
conn
.
RemoteAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[tcp] %s >-< %s"
,
conn
.
RemoteAddr
(),
node
.
A
ddr
)
}
}
type
udpDirectForwardHandler
struct
{
type
udpDirectForwardHandler
struct
{
raddr
string
raddr
string
group
*
NodeGroup
options
*
HandlerOptions
options
*
HandlerOptions
}
}
// UDPDirectForwardHandler creates a server Handler for UDP port forwarding server.
// UDPDirectForwardHandler creates a server Handler for UDP port forwarding server.
// The raddr is the remote address that the server will forward to.
// The raddr is the remote address that the server will forward to.
// NOTE: as of 2.6, remote address can be a comma-separated address list.
func
UDPDirectForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
func
UDPDirectForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
group
:=
NewNodeGroup
()
group
.
SetSelector
(
&
defaultSelector
{},
WithStrategy
(
&
RoundStrategy
{}),
WithFilter
(
&
FailFilter
{
MaxFails
:
1
,
FailTimeout
:
30
*
time
.
Second
,
}),
)
for
i
,
addr
:=
range
strings
.
Split
(
raddr
,
","
)
{
if
addr
==
""
{
continue
}
// We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing.
group
.
AddNode
(
Node
{
ID
:
i
+
1
,
Addr
:
addr
,
Host
:
addr
,
})
}
h
:=
&
udpDirectForwardHandler
{
h
:=
&
udpDirectForwardHandler
{
raddr
:
raddr
,
raddr
:
raddr
,
group
:
group
,
options
:
&
HandlerOptions
{},
options
:
&
HandlerOptions
{},
}
}
for
_
,
opt
:=
range
opts
{
for
_
,
opt
:=
range
opts
{
...
@@ -83,45 +140,79 @@ func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
...
@@ -83,45 +140,79 @@ func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
func
(
h
*
udpDirectForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
func
(
h
*
udpDirectForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
defer
conn
.
Close
()
node
,
err
:=
h
.
group
.
Next
()
if
err
!=
nil
{
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
,
err
)
return
}
var
cc
net
.
Conn
var
cc
net
.
Conn
if
h
.
options
.
Chain
.
IsEmpty
()
{
if
h
.
options
.
Chain
.
IsEmpty
()
{
raddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
h
.
ra
ddr
)
raddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
node
.
A
ddr
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
LocalAddr
(),
h
.
raddr
,
err
)
node
.
MarkDead
()
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
LocalAddr
(),
node
.
Addr
,
err
)
return
return
}
}
cc
,
err
=
net
.
DialUDP
(
"udp"
,
nil
,
raddr
)
cc
,
err
=
net
.
DialUDP
(
"udp"
,
nil
,
raddr
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
LocalAddr
(),
h
.
raddr
,
err
)
node
.
MarkDead
()
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
LocalAddr
(),
node
.
Addr
,
err
)
return
return
}
}
}
else
{
}
else
{
var
err
error
var
err
error
cc
,
err
=
getSOCKS5UDPTunnel
(
h
.
options
.
Chain
,
nil
)
cc
,
err
=
getSOCKS5UDPTunnel
(
h
.
options
.
Chain
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
LocalAddr
(),
h
.
ra
ddr
,
err
)
log
.
Logf
(
"[udp] %s - %s : %s"
,
conn
.
LocalAddr
(),
node
.
A
ddr
,
err
)
return
return
}
}
cc
=
&
udpTunnelConn
{
Conn
:
cc
,
raddr
:
h
.
ra
ddr
}
cc
=
&
udpTunnelConn
{
Conn
:
cc
,
raddr
:
node
.
A
ddr
}
}
}
defer
cc
.
Close
()
defer
cc
.
Close
()
node
.
ResetDead
()
log
.
Logf
(
"[udp] %s <-> %s"
,
conn
.
RemoteAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[udp] %s <-> %s"
,
conn
.
RemoteAddr
(),
node
.
A
ddr
)
transport
(
conn
,
cc
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[udp] %s >-< %s"
,
conn
.
RemoteAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[udp] %s >-< %s"
,
conn
.
RemoteAddr
(),
node
.
A
ddr
)
}
}
type
tcpRemoteForwardHandler
struct
{
type
tcpRemoteForwardHandler
struct
{
raddr
string
raddr
string
group
*
NodeGroup
options
*
HandlerOptions
options
*
HandlerOptions
}
}
// TCPRemoteForwardHandler creates a server Handler for TCP remote port forwarding server.
// TCPRemoteForwardHandler creates a server Handler for TCP remote port forwarding server.
// The raddr is the remote address that the server will forward to.
// The raddr is the remote address that the server will forward to.
// NOTE: as of 2.6, remote address can be a comma-separated address list.
func
TCPRemoteForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
func
TCPRemoteForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
group
:=
NewNodeGroup
()
group
.
SetSelector
(
&
defaultSelector
{},
WithStrategy
(
&
RoundStrategy
{}),
WithFilter
(
&
FailFilter
{
MaxFails
:
1
,
FailTimeout
:
30
*
time
.
Second
,
}),
)
for
i
,
addr
:=
range
strings
.
Split
(
raddr
,
","
)
{
if
addr
==
""
{
continue
}
// We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing.
group
.
AddNode
(
Node
{
ID
:
i
+
1
,
Addr
:
addr
,
Host
:
addr
,
})
}
h
:=
&
tcpRemoteForwardHandler
{
h
:=
&
tcpRemoteForwardHandler
{
raddr
:
raddr
,
raddr
:
raddr
,
group
:
group
,
options
:
&
HandlerOptions
{},
options
:
&
HandlerOptions
{},
}
}
for
_
,
opt
:=
range
opts
{
for
_
,
opt
:=
range
opts
{
...
@@ -133,28 +224,60 @@ func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
...
@@ -133,28 +224,60 @@ func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
func
(
h
*
tcpRemoteForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
func
(
h
*
tcpRemoteForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
defer
conn
.
Close
()
cc
,
err
:=
net
.
DialTimeout
(
"tcp"
,
h
.
raddr
,
DialTimeout
)
node
,
err
:=
h
.
group
.
Next
(
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[rtcp] %s -> %s : %s"
,
conn
.
LocalAddr
(),
h
.
raddr
,
err
)
log
.
Logf
(
"[rtcp] %s - %s : %s"
,
conn
.
LocalAddr
(),
h
.
raddr
,
err
)
return
}
cc
,
err
:=
net
.
DialTimeout
(
"tcp"
,
node
.
Addr
,
DialTimeout
)
if
err
!=
nil
{
node
.
MarkDead
()
log
.
Logf
(
"[rtcp] %s -> %s : %s"
,
conn
.
LocalAddr
(),
node
.
Addr
,
err
)
return
return
}
}
defer
cc
.
Close
()
defer
cc
.
Close
()
node
.
ResetDead
()
log
.
Logf
(
"[rtcp] %s <-> %s"
,
conn
.
LocalAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[rtcp] %s <-> %s"
,
conn
.
LocalAddr
(),
node
.
A
ddr
)
transport
(
cc
,
conn
)
transport
(
cc
,
conn
)
log
.
Logf
(
"[rtcp] %s >-< %s"
,
conn
.
LocalAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[rtcp] %s >-< %s"
,
conn
.
LocalAddr
(),
node
.
A
ddr
)
}
}
type
udpRemoteForwardHandler
struct
{
type
udpRemoteForwardHandler
struct
{
raddr
string
raddr
string
group
*
NodeGroup
options
*
HandlerOptions
options
*
HandlerOptions
}
}
// UDPRemoteForwardHandler creates a server Handler for UDP remote port forwarding server.
// UDPRemoteForwardHandler creates a server Handler for UDP remote port forwarding server.
// The raddr is the remote address that the server will forward to.
// The raddr is the remote address that the server will forward to.
// NOTE: as of 2.6, remote address can be a comma-separated address list.
func
UDPRemoteForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
func
UDPRemoteForwardHandler
(
raddr
string
,
opts
...
HandlerOption
)
Handler
{
group
:=
NewNodeGroup
()
group
.
SetSelector
(
&
defaultSelector
{},
WithStrategy
(
&
RoundStrategy
{}),
WithFilter
(
&
FailFilter
{
MaxFails
:
1
,
FailTimeout
:
30
*
time
.
Second
,
}),
)
for
i
,
addr
:=
range
strings
.
Split
(
raddr
,
","
)
{
if
addr
==
""
{
continue
}
// We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing.
group
.
AddNode
(
Node
{
ID
:
i
+
1
,
Addr
:
addr
,
Host
:
addr
,
})
}
h
:=
&
udpRemoteForwardHandler
{
h
:=
&
udpRemoteForwardHandler
{
raddr
:
raddr
,
raddr
:
raddr
,
group
:
group
,
options
:
&
HandlerOptions
{},
options
:
&
HandlerOptions
{},
}
}
for
_
,
opt
:=
range
opts
{
for
_
,
opt
:=
range
opts
{
...
@@ -166,20 +289,30 @@ func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
...
@@ -166,20 +289,30 @@ func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
func
(
h
*
udpRemoteForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
func
(
h
*
udpRemoteForwardHandler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
defer
conn
.
Close
()
raddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
h
.
raddr
)
node
,
err
:=
h
.
group
.
Next
(
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[rudp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
,
err
)
log
.
Logf
(
"[rudp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
,
err
)
return
return
}
}
raddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
node
.
Addr
)
if
err
!=
nil
{
node
.
MarkDead
()
log
.
Logf
(
"[rudp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
node
.
Addr
,
err
)
return
}
cc
,
err
:=
net
.
DialUDP
(
"udp"
,
nil
,
raddr
)
cc
,
err
:=
net
.
DialUDP
(
"udp"
,
nil
,
raddr
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Logf
(
"[rudp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
h
.
raddr
,
err
)
node
.
MarkDead
()
log
.
Logf
(
"[rudp] %s - %s : %s"
,
conn
.
RemoteAddr
(),
node
.
Addr
,
err
)
return
return
}
}
defer
cc
.
Close
()
node
.
ResetDead
()
log
.
Logf
(
"[rudp] %s <-> %s"
,
conn
.
RemoteAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[rudp] %s <-> %s"
,
conn
.
RemoteAddr
(),
node
.
A
ddr
)
transport
(
conn
,
cc
)
transport
(
conn
,
cc
)
log
.
Logf
(
"[rudp] %s >-< %s"
,
conn
.
RemoteAddr
(),
h
.
ra
ddr
)
log
.
Logf
(
"[rudp] %s >-< %s"
,
conn
.
RemoteAddr
(),
node
.
A
ddr
)
}
}
type
udpDirectForwardListener
struct
{
type
udpDirectForwardListener
struct
{
...
...
node.go
View file @
9345a2dc
...
@@ -140,6 +140,7 @@ func (node *Node) Clone() Node {
...
@@ -140,6 +140,7 @@ func (node *Node) Clone() Node {
group
:
node
.
group
,
group
:
node
.
group
,
failCount
:
atomic
.
LoadUint32
(
&
node
.
failCount
),
failCount
:
atomic
.
LoadUint32
(
&
node
.
failCount
),
failTime
:
atomic
.
LoadInt64
(
&
node
.
failTime
),
failTime
:
atomic
.
LoadInt64
(
&
node
.
failTime
),
Bypass
:
node
.
Bypass
,
}
}
}
}
...
@@ -187,6 +188,15 @@ func (group *NodeGroup) AddNode(node ...Node) {
...
@@ -187,6 +188,15 @@ func (group *NodeGroup) AddNode(node ...Node) {
group
.
nodes
=
append
(
group
.
nodes
,
node
...
)
group
.
nodes
=
append
(
group
.
nodes
,
node
...
)
}
}
// SetSelector sets node selector with options for the group.
func
(
group
*
NodeGroup
)
SetSelector
(
selector
NodeSelector
,
opts
...
SelectOption
)
{
if
group
==
nil
{
return
}
group
.
Selector
=
selector
group
.
Options
=
opts
}
// Nodes returns node list in the group
// Nodes returns node list in the group
func
(
group
*
NodeGroup
)
Nodes
()
[]
Node
{
func
(
group
*
NodeGroup
)
Nodes
()
[]
Node
{
if
group
==
nil
{
if
group
==
nil
{
...
...
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