代码拉取完成,页面将自动刷新
package gost
import (
"context"
"errors"
"net"
"strings"
"sync"
"time"
"fmt"
"github.com/ginuerzh/gosocks5"
"github.com/go-log/log"
smux "gopkg.in/xtaci/smux.v1"
)
type forwardConnector struct {
}
// ForwardConnector creates a Connector for data forward client.
func ForwardConnector() Connector {
return &forwardConnector{}
}
func (c *forwardConnector) Connect(conn net.Conn, address string, options ...ConnectOption) (net.Conn, error) {
return c.ConnectContext(context.Background(), conn, "tcp", address, options...)
}
func (c *forwardConnector) ConnectContext(ctx context.Context, conn net.Conn, network, address string, options ...ConnectOption) (net.Conn, error) {
return conn, nil
}
type baseForwardHandler struct {
raddr string
group *NodeGroup
options *HandlerOptions
}
func (h *baseForwardHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
h.group = NewNodeGroup() // reset node group
h.group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: h.options.MaxFails,
FailTimeout: h.options.FailTimeout,
}),
)
n := 1
addrs := append(strings.Split(h.raddr, ","), h.options.IPs...)
for _, addr := range addrs {
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.
h.group.AddNode(Node{
ID: n,
Addr: addr,
Host: addr,
marker: &failMarker{},
})
n++
}
}
type tcpDirectForwardHandler struct {
*baseForwardHandler
}
// TCPDirectForwardHandler creates a server Handler for TCP port forwarding server.
// 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 {
h := &tcpDirectForwardHandler{
baseForwardHandler: &baseForwardHandler{
raddr: raddr,
group: NewNodeGroup(),
options: &HandlerOptions{},
},
}
for _, opt := range opts {
opt(h.options)
}
return h
}
func (h *tcpDirectForwardHandler) Init(options ...HandlerOption) {
h.baseForwardHandler.Init(options...)
}
func (h *tcpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close()
log.Logf("[tcp] %s - %s", conn.RemoteAddr(), conn.LocalAddr())
retries := 1
if h.options.Chain != nil && h.options.Chain.Retries > 0 {
retries = h.options.Chain.Retries
}
if h.options.Retries > 0 {
retries = h.options.Retries
}
var cc net.Conn
var node Node
var err error
for i := 0; i < retries; i++ {
if len(h.group.Nodes()) > 0 {
node, err = h.group.Next()
if err != nil {
log.Logf("[tcp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
}
cc, err = h.options.Chain.Dial(node.Addr,
RetryChainOption(h.options.Retries),
TimeoutChainOption(h.options.Timeout),
)
if err != nil {
log.Logf("[tcp] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
node.MarkDead()
} else {
break
}
}
if err != nil {
return
}
node.ResetDead()
defer cc.Close()
addr := node.Addr
if addr == "" {
addr = conn.LocalAddr().String()
}
log.Logf("[tcp] %s <-> %s", conn.RemoteAddr(), addr)
transport(conn, cc)
log.Logf("[tcp] %s >-< %s", conn.RemoteAddr(), addr)
}
type udpDirectForwardHandler struct {
*baseForwardHandler
}
// UDPDirectForwardHandler creates a server Handler for UDP port forwarding server.
// 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 {
h := &udpDirectForwardHandler{
baseForwardHandler: &baseForwardHandler{
raddr: raddr,
group: NewNodeGroup(),
options: &HandlerOptions{},
},
}
for _, opt := range opts {
opt(h.options)
}
return h
}
func (h *udpDirectForwardHandler) Init(options ...HandlerOption) {
h.baseForwardHandler.Init(options...)
}
func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close()
log.Logf("[udp] %s - %s", conn.RemoteAddr(), conn.LocalAddr())
var node Node
var err error
if len(h.group.Nodes()) > 0 {
node, err = h.group.Next()
if err != nil {
log.Logf("[udp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
}
cc, err := h.options.Chain.DialContext(context.Background(), "udp", node.Addr)
if err != nil {
node.MarkDead()
log.Logf("[udp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
defer cc.Close()
node.ResetDead()
addr := node.Addr
if addr == "" {
addr = conn.LocalAddr().String()
}
log.Logf("[udp] %s <-> %s", conn.RemoteAddr(), addr)
transport(conn, cc)
log.Logf("[udp] %s >-< %s", conn.RemoteAddr(), addr)
}
type tcpRemoteForwardHandler struct {
*baseForwardHandler
}
// TCPRemoteForwardHandler creates a server Handler for TCP remote port forwarding server.
// 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 {
h := &tcpRemoteForwardHandler{
baseForwardHandler: &baseForwardHandler{
raddr: raddr,
group: NewNodeGroup(),
options: &HandlerOptions{},
},
}
for _, opt := range opts {
opt(h.options)
}
return h
}
func (h *tcpRemoteForwardHandler) Init(options ...HandlerOption) {
h.baseForwardHandler.Init(options...)
}
func (h *tcpRemoteForwardHandler) Handle(conn net.Conn) {
defer conn.Close()
retries := 1
if h.options.Retries > 0 {
retries = h.options.Retries
}
var cc net.Conn
var node Node
var err error
for i := 0; i < retries; i++ {
if len(h.group.Nodes()) > 0 {
node, err = h.group.Next()
if err != nil {
log.Logf("[rtcp] %s - %s : %s", conn.LocalAddr(), h.raddr, err)
return
}
}
cc, err = net.DialTimeout("tcp", node.Addr, h.options.Timeout)
if err != nil {
log.Logf("[rtcp] %s -> %s : %s", conn.LocalAddr(), node.Addr, err)
node.MarkDead()
} else {
break
}
}
if err != nil {
return
}
defer cc.Close()
node.ResetDead()
log.Logf("[rtcp] %s <-> %s", conn.LocalAddr(), node.Addr)
transport(cc, conn)
log.Logf("[rtcp] %s >-< %s", conn.LocalAddr(), node.Addr)
}
type udpRemoteForwardHandler struct {
*baseForwardHandler
}
// UDPRemoteForwardHandler creates a server Handler for UDP remote port forwarding server.
// 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 {
h := &udpRemoteForwardHandler{
baseForwardHandler: &baseForwardHandler{
raddr: raddr,
group: NewNodeGroup(),
options: &HandlerOptions{},
},
}
for _, opt := range opts {
opt(h.options)
}
return h
}
func (h *udpRemoteForwardHandler) Init(options ...HandlerOption) {
h.baseForwardHandler.Init(options...)
}
func (h *udpRemoteForwardHandler) Handle(conn net.Conn) {
defer conn.Close()
var node Node
var err error
if len(h.group.Nodes()) > 0 {
node, err = h.group.Next()
if err != nil {
log.Logf("[rudp] %s - %s : %s", conn.RemoteAddr(), h.raddr, err)
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)
if err != nil {
node.MarkDead()
log.Logf("[rudp] %s - %s : %s", conn.RemoteAddr(), node.Addr, err)
return
}
defer cc.Close()
node.ResetDead()
log.Logf("[rudp] %s <-> %s", conn.RemoteAddr(), node.Addr)
transport(conn, cc)
log.Logf("[rudp] %s >-< %s", conn.RemoteAddr(), node.Addr)
}
type tcpRemoteForwardListener struct {
addr net.Addr
chain *Chain
connChan chan net.Conn
ln net.Listener
session *muxSession
sessionMux sync.Mutex
closed chan struct{}
closeMux sync.Mutex
}
// TCPRemoteForwardListener creates a Listener for TCP remote port forwarding server.
func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
laddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
ln := &tcpRemoteForwardListener{
addr: laddr,
chain: chain,
connChan: make(chan net.Conn, 1024),
closed: make(chan struct{}),
}
if !ln.isChainValid() {
ln.ln, err = net.Listen("tcp", ln.addr.String())
return ln, err
}
go ln.listenLoop()
return ln, err
}
func (l *tcpRemoteForwardListener) isChainValid() bool {
if l.chain.IsEmpty() {
return false
}
lastNode := l.chain.LastNode()
if (lastNode.Protocol == "forward" && lastNode.Transport == "ssh") ||
lastNode.Protocol == "socks5" || lastNode.Protocol == "" {
return true
}
return false
}
func (l *tcpRemoteForwardListener) listenLoop() {
var tempDelay time.Duration
for {
conn, err := l.accept()
select {
case <-l.closed:
if conn != nil {
conn.Close()
}
return
default:
}
if err != nil {
if tempDelay == 0 {
tempDelay = 1000 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 6 * time.Second; tempDelay > max {
tempDelay = max
}
log.Logf("[rtcp] accept error: %v; retrying in %v", err, tempDelay)
time.Sleep(tempDelay)
continue
}
tempDelay = 0
select {
case l.connChan <- conn:
default:
conn.Close()
log.Logf("[rtcp] %s - %s: connection queue is full", conn.RemoteAddr(), conn.LocalAddr())
}
}
}
func (l *tcpRemoteForwardListener) Accept() (conn net.Conn, err error) {
if l.ln != nil {
return l.ln.Accept()
}
select {
case conn = <-l.connChan:
case <-l.closed:
err = errors.New("closed")
}
return
}
func (l *tcpRemoteForwardListener) accept() (conn net.Conn, err error) {
lastNode := l.chain.LastNode()
if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" {
return l.chain.Dial(l.addr.String())
}
if l.isChainValid() {
if lastNode.GetBool("mbind") {
return l.muxAccept() // multiplexing support for binding.
}
cc, er := l.chain.Conn()
if er != nil {
return nil, er
}
conn, err = l.waitConnectSOCKS5(cc)
if err != nil {
cc.Close()
}
}
return
}
func (l *tcpRemoteForwardListener) muxAccept() (conn net.Conn, err error) {
session, err := l.getSession()
if err != nil {
return nil, err
}
cc, err := session.Accept()
if err != nil {
session.Close()
return nil, err
}
return cc, nil
}
func (l *tcpRemoteForwardListener) getSession() (s *muxSession, err error) {
l.sessionMux.Lock()
defer l.sessionMux.Unlock()
if l.session != nil && !l.session.IsClosed() {
return l.session, nil
}
conn, err := l.chain.Conn()
if err != nil {
return nil, err
}
defer func(c net.Conn) {
if err != nil {
c.Close()
}
}(conn)
conn.SetDeadline(time.Now().Add(HandshakeTimeout))
defer conn.SetDeadline(time.Time{})
conn, err = socks5Handshake(conn, userSocks5HandshakeOption(l.chain.LastNode().User))
if err != nil {
return nil, err
}
req := gosocks5.NewRequest(CmdMuxBind, toSocksAddr(l.addr))
if err := req.Write(conn); err != nil {
log.Log("[rtcp] SOCKS5 BIND request: ", err)
return nil, err
}
rep, err := gosocks5.ReadReply(conn)
if err != nil {
log.Log("[rtcp] SOCKS5 BIND reply: ", err)
return nil, err
}
if rep.Rep != gosocks5.Succeeded {
log.Logf("[rtcp] bind on %s failure", l.addr)
return nil, fmt.Errorf("Bind on %s failure", l.addr.String())
}
log.Logf("[rtcp] BIND ON %s OK", rep.Addr)
// Upgrade connection to multiplex stream.
session, err := smux.Server(conn, smux.DefaultConfig())
if err != nil {
return nil, err
}
l.session = &muxSession{
conn: conn,
session: session,
}
return l.session, nil
}
func (l *tcpRemoteForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
conn, err := socks5Handshake(conn, userSocks5HandshakeOption(l.chain.LastNode().User))
if err != nil {
return nil, err
}
req := gosocks5.NewRequest(gosocks5.CmdBind, toSocksAddr(l.addr))
if err := req.Write(conn); err != nil {
log.Log("[rtcp] SOCKS5 BIND request: ", err)
return nil, err
}
// first reply, bind status
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
rep, err := gosocks5.ReadReply(conn)
if err != nil {
log.Log("[rtcp] SOCKS5 BIND reply: ", err)
return nil, err
}
conn.SetReadDeadline(time.Time{})
if rep.Rep != gosocks5.Succeeded {
log.Logf("[rtcp] bind on %s failure", l.addr)
return nil, fmt.Errorf("Bind on %s failure", l.addr.String())
}
log.Logf("[rtcp] BIND ON %s OK", rep.Addr)
// second reply, peer connected
rep, err = gosocks5.ReadReply(conn)
if err != nil {
log.Log("[rtcp]", err)
return nil, err
}
if rep.Rep != gosocks5.Succeeded {
log.Logf("[rtcp] peer connect failure: %d", rep.Rep)
return nil, errors.New("peer connect failure")
}
log.Logf("[rtcp] PEER %s CONNECTED", rep.Addr)
return conn, nil
}
func (l *tcpRemoteForwardListener) Addr() net.Addr {
if l.ln != nil {
return l.ln.Addr()
}
return l.addr
}
func (l *tcpRemoteForwardListener) Close() error {
if l.ln != nil {
return l.ln.Close()
}
l.closeMux.Lock()
defer l.closeMux.Unlock()
select {
case <-l.closed:
return nil
default:
close(l.closed)
}
return nil
}
type udpRemoteForwardListener struct {
addr net.Addr
chain *Chain
connMap *udpConnMap
connChan chan net.Conn
ln *net.UDPConn
ttl time.Duration
closed chan struct{}
ready chan struct{}
once sync.Once
closeMux sync.Mutex
config *UDPListenConfig
}
// UDPRemoteForwardListener creates a Listener for UDP remote port forwarding server.
func UDPRemoteForwardListener(addr string, chain *Chain, cfg *UDPListenConfig) (Listener, error) {
laddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
if cfg == nil {
cfg = &UDPListenConfig{}
}
backlog := cfg.Backlog
if backlog <= 0 {
backlog = defaultBacklog
}
ln := &udpRemoteForwardListener{
addr: laddr,
chain: chain,
connMap: new(udpConnMap),
connChan: make(chan net.Conn, backlog),
ready: make(chan struct{}),
closed: make(chan struct{}),
config: cfg,
}
go ln.listenLoop()
<-ln.ready
return ln, err
}
func (l *udpRemoteForwardListener) isChainValid() bool {
if l.chain.IsEmpty() {
return false
}
lastNode := l.chain.LastNode()
return lastNode.Protocol == "socks5" || lastNode.Protocol == ""
}
func (l *udpRemoteForwardListener) listenLoop() {
for {
conn, err := l.connect()
if err != nil {
log.Logf("[rudp] %s : %s", l.Addr(), err)
return
}
l.once.Do(func() {
close(l.ready)
})
func() {
defer conn.Close()
for {
b := make([]byte, mediumBufferSize)
n, raddr, err := conn.ReadFrom(b)
if err != nil {
log.Logf("[rudp] %s : %s", l.Addr(), err)
break
}
uc, ok := l.connMap.Get(raddr.String())
if !ok {
uc = newUDPServerConn(conn, raddr, &udpServerConnConfig{
ttl: l.config.TTL,
qsize: l.config.QueueSize,
onClose: func() {
l.connMap.Delete(raddr.String())
log.Logf("[rudp] %s closed (%d)", raddr, l.connMap.Size())
},
})
select {
case l.connChan <- uc:
l.connMap.Set(raddr.String(), uc)
log.Logf("[rudp] %s -> %s (%d)", raddr, l.Addr(), l.connMap.Size())
default:
uc.Close()
log.Logf("[rudp] %s - %s: connection queue is full (%d)",
raddr, l.Addr(), cap(l.connChan))
}
}
select {
case uc.rChan <- b[:n]:
if Debug {
log.Logf("[rudp] %s >>> %s : length %d", raddr, l.Addr(), n)
}
default:
log.Logf("[rudp] %s -> %s : recv queue is full", raddr, l.Addr(), cap(uc.rChan))
}
}
}()
}
}
func (l *udpRemoteForwardListener) connect() (conn net.PacketConn, err error) {
var tempDelay time.Duration
for {
select {
case <-l.closed:
return nil, errors.New("closed")
default:
}
if l.isChainValid() {
var cc net.Conn
cc, err = getSocks5UDPTunnel(l.chain, l.addr)
if err != nil {
log.Logf("[rudp] %s : %s", l.Addr(), err)
} else {
conn = cc.(net.PacketConn)
}
} else {
var uc *net.UDPConn
uc, err = net.ListenUDP("udp", l.addr.(*net.UDPAddr))
if err == nil {
l.addr = uc.LocalAddr()
conn = uc
}
}
if err != nil {
if tempDelay == 0 {
tempDelay = 1000 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 6 * time.Second; tempDelay > max {
tempDelay = max
}
log.Logf("[rudp] Accept error: %v; retrying in %v", err, tempDelay)
time.Sleep(tempDelay)
continue
}
return
}
}
func (l *udpRemoteForwardListener) Accept() (conn net.Conn, err error) {
select {
case conn = <-l.connChan:
case <-l.closed:
err = errors.New("accpet on closed listener")
}
return
}
func (l *udpRemoteForwardListener) Addr() net.Addr {
return l.addr
}
func (l *udpRemoteForwardListener) Close() error {
l.closeMux.Lock()
defer l.closeMux.Unlock()
select {
case <-l.closed:
return nil
default:
l.connMap.Range(func(k interface{}, v *udpServerConn) bool {
v.Close()
return true
})
close(l.closed)
}
return nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。