mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-12-24 11:51:13 +08:00
remove unneeded code
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -100,29 +99,15 @@ func (c *Chain) IsEmpty() bool {
|
||||
return c == nil || len(c.nodeGroups) == 0
|
||||
}
|
||||
|
||||
// Dial connects to the target TCP address addr through the chain.
|
||||
// Deprecated: use DialContext instead.
|
||||
func (c *Chain) Dial(address string, opts ...ChainOption) (conn net.Conn, err error) {
|
||||
return c.DialContext(context.Background(), "tcp", address, opts...)
|
||||
}
|
||||
|
||||
// DialContext connects to the address on the named network using the provided context.
|
||||
func (c *Chain) DialContext(ctx context.Context, network, address string, opts ...ChainOption) (conn net.Conn, err error) {
|
||||
options := &ChainOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
func (c *Chain) DialContext(ctx context.Context, network, address string) (conn net.Conn, err error) {
|
||||
retries := 1
|
||||
if c != nil && c.Retries > 0 {
|
||||
retries = c.Retries
|
||||
}
|
||||
if options.Retries > 0 {
|
||||
retries = options.Retries
|
||||
}
|
||||
|
||||
for i := 0; i < retries; i++ {
|
||||
conn, err = c.dialWithOptions(ctx, network, address, options)
|
||||
conn, err = c.dial(ctx, network, address)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
@@ -130,10 +115,7 @@ func (c *Chain) DialContext(ctx context.Context, network, address string, opts .
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Chain) dialWithOptions(ctx context.Context, network, address string, options *ChainOptions) (net.Conn, error) {
|
||||
if options == nil {
|
||||
options = &ChainOptions{}
|
||||
}
|
||||
func (c *Chain) dial(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
route, err := c.selectRouteFor(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -144,11 +126,6 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op
|
||||
ipAddr = c.resolve(address)
|
||||
}
|
||||
|
||||
timeout := options.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = DialTimeout
|
||||
}
|
||||
|
||||
if route.IsEmpty() {
|
||||
switch network {
|
||||
case "udp", "udp4", "udp6":
|
||||
@@ -158,7 +135,7 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op
|
||||
default:
|
||||
}
|
||||
d := &net.Dialer{
|
||||
Timeout: timeout,
|
||||
Timeout: DialTimeout,
|
||||
// LocalAddr: laddr, // TODO: optional local address
|
||||
}
|
||||
return d.DialContext(ctx, network, ipAddr)
|
||||
@@ -169,8 +146,7 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cOpts := append([]ConnectOption{AddrConnectOption(address)}, route.LastNode().ConnectOptions...)
|
||||
cc, err := route.LastNode().Client.ConnectContext(ctx, conn, network, ipAddr, cOpts...)
|
||||
cc, err := route.LastNode().Client.ConnectContext(ctx, conn, network, ipAddr)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
@@ -188,21 +164,13 @@ func (*Chain) resolve(addr string) string {
|
||||
}
|
||||
|
||||
// Conn obtains a handshaked connection to the last node of the chain.
|
||||
func (c *Chain) Conn(opts ...ChainOption) (conn net.Conn, err error) {
|
||||
options := &ChainOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
func (c *Chain) Conn() (conn net.Conn, err error) {
|
||||
ctx := context.Background()
|
||||
|
||||
retries := 1
|
||||
if c != nil && c.Retries > 0 {
|
||||
retries = c.Retries
|
||||
}
|
||||
if options.Retries > 0 {
|
||||
retries = options.Retries
|
||||
}
|
||||
|
||||
for i := 0; i < retries; i++ {
|
||||
var route *Chain
|
||||
@@ -227,17 +195,12 @@ func (c *Chain) getConn(_ context.Context) (conn net.Conn, err error) {
|
||||
nodes := c.Nodes()
|
||||
node := nodes[0]
|
||||
|
||||
cc, err := node.Client.Dial(node.Addr, node.DialOptions...)
|
||||
cc, err := node.Client.Dial(node.Addr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cn, err := node.Client.Handshake(cc, node.HandshakeOptions...)
|
||||
if err != nil {
|
||||
cc.Close()
|
||||
return
|
||||
}
|
||||
conn = cn
|
||||
conn = cc
|
||||
return
|
||||
}
|
||||
|
||||
@@ -255,7 +218,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||
}
|
||||
|
||||
route = newRoute()
|
||||
var nl []Node
|
||||
var nodes []Node
|
||||
|
||||
for _, group := range c.nodeGroups {
|
||||
var node Node
|
||||
@@ -264,41 +227,10 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if node.Client.Transporter.Multiplex() {
|
||||
node.DialOptions = append(node.DialOptions,
|
||||
ChainDialOption(route),
|
||||
)
|
||||
route = newRoute() // cutoff the chain for multiplex node.
|
||||
}
|
||||
|
||||
route.AddNode(node)
|
||||
nl = append(nl, node)
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
route.route = nl
|
||||
|
||||
route.route = nodes
|
||||
return
|
||||
}
|
||||
|
||||
// ChainOptions holds options for Chain.
|
||||
type ChainOptions struct {
|
||||
Retries int
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// ChainOption allows a common way to set chain options.
|
||||
type ChainOption func(opts *ChainOptions)
|
||||
|
||||
// RetryChainOption specifies the times of retry used by Chain.Dial.
|
||||
func RetryChainOption(retries int) ChainOption {
|
||||
return func(opts *ChainOptions) {
|
||||
opts.Retries = retries
|
||||
}
|
||||
}
|
||||
|
||||
// TimeoutChainOption specifies the timeout used by Chain.Dial.
|
||||
func TimeoutChainOption(timeout time.Duration) ChainOption {
|
||||
return func(opts *ChainOptions) {
|
||||
opts.Timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
200
core/client.go
200
core/client.go
@@ -2,13 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
)
|
||||
|
||||
// Client is a proxy client.
|
||||
@@ -22,200 +16,10 @@ type Client struct {
|
||||
|
||||
// Connector is responsible for connecting to the destination address.
|
||||
type Connector interface {
|
||||
// Deprecated: use ConnectContext instead.
|
||||
Connect(conn net.Conn, address string, options ...ConnectOption) (net.Conn, error)
|
||||
ConnectContext(ctx context.Context, conn net.Conn, network, address string, options ...ConnectOption) (net.Conn, error)
|
||||
}
|
||||
|
||||
type autoConnector struct {
|
||||
User *url.Userinfo
|
||||
}
|
||||
|
||||
// AutoConnector is a Connector.
|
||||
func AutoConnector(user *url.Userinfo) Connector {
|
||||
return &autoConnector{
|
||||
User: user,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *autoConnector) Connect(conn net.Conn, address string, options ...ConnectOption) (net.Conn, error) {
|
||||
return c.ConnectContext(context.Background(), conn, "tcp", address, options...)
|
||||
}
|
||||
|
||||
func (c *autoConnector) ConnectContext(ctx context.Context, conn net.Conn, network, address string, options ...ConnectOption) (net.Conn, error) {
|
||||
var cnr Connector
|
||||
switch network {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
fmt.Println("xxxxxxxxxxxxxxxxxxxxxxx------------------------------------------")
|
||||
//cnr = &httpConnector{User: c.User}
|
||||
default:
|
||||
cnr = SOCKS5UDPTunConnector(c.User)
|
||||
}
|
||||
|
||||
return cnr.ConnectContext(ctx, conn, network, address, options...)
|
||||
ConnectContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// Transporter is responsible for handshaking with the proxy server.
|
||||
type Transporter interface {
|
||||
Dial(addr string, options ...DialOption) (net.Conn, error)
|
||||
Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error)
|
||||
// Indicate that the Transporter supports multiplex
|
||||
Multiplex() bool
|
||||
}
|
||||
|
||||
// DialOptions describes the options for Transporter.Dial.
|
||||
type DialOptions struct {
|
||||
Timeout time.Duration
|
||||
Chain *Chain
|
||||
Host string
|
||||
}
|
||||
|
||||
// DialOption allows a common way to set DialOptions.
|
||||
type DialOption func(opts *DialOptions)
|
||||
|
||||
// TimeoutDialOption specifies the timeout used by Transporter.Dial
|
||||
func TimeoutDialOption(timeout time.Duration) DialOption {
|
||||
return func(opts *DialOptions) {
|
||||
opts.Timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// ChainDialOption specifies a chain used by Transporter.Dial
|
||||
func ChainDialOption(chain *Chain) DialOption {
|
||||
return func(opts *DialOptions) {
|
||||
opts.Chain = chain
|
||||
}
|
||||
}
|
||||
|
||||
// HostDialOption specifies the host used by Transporter.Dial
|
||||
func HostDialOption(host string) DialOption {
|
||||
return func(opts *DialOptions) {
|
||||
opts.Host = host
|
||||
}
|
||||
}
|
||||
|
||||
// HandshakeOptions describes the options for handshake.
|
||||
type HandshakeOptions struct {
|
||||
Addr string
|
||||
Host string
|
||||
User *url.Userinfo
|
||||
Timeout time.Duration
|
||||
Interval time.Duration
|
||||
Retry int
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// HandshakeOption allows a common way to set HandshakeOptions.
|
||||
type HandshakeOption func(opts *HandshakeOptions)
|
||||
|
||||
// AddrHandshakeOption specifies the server address
|
||||
func AddrHandshakeOption(addr string) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.Addr = addr
|
||||
}
|
||||
}
|
||||
|
||||
// HostHandshakeOption specifies the hostname
|
||||
func HostHandshakeOption(host string) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.Host = host
|
||||
}
|
||||
}
|
||||
|
||||
// UserHandshakeOption specifies the user used by Transporter.Handshake
|
||||
func UserHandshakeOption(user *url.Userinfo) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.User = user
|
||||
}
|
||||
}
|
||||
|
||||
// TimeoutHandshakeOption specifies the timeout used by Transporter.Handshake
|
||||
func TimeoutHandshakeOption(timeout time.Duration) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.Timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// IntervalHandshakeOption specifies the interval time used by Transporter.Handshake
|
||||
func IntervalHandshakeOption(interval time.Duration) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.Interval = interval
|
||||
}
|
||||
}
|
||||
|
||||
// RetryHandshakeOption specifies the times of retry used by Transporter.Handshake
|
||||
func RetryHandshakeOption(retry int) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.Retry = retry
|
||||
}
|
||||
}
|
||||
|
||||
// TLSConfigHandshakeOption specifies the TLS config used by Transporter.Handshake
|
||||
func TLSConfigHandshakeOption(config *tls.Config) HandshakeOption {
|
||||
return func(opts *HandshakeOptions) {
|
||||
opts.TLSConfig = config
|
||||
}
|
||||
}
|
||||
|
||||
// ConnectOptions describes the options for Connector.Connect.
|
||||
type ConnectOptions struct {
|
||||
Addr string
|
||||
Timeout time.Duration
|
||||
User *url.Userinfo
|
||||
Selector gosocks5.Selector
|
||||
UserAgent string
|
||||
NoTLS bool
|
||||
NoDelay bool
|
||||
}
|
||||
|
||||
// ConnectOption allows a common way to set ConnectOptions.
|
||||
type ConnectOption func(opts *ConnectOptions)
|
||||
|
||||
// AddrConnectOption specifies the corresponding address of the target.
|
||||
func AddrConnectOption(addr string) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.Addr = addr
|
||||
}
|
||||
}
|
||||
|
||||
// TimeoutConnectOption specifies the timeout for connecting to target.
|
||||
func TimeoutConnectOption(timeout time.Duration) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.Timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// UserConnectOption specifies the user info for authentication.
|
||||
func UserConnectOption(user *url.Userinfo) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.User = user
|
||||
}
|
||||
}
|
||||
|
||||
// SelectorConnectOption specifies the SOCKS5 client selector.
|
||||
func SelectorConnectOption(s gosocks5.Selector) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.Selector = s
|
||||
}
|
||||
}
|
||||
|
||||
// UserAgentConnectOption specifies the HTTP user-agent header.
|
||||
func UserAgentConnectOption(ua string) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.UserAgent = ua
|
||||
}
|
||||
}
|
||||
|
||||
// NoTLSConnectOption specifies the SOCKS5 method without TLS.
|
||||
func NoTLSConnectOption(b bool) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.NoTLS = b
|
||||
}
|
||||
}
|
||||
|
||||
// NoDelayConnectOption specifies the NoDelay option for ss.Connect.
|
||||
func NoDelayConnectOption(b bool) ConnectOption {
|
||||
return func(opts *ConnectOptions) {
|
||||
opts.NoDelay = b
|
||||
}
|
||||
Dial(addr string) (net.Conn, error)
|
||||
}
|
||||
|
||||
103
core/handler.go
103
core/handler.go
@@ -1,14 +1,8 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
"github.com/go-log/log"
|
||||
)
|
||||
|
||||
// Handler is a proxy server handler
|
||||
@@ -19,30 +13,16 @@ type Handler interface {
|
||||
|
||||
// HandlerOptions describes the options for Handler.
|
||||
type HandlerOptions struct {
|
||||
Addr string
|
||||
Chain *Chain
|
||||
Users []*url.Userinfo
|
||||
Authenticator Authenticator
|
||||
TLSConfig *tls.Config
|
||||
MaxFails int
|
||||
FailTimeout time.Duration
|
||||
Retries int
|
||||
Timeout time.Duration
|
||||
Node Node
|
||||
TCPMode bool
|
||||
IPRoutes []IPRoute
|
||||
}
|
||||
|
||||
// HandlerOption allows a common way to set handler options.
|
||||
type HandlerOption func(opts *HandlerOptions)
|
||||
|
||||
// AddrHandlerOption sets the Addr option of HandlerOptions.
|
||||
func AddrHandlerOption(addr string) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.Addr = addr
|
||||
}
|
||||
}
|
||||
|
||||
// ChainHandlerOption sets the Chain option of HandlerOptions.
|
||||
func ChainHandlerOption(chain *Chain) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
@@ -57,34 +37,6 @@ func AuthenticatorHandlerOption(authenticator Authenticator) HandlerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// MaxFailsHandlerOption sets the max_fails option of HandlerOptions.
|
||||
func MaxFailsHandlerOption(n int) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.MaxFails = n
|
||||
}
|
||||
}
|
||||
|
||||
// FailTimeoutHandlerOption sets the fail_timeout option of HandlerOptions.
|
||||
func FailTimeoutHandlerOption(d time.Duration) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.FailTimeout = d
|
||||
}
|
||||
}
|
||||
|
||||
// RetryHandlerOption sets the retry option of HandlerOptions.
|
||||
func RetryHandlerOption(retries int) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.Retries = retries
|
||||
}
|
||||
}
|
||||
|
||||
// TimeoutHandlerOption sets the timeout option of HandlerOptions.
|
||||
func TimeoutHandlerOption(timeout time.Duration) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.Timeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
// NodeHandlerOption set the server node for server handler.
|
||||
func NodeHandlerOption(node Node) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
@@ -92,64 +44,9 @@ func NodeHandlerOption(node Node) HandlerOption {
|
||||
}
|
||||
}
|
||||
|
||||
// TCPModeHandlerOption sets the tcp mode for tun/tap device.
|
||||
func TCPModeHandlerOption(b bool) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.TCPMode = b
|
||||
}
|
||||
}
|
||||
|
||||
// IPRoutesHandlerOption sets the IP routes for tun tunnel.
|
||||
func IPRoutesHandlerOption(routes ...IPRoute) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.IPRoutes = routes
|
||||
}
|
||||
}
|
||||
|
||||
type autoHandler struct {
|
||||
options *HandlerOptions
|
||||
}
|
||||
|
||||
// AutoHandler creates a server Handler for auto proxy server.
|
||||
func AutoHandler(opts ...HandlerOption) Handler {
|
||||
h := &autoHandler{}
|
||||
h.Init(opts...)
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *autoHandler) Init(options ...HandlerOption) {
|
||||
if h.options == nil {
|
||||
h.options = &HandlerOptions{}
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(h.options)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *autoHandler) Handle(conn net.Conn) {
|
||||
br := bufio.NewReader(conn)
|
||||
b, err := br.Peek(1)
|
||||
if err != nil {
|
||||
log.Logf("[auto] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
cc := &bufferdConn{Conn: conn, br: br}
|
||||
var handler Handler
|
||||
switch b[0] {
|
||||
case gosocks5.Ver5: // socks5
|
||||
handler = &socks5Handler{options: h.options}
|
||||
}
|
||||
handler.Init()
|
||||
handler.Handle(cc)
|
||||
}
|
||||
|
||||
type bufferdConn struct {
|
||||
net.Conn
|
||||
br *bufio.Reader
|
||||
}
|
||||
|
||||
func (c *bufferdConn) Read(b []byte) (int, error) {
|
||||
return c.br.Read(b)
|
||||
}
|
||||
|
||||
21
core/node.go
21
core/node.go
@@ -17,18 +17,14 @@ var (
|
||||
|
||||
// Node is a proxy node, mainly used to construct a proxy chain.
|
||||
type Node struct {
|
||||
Addr string
|
||||
Host string
|
||||
Protocol string
|
||||
Transport string
|
||||
Remote string // remote address, used by tcp/udp port forwarding
|
||||
url *url.URL // raw url
|
||||
User *url.Userinfo
|
||||
Values url.Values
|
||||
DialOptions []DialOption
|
||||
HandshakeOptions []HandshakeOption
|
||||
ConnectOptions []ConnectOption
|
||||
Client *Client
|
||||
Addr string
|
||||
Protocol string
|
||||
Transport string
|
||||
Remote string // remote address, used by tcp/udp port forwarding
|
||||
url *url.URL // raw url
|
||||
User *url.Userinfo
|
||||
Values url.Values
|
||||
Client *Client
|
||||
}
|
||||
|
||||
// ParseNode parses the node info.
|
||||
@@ -50,7 +46,6 @@ func ParseNode(s string) (node Node, err error) {
|
||||
|
||||
node = Node{
|
||||
Addr: u.Host,
|
||||
Host: u.Host,
|
||||
Remote: strings.Trim(u.EscapedPath(), "/"),
|
||||
Values: u.Query(),
|
||||
User: u.User,
|
||||
|
||||
@@ -154,37 +154,22 @@ func SOCKS5Connector(user *url.Userinfo) Connector {
|
||||
return &socks5Connector{User: user}
|
||||
}
|
||||
|
||||
func (c *socks5Connector) Connect(conn net.Conn, address string, options ...ConnectOption) (net.Conn, error) {
|
||||
return c.ConnectContext(context.Background(), conn, "tcp", address, options...)
|
||||
func (c *socks5Connector) Connect(conn net.Conn, address string) (net.Conn, error) {
|
||||
return c.ConnectContext(context.Background(), conn, "tcp", address)
|
||||
}
|
||||
|
||||
func (c *socks5Connector) ConnectContext(ctx context.Context, conn net.Conn, network, address string, options ...ConnectOption) (net.Conn, error) {
|
||||
func (c *socks5Connector) ConnectContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error) {
|
||||
switch network {
|
||||
case "udp", "udp4", "udp6":
|
||||
cnr := &socks5UDPTunConnector{User: c.User}
|
||||
return cnr.ConnectContext(ctx, conn, network, address, options...)
|
||||
return cnr.ConnectContext(ctx, conn, network, address)
|
||||
}
|
||||
|
||||
opts := &ConnectOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
|
||||
timeout := opts.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = ConnectTimeout
|
||||
}
|
||||
|
||||
conn.SetDeadline(time.Now().Add(timeout))
|
||||
conn.SetDeadline(time.Now().Add(ConnectTimeout))
|
||||
defer conn.SetDeadline(time.Time{})
|
||||
|
||||
user := opts.User
|
||||
if user == nil {
|
||||
user = c.User
|
||||
}
|
||||
cc, err := socks5Handshake(conn,
|
||||
selectorSocks5HandshakeOption(opts.Selector),
|
||||
userSocks5HandshakeOption(user),
|
||||
userSocks5HandshakeOption(c.User),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -219,7 +204,7 @@ func (c *socks5Connector) ConnectContext(ctx context.Context, conn net.Conn, net
|
||||
}
|
||||
|
||||
if reply.Rep != gosocks5.Succeeded {
|
||||
return nil, errors.New("Service unavailable")
|
||||
return nil, errors.New("service unavailable")
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
@@ -235,39 +220,16 @@ func SOCKS5UDPTunConnector(user *url.Userinfo) Connector {
|
||||
return &socks5UDPTunConnector{User: user}
|
||||
}
|
||||
|
||||
func (c *socks5UDPTunConnector) Connect(conn net.Conn, address string, options ...ConnectOption) (net.Conn, error) {
|
||||
return c.ConnectContext(context.Background(), conn, "udp", address, options...)
|
||||
}
|
||||
|
||||
func (c *socks5UDPTunConnector) ConnectContext(ctx context.Context, conn net.Conn, network, address string, options ...ConnectOption) (net.Conn, error) {
|
||||
func (c *socks5UDPTunConnector) ConnectContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error) {
|
||||
switch network {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
return nil, fmt.Errorf("%s unsupported", network)
|
||||
}
|
||||
|
||||
opts := &ConnectOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
|
||||
user := opts.User
|
||||
if user == nil {
|
||||
user = c.User
|
||||
}
|
||||
|
||||
timeout := opts.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = ConnectTimeout
|
||||
}
|
||||
conn.SetDeadline(time.Now().Add(timeout))
|
||||
conn.SetDeadline(time.Now().Add(ConnectTimeout))
|
||||
defer conn.SetDeadline(time.Time{})
|
||||
|
||||
taddr, _ := net.ResolveUDPAddr("udp", address)
|
||||
return newSocks5UDPTunnelConn(conn,
|
||||
nil, taddr,
|
||||
selectorSocks5HandshakeOption(opts.Selector),
|
||||
userSocks5HandshakeOption(user),
|
||||
)
|
||||
return newSocks5UDPTunnelConn(conn, nil, taddr, userSocks5HandshakeOption(c.User))
|
||||
}
|
||||
|
||||
type socks5Handler struct {
|
||||
@@ -344,9 +306,6 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
|
||||
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 err error
|
||||
var cc net.Conn
|
||||
@@ -368,9 +327,7 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
|
||||
fmt.Fprintf(&buf, "%s", host)
|
||||
log.Log("[route]", buf.String())
|
||||
|
||||
cc, err = route.Dial(host,
|
||||
TimeoutChainOption(h.options.Timeout),
|
||||
)
|
||||
cc, err = route.DialContext(context.Background(), "tcp", host)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
28
core/tcp.go
28
core/tcp.go
@@ -1,6 +1,8 @@
|
||||
package core
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// tcpTransporter is a raw TCP transporter.
|
||||
type tcpTransporter struct{}
|
||||
@@ -10,28 +12,8 @@ func TCPTransporter() Transporter {
|
||||
return &tcpTransporter{}
|
||||
}
|
||||
|
||||
func (tr *tcpTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||
opts := &DialOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
|
||||
timeout := opts.Timeout
|
||||
if timeout <= 0 {
|
||||
timeout = DialTimeout
|
||||
}
|
||||
if opts.Chain == nil {
|
||||
return net.DialTimeout("tcp", addr, timeout)
|
||||
}
|
||||
return opts.Chain.Dial(addr)
|
||||
}
|
||||
|
||||
func (tr *tcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (tr *tcpTransporter) Multiplex() bool {
|
||||
return false
|
||||
func (tr *tcpTransporter) Dial(addr string) (net.Conn, error) {
|
||||
return net.DialTimeout("tcp", addr, DialTimeout)
|
||||
}
|
||||
|
||||
type tcpListener struct {
|
||||
|
||||
13
core/tun.go
13
core/tun.go
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/shadowsocks/go-shadowsocks2/shadowaead"
|
||||
"github.com/songgao/water"
|
||||
"github.com/songgao/water/waterutil"
|
||||
"github.com/xtaci/tcpraw"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
@@ -181,16 +180,8 @@ func (h *tunHandler) Handle(conn net.Conn) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if h.options.TCPMode {
|
||||
if raddr != nil {
|
||||
pc, err = tcpraw.Dial("tcp", raddr.String())
|
||||
} else {
|
||||
pc, err = tcpraw.Listen("tcp", h.options.Node.Addr)
|
||||
}
|
||||
} else {
|
||||
laddr, _ := net.ResolveUDPAddr("udp", h.options.Node.Addr)
|
||||
pc, err = net.ListenUDP("udp", laddr)
|
||||
}
|
||||
laddr, _ := net.ResolveUDPAddr("udp", h.options.Node.Addr)
|
||||
pc, err = net.ListenUDP("udp", laddr)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
311
core/udp.go
311
core/udp.go
@@ -1,311 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
)
|
||||
|
||||
// UDPListenConfig is the config for UDP Listener.
|
||||
type UDPListenConfig struct {
|
||||
TTL time.Duration // timeout per connection
|
||||
Backlog int // connection backlog
|
||||
QueueSize int // recv queue size per connection
|
||||
}
|
||||
|
||||
type udpListener struct {
|
||||
ln net.PacketConn
|
||||
connChan chan net.Conn
|
||||
errChan chan error
|
||||
connMap *udpConnMap
|
||||
config *UDPListenConfig
|
||||
}
|
||||
|
||||
// UDPListener creates a Listener for UDP server.
|
||||
func UDPListener(addr string, cfg *UDPListenConfig) (Listener, error) {
|
||||
laddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ln, err := net.ListenUDP("udp", laddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg == nil {
|
||||
cfg = &UDPListenConfig{}
|
||||
}
|
||||
|
||||
backlog := cfg.Backlog
|
||||
if backlog <= 0 {
|
||||
backlog = defaultBacklog
|
||||
}
|
||||
|
||||
l := &udpListener{
|
||||
ln: ln,
|
||||
connChan: make(chan net.Conn, backlog),
|
||||
errChan: make(chan error, 1),
|
||||
connMap: new(udpConnMap),
|
||||
config: cfg,
|
||||
}
|
||||
go l.listenLoop()
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *udpListener) listenLoop() {
|
||||
for {
|
||||
// NOTE: this buffer will be released in the udpServerConn after read.
|
||||
b := MPool.Get().([]byte)
|
||||
|
||||
n, raddr, err := l.ln.ReadFrom(b)
|
||||
if err != nil {
|
||||
log.Logf("[udp] peer -> %s : %s", l.Addr(), err)
|
||||
l.Close()
|
||||
l.errChan <- err
|
||||
close(l.errChan)
|
||||
return
|
||||
}
|
||||
|
||||
conn, ok := l.connMap.Get(raddr.String())
|
||||
if !ok {
|
||||
conn = newUDPServerConn(l.ln, raddr, &udpServerConnConfig{
|
||||
ttl: l.config.TTL,
|
||||
qsize: l.config.QueueSize,
|
||||
onClose: func() {
|
||||
l.connMap.Delete(raddr.String())
|
||||
log.Logf("[udp] %s closed (%d)", raddr, l.connMap.Size())
|
||||
},
|
||||
})
|
||||
|
||||
select {
|
||||
case l.connChan <- conn:
|
||||
l.connMap.Set(raddr.String(), conn)
|
||||
log.Logf("[udp] %s -> %s (%d)", raddr, l.Addr(), l.connMap.Size())
|
||||
default:
|
||||
conn.Close()
|
||||
log.Logf("[udp] %s - %s: connection queue is full (%d)", raddr, l.Addr(), cap(l.connChan))
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case conn.rChan <- b[:n]:
|
||||
if Debug {
|
||||
log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n)
|
||||
}
|
||||
default:
|
||||
log.Logf("[udp] %s -> %s : recv queue is full (%d)", raddr, l.Addr(), cap(conn.rChan))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *udpListener) Accept() (conn net.Conn, err error) {
|
||||
var ok bool
|
||||
select {
|
||||
case conn = <-l.connChan:
|
||||
case err, ok = <-l.errChan:
|
||||
if !ok {
|
||||
err = errors.New("accpet on closed listener")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (l *udpListener) Addr() net.Addr {
|
||||
return l.ln.LocalAddr()
|
||||
}
|
||||
|
||||
func (l *udpListener) Close() error {
|
||||
err := l.ln.Close()
|
||||
l.connMap.Range(func(k interface{}, v *udpServerConn) bool {
|
||||
v.Close()
|
||||
return true
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type udpConnMap struct {
|
||||
size int64
|
||||
m sync.Map
|
||||
}
|
||||
|
||||
func (m *udpConnMap) Get(key interface{}) (conn *udpServerConn, ok bool) {
|
||||
v, ok := m.m.Load(key)
|
||||
if ok {
|
||||
conn, ok = v.(*udpServerConn)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *udpConnMap) Set(key interface{}, conn *udpServerConn) {
|
||||
m.m.Store(key, conn)
|
||||
atomic.AddInt64(&m.size, 1)
|
||||
}
|
||||
|
||||
func (m *udpConnMap) Delete(key interface{}) {
|
||||
m.m.Delete(key)
|
||||
atomic.AddInt64(&m.size, -1)
|
||||
}
|
||||
|
||||
func (m *udpConnMap) Range(f func(key interface{}, value *udpServerConn) bool) {
|
||||
m.m.Range(func(k, v interface{}) bool {
|
||||
return f(k, v.(*udpServerConn))
|
||||
})
|
||||
}
|
||||
|
||||
func (m *udpConnMap) Size() int64 {
|
||||
return atomic.LoadInt64(&m.size)
|
||||
}
|
||||
|
||||
// udpServerConn is a server side connection for UDP client peer, it implements net.Conn and net.PacketConn.
|
||||
type udpServerConn struct {
|
||||
conn net.PacketConn
|
||||
raddr net.Addr
|
||||
rChan chan []byte
|
||||
closed chan struct{}
|
||||
closeMutex sync.Mutex
|
||||
nopChan chan int
|
||||
config *udpServerConnConfig
|
||||
}
|
||||
|
||||
type udpServerConnConfig struct {
|
||||
ttl time.Duration
|
||||
qsize int
|
||||
onClose func()
|
||||
}
|
||||
|
||||
func newUDPServerConn(conn net.PacketConn, raddr net.Addr, cfg *udpServerConnConfig) *udpServerConn {
|
||||
if conn == nil || raddr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cfg == nil {
|
||||
cfg = &udpServerConnConfig{}
|
||||
}
|
||||
qsize := cfg.qsize
|
||||
if qsize <= 0 {
|
||||
qsize = defaultQueueSize
|
||||
}
|
||||
c := &udpServerConn{
|
||||
conn: conn,
|
||||
raddr: raddr,
|
||||
rChan: make(chan []byte, qsize),
|
||||
closed: make(chan struct{}),
|
||||
nopChan: make(chan int),
|
||||
config: cfg,
|
||||
}
|
||||
go c.ttlWait()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *udpServerConn) Read(b []byte) (n int, err error) {
|
||||
n, _, err = c.ReadFrom(b)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpServerConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||
select {
|
||||
case bb := <-c.rChan:
|
||||
n = copy(b, bb)
|
||||
if cap(bb) == mediumBufferSize {
|
||||
MPool.Put(bb[:cap(bb)])
|
||||
}
|
||||
case <-c.closed:
|
||||
err = errors.New("read from closed connection")
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case c.nopChan <- n:
|
||||
default:
|
||||
}
|
||||
|
||||
addr = c.raddr
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpServerConn) Write(b []byte) (n int, err error) {
|
||||
return c.WriteTo(b, c.raddr)
|
||||
}
|
||||
|
||||
func (c *udpServerConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
||||
n, err = c.conn.WriteTo(b, addr)
|
||||
|
||||
if n > 0 {
|
||||
if Debug {
|
||||
log.Logf("[udp] %s <<< %s : length %d", addr, c.LocalAddr(), n)
|
||||
}
|
||||
|
||||
select {
|
||||
case c.nopChan <- n:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *udpServerConn) Close() error {
|
||||
c.closeMutex.Lock()
|
||||
defer c.closeMutex.Unlock()
|
||||
|
||||
select {
|
||||
case <-c.closed:
|
||||
return errors.New("connection is closed")
|
||||
default:
|
||||
if c.config.onClose != nil {
|
||||
c.config.onClose()
|
||||
}
|
||||
close(c.closed)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *udpServerConn) ttlWait() {
|
||||
ttl := c.config.ttl
|
||||
if ttl == 0 {
|
||||
ttl = defaultTTL
|
||||
}
|
||||
timer := time.NewTimer(ttl)
|
||||
defer timer.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-c.nopChan:
|
||||
if !timer.Stop() {
|
||||
<-timer.C
|
||||
}
|
||||
timer.Reset(ttl)
|
||||
case <-timer.C:
|
||||
c.Close()
|
||||
return
|
||||
case <-c.closed:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *udpServerConn) LocalAddr() net.Addr {
|
||||
return c.conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (c *udpServerConn) RemoteAddr() net.Addr {
|
||||
return c.raddr
|
||||
}
|
||||
|
||||
func (c *udpServerConn) SetDeadline(t time.Time) error {
|
||||
return c.conn.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *udpServerConn) SetReadDeadline(t time.Time) error {
|
||||
return c.conn.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (c *udpServerConn) SetWriteDeadline(t time.Time) error {
|
||||
return c.conn.SetWriteDeadline(t)
|
||||
}
|
||||
44
pkg/route.go
44
pkg/route.go
@@ -45,34 +45,9 @@ func parseChainNode(ns string) (nodes []core.Node, err error) {
|
||||
if serverName == "" {
|
||||
serverName = "localhost" // default server name
|
||||
}
|
||||
timeout := node.GetDuration("timeout")
|
||||
|
||||
host := node.Get("host")
|
||||
if host == "" {
|
||||
host = node.Host
|
||||
}
|
||||
|
||||
node.DialOptions = append(node.DialOptions,
|
||||
core.TimeoutDialOption(timeout),
|
||||
core.HostDialOption(host),
|
||||
)
|
||||
|
||||
node.ConnectOptions = []core.ConnectOption{
|
||||
core.UserAgentConnectOption(node.Get("agent")),
|
||||
core.NoTLSConnectOption(node.GetBool("notls")),
|
||||
core.NoDelayConnectOption(node.GetBool("nodelay")),
|
||||
}
|
||||
|
||||
handshakeOptions := []core.HandshakeOption{
|
||||
core.AddrHandshakeOption(node.Addr),
|
||||
core.HostHandshakeOption(host),
|
||||
core.IntervalHandshakeOption(node.GetDuration("ping")),
|
||||
core.TimeoutHandshakeOption(timeout),
|
||||
core.RetryHandshakeOption(node.GetInt("retry")),
|
||||
}
|
||||
|
||||
node.Client = &core.Client{
|
||||
Connector: core.AutoConnector(node.User),
|
||||
Connector: core.SOCKS5UDPTunConnector(node.User),
|
||||
Transporter: core.TCPTransporter(),
|
||||
}
|
||||
|
||||
@@ -80,13 +55,10 @@ func parseChainNode(ns string) (nodes []core.Node, err error) {
|
||||
for _, ip := range ips {
|
||||
nd := node.Clone()
|
||||
nd.Addr = ip
|
||||
// override the default node address
|
||||
nd.HandshakeOptions = append(handshakeOptions, core.AddrHandshakeOption(ip))
|
||||
// One node per IP
|
||||
nodes = append(nodes, nd)
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
node.HandshakeOptions = handshakeOptions
|
||||
nodes = []core.Node{node}
|
||||
}
|
||||
|
||||
@@ -107,8 +79,6 @@ func (r *route) GenRouters() ([]router, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ttl := node.GetDuration("ttl")
|
||||
timeout := node.GetDuration("timeout")
|
||||
|
||||
tunRoutes := parseIPRoutes(node.Get("route"))
|
||||
gw := net.ParseIP(node.Get("gw")) // default gateway
|
||||
@@ -122,12 +92,6 @@ func (r *route) GenRouters() ([]router, error) {
|
||||
switch node.Transport {
|
||||
case "tcp":
|
||||
ln, err = core.TCPListener(node.Addr)
|
||||
case "udp":
|
||||
ln, err = core.UDPListener(node.Addr, &core.UDPListenConfig{
|
||||
TTL: ttl,
|
||||
Backlog: node.GetInt("backlog"),
|
||||
QueueSize: node.GetInt("queue"),
|
||||
})
|
||||
case "tun":
|
||||
cfg := core.TunConfig{
|
||||
Name: node.Get("name"),
|
||||
@@ -150,17 +114,13 @@ func (r *route) GenRouters() ([]router, error) {
|
||||
case "tun":
|
||||
handler = core.TunHandler()
|
||||
default:
|
||||
handler = core.AutoHandler()
|
||||
handler = core.SOCKS5Handler()
|
||||
}
|
||||
|
||||
handler.Init(
|
||||
core.AddrHandlerOption(ln.Addr().String()),
|
||||
core.ChainHandlerOption(chain),
|
||||
core.AuthenticatorHandlerOption(core.DefaultAuthenticator),
|
||||
core.RetryHandlerOption(node.GetInt("retry")),
|
||||
core.TimeoutHandlerOption(timeout),
|
||||
core.NodeHandlerOption(node),
|
||||
core.TCPModeHandlerOption(node.GetBool("tcp")),
|
||||
core.IPRoutesHandlerOption(tunRoutes...),
|
||||
)
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ func TestGetTopController(t *testing.T) {
|
||||
fmt.Println(controller.Scale)
|
||||
}
|
||||
|
||||
func TestDdp(t *testing.T) {
|
||||
func TestUdp(t *testing.T) {
|
||||
go func() {
|
||||
server()
|
||||
}()
|
||||
|
||||
Reference in New Issue
Block a user